Skip to content
Snippets Groups Projects
Commit 2e968fcb authored by Thomas Jahns's avatar Thomas Jahns :cartwheel: Committed by Sergey Kosukhin
Browse files

Replace loops with O(1) computation.

parent f1b4092e
No related branches found
No related tags found
No related merge requests found
......@@ -134,6 +134,7 @@ Makefile
/tests/test_cdf_read
/tests/test_cdf_write
/tests/test_grib
/tests/test_month_adjust
/tests/test_resource_copy
/tests/test_resource_copy_mpi
/tests/test_table
......
......@@ -6,6 +6,8 @@
// clang-format off
#include <stdlib.h>
#include "cdi.h"
#ifdef __cplusplus
......@@ -30,6 +32,20 @@ calendar_dpy(int calendar)
int days_per_year(int calendar, int year);
int days_per_month(int calendar, int year, int month);
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 };
}
#ifdef __cplusplus
}
#endif
......
......@@ -1035,10 +1035,9 @@ rtimeval2datetime(double timevalue, taxis_t *taxis)
month += nmon;
// clang-format off
while (month > 12) { month -= 12; year++; }
while (month < 1) { month += 12; year--; }
// clang-format on
struct yearMonth ym = normalize_month(year, month);
year = ym.year;
month = ym.month;
timeunits = TUNIT_DAY;
timevalue = fmon * days_per_month(calendar, year, month);
......@@ -1084,10 +1083,9 @@ datetime2rtimeval(CdiDateTime vDateTime, taxis_t *taxis)
int nmonth = (int) value;
month -= nmonth;
// clang-format off
while (month > 12) { month -= 12; year++; }
while (month < 1) { month += 12; year--; }
// clang-format on
struct yearMonth ym = normalize_month(year, month);
year = ym.year;
month = ym.month;
const int dpm = days_per_month(calendar, year, month);
......@@ -1267,10 +1265,9 @@ cdiSetForecastPeriod(double timevalue, taxis_t *taxis)
month -= nmon;
// clang-format off
while (month > 12) { month -= 12; year++; }
while (month < 1) { month += 12; year--; }
// clang-format on
struct yearMonth ym = normalize_month(year, month);
year = ym.year;
month = ym.month;
timeunits = TUNIT_DAY;
timevalue = fmon * days_per_month(calendar, year, month);
......
......@@ -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 \
......@@ -23,6 +24,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
......@@ -41,6 +43,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
......
#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