Skip to content
Snippets Groups Projects
Commit a56b8e14 authored by Thomas Jahns's avatar Thomas Jahns :cartwheel:
Browse files

Replace loops with O(1) computation.

parent a70eb18a
No related branches found
No related tags found
No related merge requests found
#ifndef _CALENDAR_H
#define _CALENDAR_H
#include <stdlib.h>
#include "cdi.h"
#ifdef __cplusplus
......@@ -30,6 +32,22 @@ int days_per_month(int calendar, int year, int month);
void cdi_decode_day(int dpy, int days, int *year, int *month, int *day);
int cdi_encode_day(int dpy, int year, int month, int day);
struct yearMonth
{
int year, month;
};
/* normalizes month to range [1,12] and adjusts year accordingly */
static inline struct yearMonth
normalize_month(int year, int month)
{
div_t modres = div(month-1, 12);
year += modres.quot - ((month < 1) & (modres.rem != 0));
return (struct yearMonth){ .year = year, .month = (modres.rem + 12)%12 + 1 };
}
#if defined (__cplusplus)
}
#endif
......
......@@ -1051,8 +1051,9 @@ void timeval2vtime(double timevalue, taxis_t *taxis, int *vdate, int *vtime)
month += nmon;
while ( month > 12 ) { month -= 12; year++; }
while ( month < 1 ) { month += 12; year--; }
struct yearMonth ym = normalize_month(year, month);
year = ym.year;
month = ym.month;
int dpm = days_per_month(calendar, year, month);
timeunit = TUNIT_DAY;
......@@ -1115,8 +1116,9 @@ double vtime2timeval(int vdate, int vtime, taxis_t *taxis)
int nmonth = (int) value;
month -= nmonth;
while ( month > 12 ) { month -= 12; year++; }
while ( month < 1 ) { month += 12; year--; }
struct yearMonth ym = normalize_month(year, month);
year = ym.year;
month = ym.month;
int dpm = days_per_month(calendar, year, month);
......@@ -1287,8 +1289,9 @@ void cdiSetForecastPeriod(double timevalue, taxis_t *taxis)
month -= nmon;
while ( month > 12 ) { month -= 12; year++; }
while ( month < 1 ) { month += 12; year--; }
struct yearMonth ym = normalize_month(year, month);
year = ym.year;
month = ym.month;
dpm = days_per_month(calendar, year, month);
timeunit = TUNIT_DAY;
......
......@@ -8,6 +8,7 @@ TESTS = cksum_verify \
test_cksum_service test_cksum_nc2 test_cksum_nc4 test_cksum_ieg \
test_chunk_cksum \
calendar_test1 \
test_month_adjust \
pio_write_run pio_cksum_mpinonb pio_cksum_fpguard \
pio_cksum_asynch pio_cksum_writer \
pio_cksum_cdf \
......@@ -21,6 +22,7 @@ TESTS = cksum_verify \
check_PROGRAMS = cksum_verify test_grib cksum_write cksum_read \
calendar_test1 \
test_month_adjust \
pio_write \
test_resource_copy cksum_write_chunk pio_write_deco2d test_table \
test_byteswap
......@@ -39,6 +41,7 @@ cksum_read_SOURCES = cksum_read.c \
stream_cksum.c stream_cksum.h \
ensure_array_size.h ensure_array_size.c
calendar_test1_SOURCES = calendar_test1.c
test_month_adjust_SOURCES = test_month_adjust.c
pio_write_SOURCES = pio_write.c pio_write.h simple_model.c \
simple_model_helper.h simple_model_helper.c \
pio_write_setup_grid.h pio_write_setup_grid.c
......
......@@ -80,19 +80,21 @@ host_triplet = @host@
TESTS = cksum_verify$(EXEEXT) test_cksum_grib test_cksum_grib2 \
test_cksum_nc test_cksum_extra test_cksum_service \
test_cksum_nc2 test_cksum_nc4 test_cksum_ieg test_chunk_cksum \
calendar_test1$(EXEEXT) pio_write_run pio_cksum_mpinonb \
pio_cksum_fpguard pio_cksum_asynch pio_cksum_writer \
pio_cksum_cdf pio_cksum_grb2 pio_cksum_mpi_fw_ordered \
pio_cksum_mpi_fw_at_all pio_cksum_mpi_fw_at_reblock \
test_resource_copy$(EXEEXT) pio_write_deco2d_run test_f2003 \
test_cdf_transformation test_cdf_const test_table$(EXEEXT) \
test_byteswap$(EXEEXT) $(am__append_2)
calendar_test1$(EXEEXT) test_month_adjust$(EXEEXT) \
pio_write_run pio_cksum_mpinonb pio_cksum_fpguard \
pio_cksum_asynch pio_cksum_writer pio_cksum_cdf pio_cksum_grb2 \
pio_cksum_mpi_fw_ordered pio_cksum_mpi_fw_at_all \
pio_cksum_mpi_fw_at_reblock test_resource_copy$(EXEEXT) \
pio_write_deco2d_run test_f2003 test_cdf_transformation \
test_cdf_const test_table$(EXEEXT) test_byteswap$(EXEEXT) \
$(am__append_2)
check_PROGRAMS = cksum_verify$(EXEEXT) test_grib$(EXEEXT) \
cksum_write$(EXEEXT) cksum_read$(EXEEXT) \
calendar_test1$(EXEEXT) pio_write$(EXEEXT) \
test_resource_copy$(EXEEXT) cksum_write_chunk$(EXEEXT) \
pio_write_deco2d$(EXEEXT) test_table$(EXEEXT) \
test_byteswap$(EXEEXT) $(am__EXEEXT_1) $(am__EXEEXT_2)
calendar_test1$(EXEEXT) test_month_adjust$(EXEEXT) \
pio_write$(EXEEXT) test_resource_copy$(EXEEXT) \
cksum_write_chunk$(EXEEXT) pio_write_deco2d$(EXEEXT) \
test_table$(EXEEXT) test_byteswap$(EXEEXT) $(am__EXEEXT_1) \
$(am__EXEEXT_2)
@ENABLE_NETCDF_TRUE@am__append_1 = test_cdf_write test_cdf_read
@USE_MPI_TRUE@am__append_2 = test_resource_copy_mpi_run
@USE_MPI_TRUE@am__append_3 = test_resource_copy_mpi
......@@ -162,8 +164,8 @@ CONFIG_CLEAN_VPATH_FILES =
@ENABLE_NETCDF_TRUE@am__EXEEXT_1 = test_cdf_write$(EXEEXT) \
@ENABLE_NETCDF_TRUE@ test_cdf_read$(EXEEXT)
@USE_MPI_TRUE@am__EXEEXT_2 = test_resource_copy_mpi$(EXEEXT)
calendar_test1_SOURCES = calendar_test1.c
calendar_test1_OBJECTS = calendar_test1.$(OBJEXT)
am_calendar_test1_OBJECTS = calendar_test1.$(OBJEXT)
calendar_test1_OBJECTS = $(am_calendar_test1_OBJECTS)
calendar_test1_LDADD = $(LDADD)
calendar_test1_DEPENDENCIES = ../src/libcdi.la
AM_V_lt = $(am__v_lt_@AM_V@)
......@@ -223,6 +225,10 @@ am_test_grib_OBJECTS = test_grib.$(OBJEXT)
test_grib_OBJECTS = $(am_test_grib_OBJECTS)
test_grib_LDADD = $(LDADD)
test_grib_DEPENDENCIES = ../src/libcdi.la
am_test_month_adjust_OBJECTS = test_month_adjust.$(OBJEXT)
test_month_adjust_OBJECTS = $(am_test_month_adjust_OBJECTS)
test_month_adjust_LDADD = $(LDADD)
test_month_adjust_DEPENDENCIES = ../src/libcdi.la
am_test_resource_copy_OBJECTS = test_resource_copy.$(OBJEXT)
test_resource_copy_OBJECTS = $(am_test_resource_copy_OBJECTS)
test_resource_copy_DEPENDENCIES = $(am__DEPENDENCIES_2) \
......@@ -272,19 +278,21 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = calendar_test1.c $(cksum_read_SOURCES) \
SOURCES = $(calendar_test1_SOURCES) $(cksum_read_SOURCES) \
$(cksum_verify_SOURCES) $(cksum_write_SOURCES) \
$(cksum_write_chunk_SOURCES) $(pio_write_SOURCES) \
$(pio_write_deco2d_SOURCES) $(test_byteswap_SOURCES) \
$(test_cdf_read_SOURCES) $(test_cdf_write_SOURCES) \
$(test_grib_SOURCES) $(test_resource_copy_SOURCES) \
$(test_grib_SOURCES) $(test_month_adjust_SOURCES) \
$(test_resource_copy_SOURCES) \
$(test_resource_copy_mpi_SOURCES) $(test_table_SOURCES)
DIST_SOURCES = calendar_test1.c $(cksum_read_SOURCES) \
DIST_SOURCES = $(calendar_test1_SOURCES) $(cksum_read_SOURCES) \
$(cksum_verify_SOURCES) $(cksum_write_SOURCES) \
$(cksum_write_chunk_SOURCES) $(pio_write_SOURCES) \
$(pio_write_deco2d_SOURCES) $(test_byteswap_SOURCES) \
$(test_cdf_read_SOURCES) $(test_cdf_write_SOURCES) \
$(test_grib_SOURCES) $(test_resource_copy_SOURCES) \
$(test_grib_SOURCES) $(test_month_adjust_SOURCES) \
$(test_resource_copy_SOURCES) \
$(test_resource_copy_mpi_SOURCES) $(test_table_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
......@@ -528,7 +536,8 @@ cksum_read_SOURCES = cksum_read.c \
stream_cksum.c stream_cksum.h \
ensure_array_size.h ensure_array_size.c
calendar_tes1_SOURCES = calendar_test1.c
calendar_test1_SOURCES = calendar_test1.c
test_month_adjust_SOURCES = test_month_adjust.c
pio_write_SOURCES = pio_write.c pio_write.h simple_model.c \
simple_model_helper.h simple_model_helper.c \
pio_write_setup_grid.h pio_write_setup_grid.c
......@@ -701,6 +710,10 @@ test_grib$(EXEEXT): $(test_grib_OBJECTS) $(test_grib_DEPENDENCIES) $(EXTRA_test_
@rm -f test_grib$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(test_grib_OBJECTS) $(test_grib_LDADD) $(LIBS)
test_month_adjust$(EXEEXT): $(test_month_adjust_OBJECTS) $(test_month_adjust_DEPENDENCIES) $(EXTRA_test_month_adjust_DEPENDENCIES)
@rm -f test_month_adjust$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(test_month_adjust_OBJECTS) $(test_month_adjust_LDADD) $(LIBS)
test_resource_copy$(EXEEXT): $(test_resource_copy_OBJECTS) $(test_resource_copy_DEPENDENCIES) $(EXTRA_test_resource_copy_DEPENDENCIES)
@rm -f test_resource_copy$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(test_resource_copy_OBJECTS) $(test_resource_copy_LDADD) $(LIBS)
......@@ -735,6 +748,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_cdf_read.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_cdf_write.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_grib.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_month_adjust.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_resource_copy.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_resource_copy_mpi-test_resource_copy.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_table.Po@am__quote@
......
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include "calendar.h"
int main(void)
{
static const int vals[] = { -12, -17, 17, 11, -769652651 };
enum { numVals = sizeof (vals) / sizeof (vals[0]) };
for (size_t i = 0; i < numVals; ++i) {
enum { startYear = 1900 };
int month = vals[i];
struct yearMonth ym = normalize_month(startYear, month);
if ((long)ym.year * 12 + ym.month != (long)startYear * 12 + month) {
fprintf(stderr, "problem: month=%d, ym.month=%d, ym.year=%d\n"
"(long)ym.year * 12 + ym.month = %ld\n"
"(long)startYear * 12 + month = %ld\n",
month, ym.month, ym.year,
(long)ym.year * 12 + ym.month,
(long)startYear * 12 + month);
abort();
}
}
{
struct timeval tv;
if (gettimeofday(&tv, NULL)) {
perror("failed to get time for random number generator initialization");
exit(EXIT_FAILURE);
}
srandom((unsigned)(tv.tv_sec ^ tv.tv_usec));
}
for (size_t j = 0; j < 1000000; ++j) {
int year = (int)(random() - RAND_MAX/2),
month = (int)(random() - RAND_MAX/2);
struct yearMonth ym = normalize_month(year, month);
if ((long)ym.year * 12 + ym.month != (long)year * 12 + month) {
fprintf(stderr, "problem: month=%d, ym.month=%d, ym.year=%d\n"
"(long)ym.year * 12 + ym.month = %ld\n"
"(long)year * 12 + month = %ld\n",
month, ym.month, ym.year,
(long)ym.year * 12 + ym.month,
(long)year * 12 + month);
abort();
}
}
return EXIT_SUCCESS;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment