Home | History | Annotate | Line # | Download | only in libntp
      1  1.11  christos /*	$NetBSD: ntp_calendar.c,v 1.12 2024/08/18 20:47:13 christos Exp $	*/
      2   1.1  christos 
      3   1.1  christos /*
      4   1.1  christos  * ntp_calendar.c - calendar and helper functions
      5   1.1  christos  *
      6   1.1  christos  * Written by Juergen Perlinger (perlinger (at) ntp.org) for the NTP project.
      7   1.1  christos  * The contents of 'html/copyright.html' apply.
      8   1.7  christos  *
      9   1.7  christos  * --------------------------------------------------------------------
     10   1.7  christos  * Some notes on the implementation:
     11   1.7  christos  *
     12   1.7  christos  * Calendar algorithms thrive on the division operation, which is one of
     13   1.7  christos  * the slowest numerical operations in any CPU. What saves us here from
     14   1.7  christos  * abysmal performance is the fact that all divisions are divisions by
     15   1.7  christos  * constant numbers, and most compilers can do this by a multiplication
     16   1.7  christos  * operation.  But this might not work when using the div/ldiv/lldiv
     17   1.7  christos  * function family, because many compilers are not able to do inline
     18   1.7  christos  * expansion of the code with following optimisation for the
     19   1.7  christos  * constant-divider case.
     20   1.7  christos  *
     21   1.7  christos  * Also div/ldiv/lldiv are defined in terms of int/long/longlong, which
     22   1.7  christos  * are inherently target dependent. Nothing that could not be cured with
     23   1.7  christos  * autoconf, but still a mess...
     24   1.7  christos  *
     25   1.7  christos  * Furthermore, we need floor division in many places. C either leaves
     26   1.7  christos  * the division behaviour undefined (< C99) or demands truncation to
     27   1.7  christos  * zero (>= C99), so additional steps are required to make sure the
     28   1.7  christos  * algorithms work. The {l,ll}div function family is requested to
     29   1.7  christos  * truncate towards zero, which is also the wrong direction for our
     30   1.7  christos  * purpose.
     31   1.7  christos  *
     32   1.7  christos  * For all this, all divisions by constant are coded manually, even when
     33   1.7  christos  * there is a joined div/mod operation: The optimiser should sort that
     34   1.7  christos  * out, if possible. Most of the calculations are done with unsigned
     35   1.7  christos  * types, explicitely using two's complement arithmetics where
     36   1.7  christos  * necessary. This minimises the dependecies to compiler and target,
     37   1.7  christos  * while still giving reasonable to good performance.
     38   1.7  christos  *
     39   1.7  christos  * The implementation uses a few tricks that exploit properties of the
     40   1.7  christos  * two's complement: Floor division on negative dividents can be
     41   1.7  christos  * executed by using the one's complement of the divident. One's
     42   1.7  christos  * complement can be easily created using XOR and a mask.
     43   1.7  christos  *
     44   1.7  christos  * Finally, check for overflow conditions is minimal. There are only two
     45  1.11  christos  * calculation steps in the whole calendar that potentially suffer from
     46  1.11  christos  * an internal overflow, and these are coded in a way that avoids
     47  1.11  christos  * it. All other functions do not suffer from internal overflow and
     48  1.11  christos  * simply return the result truncated to 32 bits.
     49   1.1  christos  */
     50   1.7  christos 
     51   1.1  christos #include <config.h>
     52   1.1  christos #include <sys/types.h>
     53   1.1  christos 
     54   1.1  christos #include "ntp_types.h"
     55   1.1  christos #include "ntp_calendar.h"
     56   1.1  christos #include "ntp_stdlib.h"
     57   1.1  christos #include "ntp_fp.h"
     58   1.1  christos #include "ntp_unixtime.h"
     59   1.1  christos 
     60  1.11  christos #include "ntpd.h"
     61  1.11  christos 
     62   1.7  christos /* For now, let's take the conservative approach: if the target property
     63   1.7  christos  * macros are not defined, check a few well-known compiler/architecture
     64   1.7  christos  * settings. Default is to assume that the representation of signed
     65   1.7  christos  * integers is unknown and shift-arithmetic-right is not available.
     66   1.7  christos  */
     67   1.7  christos #ifndef TARGET_HAS_2CPL
     68   1.7  christos # if defined(__GNUC__)
     69   1.7  christos #  if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
     70   1.7  christos #   define TARGET_HAS_2CPL 1
     71   1.7  christos #  else
     72   1.7  christos #   define TARGET_HAS_2CPL 0
     73   1.7  christos #  endif
     74   1.7  christos # elif defined(_MSC_VER)
     75   1.7  christos #  if defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM)
     76   1.7  christos #   define TARGET_HAS_2CPL 1
     77   1.7  christos #  else
     78   1.7  christos #   define TARGET_HAS_2CPL 0
     79   1.7  christos #  endif
     80   1.7  christos # else
     81   1.7  christos #  define TARGET_HAS_2CPL 0
     82   1.7  christos # endif
     83   1.7  christos #endif
     84   1.7  christos 
     85   1.7  christos #ifndef TARGET_HAS_SAR
     86   1.7  christos # define TARGET_HAS_SAR 0
     87   1.7  christos #endif
     88   1.7  christos 
     89  1.11  christos #if !defined(HAVE_64BITREGS) && defined(UINT64_MAX) && (SIZE_MAX >= UINT64_MAX)
     90  1.11  christos # define HAVE_64BITREGS
     91  1.11  christos #endif
     92  1.11  christos 
     93   1.1  christos /*
     94   1.1  christos  *---------------------------------------------------------------------
     95   1.1  christos  * replacing the 'time()' function
     96   1.9  christos  *---------------------------------------------------------------------
     97   1.1  christos  */
     98   1.1  christos 
     99   1.1  christos static systime_func_ptr systime_func = &time;
    100   1.1  christos static inline time_t now(void);
    101   1.1  christos 
    102   1.1  christos 
    103   1.1  christos systime_func_ptr
    104   1.1  christos ntpcal_set_timefunc(
    105   1.1  christos 	systime_func_ptr nfunc
    106   1.1  christos 	)
    107   1.1  christos {
    108   1.1  christos 	systime_func_ptr res;
    109   1.5  christos 
    110   1.1  christos 	res = systime_func;
    111   1.1  christos 	if (NULL == nfunc)
    112   1.1  christos 		nfunc = &time;
    113   1.1  christos 	systime_func = nfunc;
    114   1.1  christos 
    115   1.1  christos 	return res;
    116   1.1  christos }
    117   1.1  christos 
    118   1.1  christos 
    119   1.1  christos static inline time_t
    120   1.1  christos now(void)
    121   1.1  christos {
    122   1.1  christos 	return (*systime_func)(NULL);
    123   1.1  christos }
    124   1.1  christos 
    125   1.1  christos /*
    126   1.1  christos  *---------------------------------------------------------------------
    127   1.7  christos  * Get sign extension mask and unsigned 2cpl rep for a signed integer
    128   1.7  christos  *---------------------------------------------------------------------
    129   1.7  christos  */
    130   1.7  christos 
    131   1.7  christos static inline uint32_t
    132   1.7  christos int32_sflag(
    133   1.7  christos 	const int32_t v)
    134   1.7  christos {
    135   1.7  christos #   if TARGET_HAS_2CPL && TARGET_HAS_SAR && SIZEOF_INT >= 4
    136   1.7  christos 
    137   1.7  christos 	/* Let's assume that shift is the fastest way to get the sign
    138   1.7  christos 	 * extension of of a signed integer. This might not always be
    139   1.7  christos 	 * true, though -- On 8bit CPUs or machines without barrel
    140   1.7  christos 	 * shifter this will kill the performance. So we make sure
    141   1.7  christos 	 * we do this only if 'int' has at least 4 bytes.
    142   1.7  christos 	 */
    143   1.7  christos 	return (uint32_t)(v >> 31);
    144  1.11  christos 
    145   1.7  christos #   else
    146   1.7  christos 
    147   1.7  christos 	/* This should be a rather generic approach for getting a sign
    148   1.7  christos 	 * extension mask...
    149   1.7  christos 	 */
    150   1.7  christos 	return UINT32_C(0) - (uint32_t)(v < 0);
    151   1.7  christos 
    152   1.7  christos #   endif
    153   1.7  christos }
    154   1.7  christos 
    155   1.7  christos static inline int32_t
    156   1.7  christos uint32_2cpl_to_int32(
    157   1.7  christos 	const uint32_t vu)
    158   1.7  christos {
    159   1.7  christos 	int32_t v;
    160  1.11  christos 
    161   1.7  christos #   if TARGET_HAS_2CPL
    162   1.7  christos 
    163   1.7  christos 	/* Just copy through the 32 bits from the unsigned value if
    164   1.7  christos 	 * we're on a two's complement target.
    165   1.7  christos 	 */
    166   1.7  christos 	v = (int32_t)vu;
    167   1.7  christos 
    168   1.7  christos #   else
    169   1.7  christos 
    170   1.7  christos 	/* Convert to signed integer, making sure signed integer
    171   1.7  christos 	 * overflow cannot happen. Again, the optimiser might or might
    172   1.7  christos 	 * not find out that this is just a copy of 32 bits on a target
    173   1.7  christos 	 * with two's complement representation for signed integers.
    174   1.7  christos 	 */
    175   1.7  christos 	if (vu > INT32_MAX)
    176   1.7  christos 		v = -(int32_t)(~vu) - 1;
    177   1.7  christos 	else
    178   1.7  christos 		v = (int32_t)vu;
    179  1.11  christos 
    180   1.7  christos #   endif
    181  1.11  christos 
    182   1.7  christos 	return v;
    183   1.7  christos }
    184   1.7  christos 
    185   1.7  christos /*
    186   1.7  christos  *---------------------------------------------------------------------
    187   1.1  christos  * Convert between 'time_t' and 'vint64'
    188   1.1  christos  *---------------------------------------------------------------------
    189   1.1  christos  */
    190   1.1  christos vint64
    191   1.1  christos time_to_vint64(
    192   1.1  christos 	const time_t * ptt
    193   1.1  christos 	)
    194   1.1  christos {
    195   1.1  christos 	vint64 res;
    196   1.1  christos 	time_t tt;
    197   1.1  christos 
    198   1.1  christos 	tt = *ptt;
    199   1.1  christos 
    200   1.7  christos #   if SIZEOF_TIME_T <= 4
    201   1.1  christos 
    202   1.1  christos 	res.D_s.hi = 0;
    203   1.1  christos 	if (tt < 0) {
    204   1.1  christos 		res.D_s.lo = (uint32_t)-tt;
    205   1.1  christos 		M_NEG(res.D_s.hi, res.D_s.lo);
    206   1.1  christos 	} else {
    207   1.1  christos 		res.D_s.lo = (uint32_t)tt;
    208   1.1  christos 	}
    209   1.1  christos 
    210   1.7  christos #   elif defined(HAVE_INT64)
    211   1.1  christos 
    212   1.1  christos 	res.q_s = tt;
    213   1.1  christos 
    214   1.7  christos #   else
    215   1.1  christos 	/*
    216   1.1  christos 	 * shifting negative signed quantities is compiler-dependent, so
    217   1.1  christos 	 * we better avoid it and do it all manually. And shifting more
    218   1.1  christos 	 * than the width of a quantity is undefined. Also a don't do!
    219   1.1  christos 	 */
    220   1.1  christos 	if (tt < 0) {
    221   1.1  christos 		tt = -tt;
    222   1.1  christos 		res.D_s.lo = (uint32_t)tt;
    223   1.1  christos 		res.D_s.hi = (uint32_t)(tt >> 32);
    224   1.1  christos 		M_NEG(res.D_s.hi, res.D_s.lo);
    225   1.1  christos 	} else {
    226   1.1  christos 		res.D_s.lo = (uint32_t)tt;
    227   1.1  christos 		res.D_s.hi = (uint32_t)(tt >> 32);
    228   1.1  christos 	}
    229   1.1  christos 
    230   1.7  christos #   endif
    231   1.1  christos 
    232   1.1  christos 	return res;
    233   1.1  christos }
    234   1.1  christos 
    235   1.1  christos 
    236   1.1  christos time_t
    237   1.1  christos vint64_to_time(
    238   1.1  christos 	const vint64 *tv
    239   1.1  christos 	)
    240   1.1  christos {
    241   1.1  christos 	time_t res;
    242   1.1  christos 
    243   1.7  christos #   if SIZEOF_TIME_T <= 4
    244   1.1  christos 
    245   1.1  christos 	res = (time_t)tv->D_s.lo;
    246   1.1  christos 
    247   1.7  christos #   elif defined(HAVE_INT64)
    248   1.1  christos 
    249   1.1  christos 	res = (time_t)tv->q_s;
    250   1.1  christos 
    251   1.7  christos #   else
    252   1.1  christos 
    253   1.1  christos 	res = ((time_t)tv->d_s.hi << 32) | tv->D_s.lo;
    254   1.1  christos 
    255   1.7  christos #   endif
    256   1.1  christos 
    257   1.1  christos 	return res;
    258   1.5  christos }
    259   1.1  christos 
    260   1.1  christos /*
    261   1.1  christos  *---------------------------------------------------------------------
    262   1.1  christos  * Get the build date & time
    263   1.1  christos  *---------------------------------------------------------------------
    264   1.1  christos  */
    265   1.1  christos int
    266   1.1  christos ntpcal_get_build_date(
    267   1.1  christos 	struct calendar * jd
    268   1.1  christos 	)
    269   1.1  christos {
    270   1.1  christos 	/* The C standard tells us the format of '__DATE__':
    271   1.1  christos 	 *
    272   1.1  christos 	 * __DATE__ The date of translation of the preprocessing
    273   1.1  christos 	 * translation unit: a character string literal of the form "Mmm
    274   1.1  christos 	 * dd yyyy", where the names of the months are the same as those
    275   1.1  christos 	 * generated by the asctime function, and the first character of
    276   1.1  christos 	 * dd is a space character if the value is less than 10. If the
    277   1.1  christos 	 * date of translation is not available, an
    278   1.1  christos 	 * implementation-defined valid date shall be supplied.
    279   1.1  christos 	 *
    280   1.1  christos 	 * __TIME__ The time of translation of the preprocessing
    281   1.1  christos 	 * translation unit: a character string literal of the form
    282   1.1  christos 	 * "hh:mm:ss" as in the time generated by the asctime
    283   1.1  christos 	 * function. If the time of translation is not available, an
    284   1.1  christos 	 * implementation-defined valid time shall be supplied.
    285   1.1  christos 	 *
    286   1.1  christos 	 * Note that MSVC declares DATE and TIME to be in the local time
    287   1.1  christos 	 * zone, while neither the C standard nor the GCC docs make any
    288   1.1  christos 	 * statement about this. As a result, we may be +/-12hrs off
    289  1.11  christos 	 * UTC.	 But for practical purposes, this should not be a
    290   1.1  christos 	 * problem.
    291   1.1  christos 	 *
    292   1.1  christos 	 */
    293   1.7  christos #   ifdef MKREPRO_DATE
    294   1.3       apb 	static const char build[] = MKREPRO_TIME "/" MKREPRO_DATE;
    295   1.7  christos #   else
    296   1.1  christos 	static const char build[] = __TIME__ "/" __DATE__;
    297   1.7  christos #   endif
    298   1.1  christos 	static const char mlist[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
    299   1.4  christos 
    300   1.1  christos 	char		  monstr[4];
    301   1.1  christos 	const char *	  cp;
    302   1.1  christos 	unsigned short	  hour, minute, second, day, year;
    303  1.11  christos 	/* Note: The above quantities are used for sscanf 'hu' format,
    304   1.1  christos 	 * so using 'uint16_t' is contra-indicated!
    305   1.1  christos 	 */
    306   1.4  christos 
    307   1.7  christos #   ifdef DEBUG
    308  1.11  christos 	static int	  ignore  = 0;
    309   1.7  christos #   endif
    310   1.5  christos 
    311   1.1  christos 	ZERO(*jd);
    312   1.1  christos 	jd->year     = 1970;
    313   1.1  christos 	jd->month    = 1;
    314   1.1  christos 	jd->monthday = 1;
    315   1.1  christos 
    316   1.7  christos #   ifdef DEBUG
    317   1.4  christos 	/* check environment if build date should be ignored */
    318   1.4  christos 	if (0 == ignore) {
    319   1.4  christos 	    const char * envstr;
    320   1.4  christos 	    envstr = getenv("NTPD_IGNORE_BUILD_DATE");
    321   1.4  christos 	    ignore = 1 + (envstr && (!*envstr || !strcasecmp(envstr, "yes")));
    322   1.4  christos 	}
    323   1.4  christos 	if (ignore > 1)
    324   1.4  christos 	    return FALSE;
    325   1.7  christos #   endif
    326   1.4  christos 
    327   1.1  christos 	if (6 == sscanf(build, "%hu:%hu:%hu/%3s %hu %hu",
    328   1.1  christos 			&hour, &minute, &second, monstr, &day, &year)) {
    329   1.1  christos 		cp = strstr(mlist, monstr);
    330   1.1  christos 		if (NULL != cp) {
    331   1.1  christos 			jd->year     = year;
    332   1.1  christos 			jd->month    = (uint8_t)((cp - mlist) / 3 + 1);
    333   1.1  christos 			jd->monthday = (uint8_t)day;
    334   1.1  christos 			jd->hour     = (uint8_t)hour;
    335   1.1  christos 			jd->minute   = (uint8_t)minute;
    336   1.1  christos 			jd->second   = (uint8_t)second;
    337   1.1  christos 
    338   1.1  christos 			return TRUE;
    339   1.1  christos 		}
    340   1.1  christos 	}
    341   1.1  christos 
    342   1.1  christos 	return FALSE;
    343   1.1  christos }
    344   1.1  christos 
    345   1.1  christos 
    346   1.1  christos /*
    347   1.1  christos  *---------------------------------------------------------------------
    348   1.1  christos  * basic calendar stuff
    349   1.9  christos  *---------------------------------------------------------------------
    350   1.1  christos  */
    351   1.1  christos 
    352   1.1  christos /*
    353   1.1  christos  * Some notes on the terminology:
    354   1.1  christos  *
    355   1.1  christos  * We use the proleptic Gregorian calendar, which is the Gregorian
    356   1.1  christos  * calendar extended in both directions ad infinitum. This totally
    357   1.1  christos  * disregards the fact that this calendar was invented in 1582, and
    358   1.1  christos  * was adopted at various dates over the world; sometimes even after
    359   1.1  christos  * the start of the NTP epoch.
    360   1.1  christos  *
    361   1.1  christos  * Normally date parts are given as current cycles, while time parts
    362   1.1  christos  * are given as elapsed cycles:
    363   1.1  christos  *
    364   1.1  christos  * 1970-01-01/03:04:05 means 'IN the 1970st. year, IN the first month,
    365   1.1  christos  * ON the first day, with 3hrs, 4minutes and 5 seconds elapsed.
    366   1.1  christos  *
    367   1.1  christos  * The basic calculations for this calendar implementation deal with
    368   1.1  christos  * ELAPSED date units, which is the number of full years, full months
    369   1.1  christos  * and full days before a date: 1970-01-01 would be (1969, 0, 0) in
    370   1.1  christos  * that notation.
    371   1.1  christos  *
    372   1.1  christos  * To ease the numeric computations, month and day values outside the
    373   1.1  christos  * normal range are acceptable: 2001-03-00 will be treated as the day
    374   1.1  christos  * before 2001-03-01, 2000-13-32 will give the same result as
    375   1.1  christos  * 2001-02-01 and so on.
    376   1.1  christos  *
    377   1.1  christos  * 'rd' or 'RD' is used as an abbreviation for the latin 'rata die'
    378   1.1  christos  * (day number).  This is the number of days elapsed since 0000-12-31
    379   1.1  christos  * in the proleptic Gregorian calendar. The begin of the Christian Era
    380   1.1  christos  * (0001-01-01) is RD(1).
    381   1.1  christos  */
    382   1.1  christos 
    383   1.1  christos /*
    384   1.9  christos  * ====================================================================
    385   1.1  christos  *
    386   1.1  christos  * General algorithmic stuff
    387   1.1  christos  *
    388   1.9  christos  * ====================================================================
    389   1.1  christos  */
    390   1.1  christos 
    391   1.1  christos /*
    392   1.1  christos  *---------------------------------------------------------------------
    393  1.11  christos  * fast modulo 7 operations (floor/mathematical convention)
    394  1.11  christos  *---------------------------------------------------------------------
    395  1.11  christos  */
    396  1.11  christos int
    397  1.11  christos u32mod7(
    398  1.11  christos 	uint32_t x
    399  1.11  christos 	)
    400  1.11  christos {
    401  1.11  christos 	/* This is a combination of tricks from "Hacker's Delight" with
    402  1.11  christos 	 * some modifications, like a multiplication that rounds up to
    403  1.11  christos 	 * drop the final adjustment stage.
    404  1.11  christos 	 *
    405  1.11  christos 	 * Do a partial reduction by digit sum to keep the value in the
    406  1.11  christos 	 * range permitted for the mul/shift stage. There are several
    407  1.11  christos 	 * possible and absolutely equivalent shift/mask combinations;
    408  1.11  christos 	 * this one is ARM-friendly because of a mask that fits into 16
    409  1.11  christos 	 * bit.
    410  1.11  christos 	 */
    411  1.11  christos 	x = (x >> 15) + (x & UINT32_C(0x7FFF));
    412  1.11  christos 	/* Take reminder as (mod 8) by mul/shift. Since the multiplier
    413  1.11  christos 	 * was calculated using ceil() instead of floor(), it skips the
    414  1.11  christos 	 * value '7' properly.
    415  1.11  christos 	 *    M <- ceil(ldexp(8/7, 29))
    416  1.11  christos 	 */
    417  1.11  christos 	return (int)((x * UINT32_C(0x24924925)) >> 29);
    418  1.11  christos }
    419  1.11  christos 
    420  1.11  christos int
    421  1.11  christos i32mod7(
    422  1.11  christos 	int32_t x
    423  1.11  christos 	)
    424  1.11  christos {
    425  1.11  christos 	/* We add (2**32 - 2**32 % 7), which is (2**32 - 4), to negative
    426  1.11  christos 	 * numbers to map them into the postive range. Only the term '-4'
    427  1.11  christos 	 * survives, obviously.
    428  1.11  christos 	 */
    429  1.11  christos 	uint32_t ux = (uint32_t)x;
    430  1.11  christos 	return u32mod7((x < 0) ? (ux - 4u) : ux);
    431  1.11  christos }
    432  1.11  christos 
    433  1.11  christos uint32_t
    434  1.11  christos i32fmod(
    435  1.11  christos 	int32_t	 x,
    436  1.11  christos 	uint32_t d
    437  1.11  christos 	)
    438  1.11  christos {
    439  1.11  christos 	uint32_t ux = (uint32_t)x;
    440  1.11  christos 	uint32_t sf = UINT32_C(0) - (x < 0);
    441  1.11  christos 	ux = (sf ^ ux ) % d;
    442  1.11  christos 	return (d & sf) + (sf ^ ux);
    443  1.11  christos }
    444  1.11  christos 
    445  1.11  christos /*
    446  1.11  christos  *---------------------------------------------------------------------
    447   1.1  christos  * Do a periodic extension of 'value' around 'pivot' with a period of
    448   1.1  christos  * 'cycle'.
    449   1.1  christos  *
    450   1.1  christos  * The result 'res' is a number that holds to the following properties:
    451   1.1  christos  *
    452   1.1  christos  *   1)	 res MOD cycle == value MOD cycle
    453   1.1  christos  *   2)	 pivot <= res < pivot + cycle
    454   1.1  christos  *	 (replace </<= with >/>= for negative cycles)
    455   1.1  christos  *
    456   1.1  christos  * where 'MOD' denotes the modulo operator for FLOOR DIVISION, which
    457   1.1  christos  * is not the same as the '%' operator in C: C requires division to be
    458   1.1  christos  * a truncated division, where remainder and dividend have the same
    459   1.1  christos  * sign if the remainder is not zero, whereas floor division requires
    460   1.1  christos  * divider and modulus to have the same sign for a non-zero modulus.
    461   1.1  christos  *
    462   1.1  christos  * This function has some useful applications:
    463   1.1  christos  *
    464   1.1  christos  * + let Y be a calendar year and V a truncated 2-digit year: then
    465   1.1  christos  *	periodic_extend(Y-50, V, 100)
    466   1.1  christos  *   is the closest expansion of the truncated year with respect to
    467   1.1  christos  *   the full year, that is a 4-digit year with a difference of less
    468   1.1  christos  *   than 50 years to the year Y. ("century unfolding")
    469   1.1  christos  *
    470   1.1  christos  * + let T be a UN*X time stamp and V be seconds-of-day: then
    471   1.1  christos  *	perodic_extend(T-43200, V, 86400)
    472   1.1  christos  *   is a time stamp that has the same seconds-of-day as the input
    473   1.1  christos  *   value, with an absolute difference to T of <= 12hrs.  ("day
    474   1.1  christos  *   unfolding")
    475   1.1  christos  *
    476   1.1  christos  * + Wherever you have a truncated periodic value and a non-truncated
    477   1.1  christos  *   base value and you want to match them somehow...
    478   1.1  christos  *
    479   1.1  christos  * Basically, the function delivers 'pivot + (value - pivot) % cycle',
    480   1.1  christos  * but the implementation takes some pains to avoid internal signed
    481   1.1  christos  * integer overflows in the '(value - pivot) % cycle' part and adheres
    482   1.1  christos  * to the floor division convention.
    483   1.1  christos  *
    484   1.1  christos  * If 64bit scalars where available on all intended platforms, writing a
    485   1.1  christos  * version that uses 64 bit ops would be easy; writing a general
    486   1.1  christos  * division routine for 64bit ops on a platform that can only do
    487   1.1  christos  * 32/16bit divisions and is still performant is a bit more
    488   1.1  christos  * difficult. Since most usecases can be coded in a way that does only
    489  1.11  christos  * require the 32bit version a 64bit version is NOT provided here.
    490   1.9  christos  *---------------------------------------------------------------------
    491   1.1  christos  */
    492   1.1  christos int32_t
    493   1.1  christos ntpcal_periodic_extend(
    494   1.1  christos 	int32_t pivot,
    495   1.1  christos 	int32_t value,
    496   1.1  christos 	int32_t cycle
    497   1.1  christos 	)
    498   1.1  christos {
    499  1.11  christos 	/* Implement a 4-quadrant modulus calculation by 2 2-quadrant
    500  1.11  christos 	 * branches, one for positive and one for negative dividers.
    501  1.11  christos 	 * Everything else can be handled by bit level logic and
    502  1.11  christos 	 * conditional one's complement arithmetic.  By convention, we
    503  1.11  christos 	 * assume
    504  1.11  christos 	 *
    505  1.11  christos 	 * x % b == 0  if  |b| < 2
    506  1.11  christos 	 *
    507  1.11  christos 	 * that is, we don't actually divide for cycles of -1,0,1 and
    508  1.11  christos 	 * return the pivot value in that case.
    509  1.11  christos 	 */
    510  1.11  christos 	uint32_t	uv = (uint32_t)value;
    511  1.11  christos 	uint32_t	up = (uint32_t)pivot;
    512  1.11  christos 	uint32_t	uc, sf;
    513  1.11  christos 
    514  1.11  christos 	if (cycle > 1)
    515  1.11  christos 	{
    516  1.11  christos 		uc = (uint32_t)cycle;
    517  1.11  christos 		sf = UINT32_C(0) - (value < pivot);
    518  1.11  christos 
    519  1.11  christos 		uv = sf ^ (uv - up);
    520  1.11  christos 		uv %= uc;
    521  1.11  christos 		pivot += (uc & sf) + (sf ^ uv);
    522   1.1  christos 	}
    523  1.11  christos 	else if (cycle < -1)
    524  1.11  christos 	{
    525  1.11  christos 		uc = ~(uint32_t)cycle + 1;
    526  1.11  christos 		sf = UINT32_C(0) - (value > pivot);
    527  1.11  christos 
    528  1.11  christos 		uv = sf ^ (up - uv);
    529  1.11  christos 		uv %= uc;
    530  1.11  christos 		pivot -= (uc & sf) + (sf ^ uv);
    531   1.1  christos 	}
    532   1.1  christos 	return pivot;
    533   1.1  christos }
    534   1.1  christos 
    535   1.9  christos /*---------------------------------------------------------------------
    536   1.9  christos  * Note to the casual reader
    537   1.9  christos  *
    538   1.9  christos  * In the next two functions you will find (or would have found...)
    539   1.9  christos  * the expression
    540   1.9  christos  *
    541   1.9  christos  *   res.Q_s -= 0x80000000;
    542   1.9  christos  *
    543   1.9  christos  * There was some ruckus about a possible programming error due to
    544   1.9  christos  * integer overflow and sign propagation.
    545   1.9  christos  *
    546   1.9  christos  * This assumption is based on a lack of understanding of the C
    547   1.9  christos  * standard. (Though this is admittedly not one of the most 'natural'
    548   1.9  christos  * aspects of the 'C' language and easily to get wrong.)
    549   1.9  christos  *
    550  1.11  christos  * see
    551   1.9  christos  *	http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
    552   1.9  christos  *	"ISO/IEC 9899:201x Committee Draft  April 12, 2011"
    553   1.9  christos  *	6.4.4.1 Integer constants, clause 5
    554   1.9  christos  *
    555   1.9  christos  * why there is no sign extension/overflow problem here.
    556   1.9  christos  *
    557   1.9  christos  * But to ease the minds of the doubtful, I added back the 'u' qualifiers
    558  1.11  christos  * that somehow got lost over the last years.
    559   1.9  christos  */
    560   1.9  christos 
    561   1.9  christos 
    562   1.1  christos /*
    563   1.9  christos  *---------------------------------------------------------------------
    564   1.1  christos  * Convert a timestamp in NTP scale to a 64bit seconds value in the UN*X
    565   1.1  christos  * scale with proper epoch unfolding around a given pivot or the current
    566   1.1  christos  * system time. This function happily accepts negative pivot values as
    567  1.11  christos  * timestamps before 1970-01-01, so be aware of possible trouble on
    568   1.1  christos  * platforms with 32bit 'time_t'!
    569   1.1  christos  *
    570   1.1  christos  * This is also a periodic extension, but since the cycle is 2^32 and
    571   1.1  christos  * the shift is 2^31, we can do some *very* fast math without explicit
    572   1.1  christos  * divisions.
    573   1.9  christos  *---------------------------------------------------------------------
    574   1.1  christos  */
    575   1.1  christos vint64
    576   1.1  christos ntpcal_ntp_to_time(
    577   1.1  christos 	uint32_t	ntp,
    578   1.1  christos 	const time_t *	pivot
    579   1.1  christos 	)
    580   1.1  christos {
    581   1.1  christos 	vint64 res;
    582   1.1  christos 
    583   1.7  christos #   if defined(HAVE_INT64)
    584   1.1  christos 
    585   1.5  christos 	res.q_s = (pivot != NULL)
    586   1.1  christos 		      ? *pivot
    587   1.5  christos 		      : now();
    588   1.9  christos 	res.Q_s -= 0x80000000u;		/* unshift of half range */
    589   1.1  christos 	ntp	-= (uint32_t)JAN_1970;	/* warp into UN*X domain */
    590   1.1  christos 	ntp	-= res.D_s.lo;		/* cycle difference	 */
    591   1.1  christos 	res.Q_s += (uint64_t)ntp;	/* get expanded time	 */
    592   1.1  christos 
    593   1.7  christos #   else /* no 64bit scalars */
    594   1.5  christos 
    595   1.1  christos 	time_t tmp;
    596   1.5  christos 
    597   1.5  christos 	tmp = (pivot != NULL)
    598   1.1  christos 		  ? *pivot
    599   1.5  christos 		  : now();
    600   1.1  christos 	res = time_to_vint64(&tmp);
    601   1.9  christos 	M_SUB(res.D_s.hi, res.D_s.lo, 0, 0x80000000u);
    602   1.1  christos 	ntp -= (uint32_t)JAN_1970;	/* warp into UN*X domain */
    603   1.1  christos 	ntp -= res.D_s.lo;		/* cycle difference	 */
    604   1.1  christos 	M_ADD(res.D_s.hi, res.D_s.lo, 0, ntp);
    605   1.1  christos 
    606   1.7  christos #   endif /* no 64bit scalars */
    607   1.1  christos 
    608   1.1  christos 	return res;
    609   1.1  christos }
    610   1.1  christos 
    611   1.1  christos /*
    612   1.9  christos  *---------------------------------------------------------------------
    613   1.1  christos  * Convert a timestamp in NTP scale to a 64bit seconds value in the NTP
    614   1.1  christos  * scale with proper epoch unfolding around a given pivot or the current
    615   1.1  christos  * system time.
    616   1.1  christos  *
    617   1.1  christos  * Note: The pivot must be given in the UN*X time domain!
    618   1.1  christos  *
    619   1.1  christos  * This is also a periodic extension, but since the cycle is 2^32 and
    620   1.1  christos  * the shift is 2^31, we can do some *very* fast math without explicit
    621   1.1  christos  * divisions.
    622   1.9  christos  *---------------------------------------------------------------------
    623   1.1  christos  */
    624   1.1  christos vint64
    625   1.1  christos ntpcal_ntp_to_ntp(
    626   1.1  christos 	uint32_t      ntp,
    627   1.1  christos 	const time_t *pivot
    628   1.1  christos 	)
    629   1.1  christos {
    630   1.1  christos 	vint64 res;
    631   1.1  christos 
    632   1.7  christos #   if defined(HAVE_INT64)
    633   1.1  christos 
    634   1.1  christos 	res.q_s = (pivot)
    635   1.1  christos 		      ? *pivot
    636   1.1  christos 		      : now();
    637   1.9  christos 	res.Q_s -= 0x80000000u;		/* unshift of half range */
    638   1.1  christos 	res.Q_s += (uint32_t)JAN_1970;	/* warp into NTP domain	 */
    639   1.1  christos 	ntp	-= res.D_s.lo;		/* cycle difference	 */
    640   1.1  christos 	res.Q_s += (uint64_t)ntp;	/* get expanded time	 */
    641   1.1  christos 
    642   1.7  christos #   else /* no 64bit scalars */
    643   1.5  christos 
    644   1.1  christos 	time_t tmp;
    645   1.5  christos 
    646   1.1  christos 	tmp = (pivot)
    647   1.1  christos 		  ? *pivot
    648   1.1  christos 		  : now();
    649   1.1  christos 	res = time_to_vint64(&tmp);
    650   1.1  christos 	M_SUB(res.D_s.hi, res.D_s.lo, 0, 0x80000000u);
    651   1.1  christos 	M_ADD(res.D_s.hi, res.D_s.lo, 0, (uint32_t)JAN_1970);/*into NTP */
    652   1.1  christos 	ntp -= res.D_s.lo;		/* cycle difference	 */
    653   1.1  christos 	M_ADD(res.D_s.hi, res.D_s.lo, 0, ntp);
    654   1.1  christos 
    655   1.7  christos #   endif /* no 64bit scalars */
    656   1.1  christos 
    657   1.1  christos 	return res;
    658   1.1  christos }
    659   1.1  christos 
    660   1.1  christos 
    661   1.1  christos /*
    662   1.9  christos  * ====================================================================
    663   1.1  christos  *
    664   1.1  christos  * Splitting values to composite entities
    665   1.1  christos  *
    666   1.9  christos  * ====================================================================
    667   1.1  christos  */
    668   1.1  christos 
    669   1.1  christos /*
    670   1.9  christos  *---------------------------------------------------------------------
    671   1.1  christos  * Split a 64bit seconds value into elapsed days in 'res.hi' and
    672   1.1  christos  * elapsed seconds since midnight in 'res.lo' using explicit floor
    673   1.1  christos  * division. This function happily accepts negative time values as
    674   1.1  christos  * timestamps before the respective epoch start.
    675   1.9  christos  *---------------------------------------------------------------------
    676   1.1  christos  */
    677   1.1  christos ntpcal_split
    678   1.1  christos ntpcal_daysplit(
    679   1.1  christos 	const vint64 *ts
    680   1.1  christos 	)
    681   1.1  christos {
    682   1.1  christos 	ntpcal_split res;
    683  1.11  christos 	uint32_t Q, R;
    684   1.1  christos 
    685  1.11  christos #   if defined(HAVE_64BITREGS)
    686  1.11  christos 
    687  1.11  christos 	/* Assume we have 64bit registers an can do a divison by
    688  1.11  christos 	 * constant reasonably fast using the one's complement trick..
    689  1.11  christos 	 */
    690  1.11  christos 	uint64_t sf64 = (uint64_t)-(ts->q_s < 0);
    691  1.11  christos 	Q = (uint32_t)(sf64 ^ ((sf64 ^ ts->Q_s) / SECSPERDAY));
    692  1.11  christos 	R = (uint32_t)(ts->Q_s - Q * SECSPERDAY);
    693  1.11  christos 
    694  1.11  christos #   elif defined(UINT64_MAX) && !defined(__arm__)
    695  1.11  christos 
    696  1.11  christos 	/* We rely on the compiler to do efficient 64bit divisions as
    697  1.11  christos 	 * good as possible. Which might or might not be true. At least
    698  1.11  christos 	 * for ARM CPUs, the sum-by-digit code in the next section is
    699  1.11  christos 	 * faster for many compilers. (This might change over time, but
    700  1.11  christos 	 * the 64bit-by-32bit division will never outperform the exact
    701  1.11  christos 	 * division by a substantial factor....)
    702   1.7  christos 	 */
    703   1.7  christos 	if (ts->q_s < 0)
    704   1.7  christos 		Q = ~(uint32_t)(~ts->Q_s / SECSPERDAY);
    705   1.7  christos 	else
    706  1.11  christos 		Q =  (uint32_t)( ts->Q_s / SECSPERDAY);
    707  1.11  christos 	R = ts->D_s.lo - Q * SECSPERDAY;
    708   1.7  christos 
    709   1.7  christos #   else
    710   1.7  christos 
    711  1.11  christos 	/* We don't have 64bit regs. That hurts a bit.
    712  1.11  christos 	 *
    713  1.11  christos 	 * Here we use a mean trick to get away with just one explicit
    714  1.11  christos 	 * modulo operation and pure 32bit ops.
    715  1.11  christos 	 *
    716  1.11  christos 	 * Remember: 86400 <--> 128 * 675
    717  1.11  christos 	 *
    718  1.11  christos 	 * So we discard the lowest 7 bit and do an exact division by
    719  1.11  christos 	 * 675, modulo 2**32.
    720  1.11  christos 	 *
    721  1.11  christos 	 * First we shift out the lower 7 bits.
    722  1.11  christos 	 *
    723  1.11  christos 	 * Then we use a digit-wise pseudo-reduction, where a 'digit' is
    724  1.11  christos 	 * actually a 16-bit group. This is followed by a full reduction
    725  1.11  christos 	 * with a 'true' division step. This yields the modulus of the
    726  1.11  christos 	 * full 64bit value. The sign bit gets some extra treatment.
    727  1.11  christos 	 *
    728  1.11  christos 	 * Then we decrement the lower limb by that modulus, so it is
    729  1.11  christos 	 * exactly divisible by 675. [*]
    730  1.11  christos 	 *
    731  1.11  christos 	 * Then we multiply with the modular inverse of 675 (mod 2**32)
    732  1.11  christos 	 * and voila, we have the result.
    733  1.11  christos 	 *
    734  1.11  christos 	 * Special Thanks to Henry S. Warren and his "Hacker's delight"
    735  1.11  christos 	 * for giving that idea.
    736  1.11  christos 	 *
    737  1.11  christos 	 * (Note[*]: that's not the full truth. We would have to
    738  1.11  christos 	 * subtract the modulus from the full 64 bit number to get a
    739  1.11  christos 	 * number that is divisible by 675. But since we use the
    740  1.11  christos 	 * multiplicative inverse (mod 2**32) there's no reason to carry
    741  1.11  christos 	 * the subtraction into the upper bits!)
    742  1.11  christos 	 */
    743  1.11  christos 	uint32_t al = ts->D_s.lo;
    744  1.11  christos 	uint32_t ah = ts->D_s.hi;
    745  1.11  christos 
    746  1.11  christos 	/* shift out the lower 7 bits, smash sign bit */
    747  1.11  christos 	al = (al >> 7) | (ah << 25);
    748  1.11  christos 	ah = (ah >> 7) & 0x00FFFFFFu;
    749  1.11  christos 
    750  1.11  christos 	R  = (ts->d_s.hi < 0) ? 239 : 0;/* sign bit value */
    751  1.11  christos 	R += (al & 0xFFFF);
    752  1.11  christos 	R += (al >> 16	 ) * 61u;	/* 2**16 % 675 */
    753  1.11  christos 	R += (ah & 0xFFFF) * 346u;	/* 2**32 % 675 */
    754  1.11  christos 	R += (ah >> 16	 ) * 181u;	/* 2**48 % 675 */
    755  1.11  christos 	R %= 675u;			/* final reduction */
    756  1.11  christos 	Q  = (al - R) * 0x2D21C10Bu;	/* modinv(675, 2**32) */
    757  1.11  christos 	R  = (R << 7) | (ts->d_s.lo & 0x07F);
    758  1.11  christos 
    759  1.11  christos #   endif
    760  1.11  christos 
    761  1.11  christos 	res.hi = uint32_2cpl_to_int32(Q);
    762  1.11  christos 	res.lo = R;
    763  1.11  christos 
    764  1.11  christos 	return res;
    765  1.11  christos }
    766  1.11  christos 
    767  1.11  christos /*
    768  1.11  christos  *---------------------------------------------------------------------
    769  1.11  christos  * Split a 64bit seconds value into elapsed weeks in 'res.hi' and
    770  1.11  christos  * elapsed seconds since week start in 'res.lo' using explicit floor
    771  1.11  christos  * division. This function happily accepts negative time values as
    772  1.11  christos  * timestamps before the respective epoch start.
    773  1.11  christos  *---------------------------------------------------------------------
    774  1.11  christos  */
    775  1.11  christos ntpcal_split
    776  1.11  christos ntpcal_weeksplit(
    777  1.11  christos 	const vint64 *ts
    778  1.11  christos 	)
    779  1.11  christos {
    780  1.11  christos 	ntpcal_split res;
    781  1.11  christos 	uint32_t Q, R;
    782   1.7  christos 
    783  1.11  christos 	/* This is a very close relative to the day split function; for
    784  1.11  christos 	 * details, see there!
    785   1.7  christos 	 */
    786   1.7  christos 
    787  1.11  christos #   if defined(HAVE_64BITREGS)
    788  1.11  christos 
    789  1.11  christos 	uint64_t sf64 = (uint64_t)-(ts->q_s < 0);
    790  1.11  christos 	Q = (uint32_t)(sf64 ^ ((sf64 ^ ts->Q_s) / SECSPERWEEK));
    791  1.11  christos 	R = (uint32_t)(ts->Q_s - Q * SECSPERWEEK);
    792  1.11  christos 
    793  1.11  christos #   elif defined(UINT64_MAX) && !defined(__arm__)
    794   1.7  christos 
    795  1.11  christos 	if (ts->q_s < 0)
    796  1.11  christos 		Q = ~(uint32_t)(~ts->Q_s / SECSPERWEEK);
    797  1.11  christos 	else
    798  1.11  christos 		Q =  (uint32_t)( ts->Q_s / SECSPERWEEK);
    799  1.11  christos 	R = ts->D_s.lo - Q * SECSPERWEEK;
    800   1.7  christos 
    801  1.11  christos #   else
    802   1.7  christos 
    803  1.11  christos 	/* Remember: 7*86400 <--> 604800 <--> 128 * 4725 */
    804  1.11  christos 	uint32_t al = ts->D_s.lo;
    805  1.11  christos 	uint32_t ah = ts->D_s.hi;
    806  1.11  christos 
    807  1.11  christos 	al = (al >> 7) | (ah << 25);
    808  1.11  christos 	ah = (ah >> 7) & 0x00FFFFFF;
    809  1.11  christos 
    810  1.11  christos 	R  = (ts->d_s.hi < 0) ? 2264 : 0;/* sign bit value */
    811  1.11  christos 	R += (al & 0xFFFF);
    812  1.11  christos 	R += (al >> 16	 ) * 4111u;	/* 2**16 % 4725 */
    813  1.11  christos 	R += (ah & 0xFFFF) * 3721u;	/* 2**32 % 4725 */
    814  1.11  christos 	R += (ah >> 16	 ) * 2206u;	/* 2**48 % 4725 */
    815  1.11  christos 	R %= 4725u;			/* final reduction */
    816  1.11  christos 	Q  = (al - R) * 0x98BBADDDu;	/* modinv(4725, 2**32) */
    817  1.11  christos 	R  = (R << 7) | (ts->d_s.lo & 0x07F);
    818   1.7  christos 
    819   1.7  christos #   endif
    820  1.11  christos 
    821   1.7  christos 	res.hi = uint32_2cpl_to_int32(Q);
    822  1.11  christos 	res.lo = R;
    823   1.5  christos 
    824   1.1  christos 	return res;
    825   1.1  christos }
    826   1.1  christos 
    827   1.1  christos /*
    828   1.9  christos  *---------------------------------------------------------------------
    829   1.1  christos  * Split a 32bit seconds value into h/m/s and excessive days.  This
    830   1.1  christos  * function happily accepts negative time values as timestamps before
    831   1.1  christos  * midnight.
    832   1.9  christos  *---------------------------------------------------------------------
    833   1.1  christos  */
    834   1.1  christos static int32_t
    835   1.1  christos priv_timesplit(
    836   1.1  christos 	int32_t split[3],
    837   1.1  christos 	int32_t ts
    838   1.1  christos 	)
    839   1.1  christos {
    840   1.7  christos 	/* Do 3 chained floor divisions by positive constants, using the
    841   1.7  christos 	 * one's complement trick and factoring out the intermediate XOR
    842   1.7  christos 	 * ops to reduce the number of operations.
    843   1.7  christos 	 */
    844  1.11  christos 	uint32_t us, um, uh, ud, sf32;
    845   1.7  christos 
    846  1.11  christos 	sf32 = int32_sflag(ts);
    847   1.7  christos 
    848  1.11  christos 	us = (uint32_t)ts;
    849  1.11  christos 	um = (sf32 ^ us) / SECSPERMIN;
    850   1.7  christos 	uh = um / MINSPERHR;
    851   1.7  christos 	ud = uh / HRSPERDAY;
    852   1.7  christos 
    853  1.11  christos 	um ^= sf32;
    854  1.11  christos 	uh ^= sf32;
    855  1.11  christos 	ud ^= sf32;
    856   1.7  christos 
    857   1.7  christos 	split[0] = (int32_t)(uh - ud * HRSPERDAY );
    858   1.7  christos 	split[1] = (int32_t)(um - uh * MINSPERHR );
    859   1.7  christos 	split[2] = (int32_t)(us - um * SECSPERMIN);
    860  1.11  christos 
    861   1.7  christos 	return uint32_2cpl_to_int32(ud);
    862   1.1  christos }
    863   1.1  christos 
    864   1.1  christos /*
    865   1.9  christos  *---------------------------------------------------------------------
    866   1.1  christos  * Given the number of elapsed days in the calendar era, split this
    867   1.1  christos  * number into the number of elapsed years in 'res.hi' and the number
    868   1.1  christos  * of elapsed days of that year in 'res.lo'.
    869   1.1  christos  *
    870   1.1  christos  * if 'isleapyear' is not NULL, it will receive an integer that is 0 for
    871   1.1  christos  * regular years and a non-zero value for leap years.
    872   1.1  christos  *---------------------------------------------------------------------
    873   1.1  christos  */
    874   1.1  christos ntpcal_split
    875   1.1  christos ntpcal_split_eradays(
    876   1.1  christos 	int32_t days,
    877   1.1  christos 	int  *isleapyear
    878   1.1  christos 	)
    879   1.1  christos {
    880  1.11  christos 	/* Use the fast cycle split algorithm here, to calculate the
    881   1.7  christos 	 * centuries and years in a century with one division each. This
    882   1.7  christos 	 * reduces the number of division operations to two, but is
    883  1.11  christos 	 * susceptible to internal range overflow. We take some extra
    884  1.11  christos 	 * steps to avoid the gap.
    885   1.7  christos 	 */
    886   1.1  christos 	ntpcal_split res;
    887   1.7  christos 	int32_t	 n100, n001; /* calendar year cycles */
    888  1.11  christos 	uint32_t uday, Q;
    889   1.5  christos 
    890  1.11  christos 	/* split off centuries first
    891  1.11  christos 	 *
    892  1.11  christos 	 * We want to execute '(days * 4 + 3) /% 146097' under floor
    893  1.11  christos 	 * division rules in the first step. Well, actually we want to
    894  1.11  christos 	 * calculate 'floor((days + 0.75) / 36524.25)', but we want to
    895  1.11  christos 	 * do it in scaled integer calculation.
    896  1.11  christos 	 */
    897  1.11  christos #   if defined(HAVE_64BITREGS)
    898  1.11  christos 
    899  1.11  christos 	/* not too complicated with an intermediate 64bit value */
    900  1.11  christos 	uint64_t	ud64, sf64;
    901  1.11  christos 	ud64 = ((uint64_t)days << 2) | 3u;
    902  1.11  christos 	sf64 = (uint64_t)-(days < 0);
    903  1.11  christos 	Q    = (uint32_t)(sf64 ^ ((sf64 ^ ud64) / GREGORIAN_CYCLE_DAYS));
    904  1.11  christos 	uday = (uint32_t)(ud64 - Q * GREGORIAN_CYCLE_DAYS);
    905   1.7  christos 	n100 = uint32_2cpl_to_int32(Q);
    906  1.11  christos 
    907  1.11  christos #   else
    908  1.11  christos 
    909  1.11  christos 	/* '4*days+3' suffers from range overflow when going to the
    910  1.11  christos 	 * limits. We solve this by doing an exact division (mod 2^32)
    911  1.11  christos 	 * after caclulating the remainder first.
    912  1.11  christos 	 *
    913  1.11  christos 	 * We start with a partial reduction by digit sums, extracting
    914  1.11  christos 	 * the upper bits from the original value before they get lost
    915  1.11  christos 	 * by scaling, and do one full division step to get the true
    916  1.11  christos 	 * remainder.  Then a final multiplication with the
    917  1.11  christos 	 * multiplicative inverse of 146097 (mod 2^32) gives us the full
    918  1.11  christos 	 * quotient.
    919  1.11  christos 	 *
    920  1.11  christos 	 * (-2^33) % 146097	--> 130717    : the sign bit value
    921  1.11  christos 	 * ( 2^20) % 146097	--> 25897     : the upper digit value
    922  1.11  christos 	 * modinv(146097, 2^32) --> 660721233 : the inverse
    923  1.11  christos 	 */
    924  1.11  christos 	uint32_t ux = ((uint32_t)days << 2) | 3;
    925  1.11  christos 	uday  = (days < 0) ? 130717u : 0u;	    /* sign dgt */
    926  1.11  christos 	uday += ((days >> 18) & 0x01FFFu) * 25897u; /* hi dgt (src!) */
    927  1.11  christos 	uday += (ux & 0xFFFFFu);		    /* lo dgt */
    928  1.11  christos 	uday %= GREGORIAN_CYCLE_DAYS;		    /* full reduction */
    929  1.11  christos 	Q     = (ux  - uday) * 660721233u;	    /* exact div */
    930  1.11  christos 	n100  = uint32_2cpl_to_int32(Q);
    931  1.11  christos 
    932  1.11  christos #   endif
    933  1.11  christos 
    934   1.7  christos 	/* Split off years in century -- days >= 0 here, and we're far
    935   1.7  christos 	 * away from integer overflow trouble now. */
    936   1.7  christos 	uday |= 3;
    937  1.11  christos 	n001  = uday / GREGORIAN_NORMAL_LEAP_CYCLE_DAYS;
    938  1.11  christos 	uday -= n001 * GREGORIAN_NORMAL_LEAP_CYCLE_DAYS;
    939   1.7  christos 
    940   1.7  christos 	/* Assemble the year and day in year */
    941   1.7  christos 	res.hi = n100 * 100 + n001;
    942   1.7  christos 	res.lo = uday / 4u;
    943   1.7  christos 
    944  1.11  christos 	/* Possibly set the leap year flag */
    945  1.11  christos 	if (isleapyear) {
    946  1.11  christos 		uint32_t tc = (uint32_t)n100 + 1;
    947  1.11  christos 		uint32_t ty = (uint32_t)n001 + 1;
    948  1.11  christos 		*isleapyear = !(ty & 3)
    949  1.11  christos 		    && ((ty != 100) || !(tc & 3));
    950  1.11  christos 	}
    951   1.1  christos 	return res;
    952   1.1  christos }
    953   1.1  christos 
    954   1.1  christos /*
    955   1.1  christos  *---------------------------------------------------------------------
    956   1.1  christos  * Given a number of elapsed days in a year and a leap year indicator,
    957   1.1  christos  * split the number of elapsed days into the number of elapsed months in
    958   1.1  christos  * 'res.hi' and the number of elapsed days of that month in 'res.lo'.
    959   1.1  christos  *
    960   1.1  christos  * This function will fail and return {-1,-1} if the number of elapsed
    961   1.1  christos  * days is not in the valid range!
    962   1.1  christos  *---------------------------------------------------------------------
    963   1.1  christos  */
    964   1.1  christos ntpcal_split
    965   1.1  christos ntpcal_split_yeardays(
    966   1.1  christos 	int32_t eyd,
    967  1.11  christos 	int	isleap
    968   1.1  christos 	)
    969   1.1  christos {
    970  1.11  christos 	/* Use the unshifted-year, February-with-30-days approach here.
    971  1.11  christos 	 * Fractional interpolations are used in both directions, with
    972  1.11  christos 	 * the smallest power-of-two divider to avoid any true division.
    973  1.11  christos 	 */
    974  1.11  christos 	ntpcal_split	res = {-1, -1};
    975  1.11  christos 
    976  1.11  christos 	/* convert 'isleap' to number of defective days */
    977  1.11  christos 	isleap = 1 + !isleap;
    978  1.11  christos 	/* adjust for February of 30 nominal days */
    979  1.11  christos 	if (eyd >= 61 - isleap)
    980  1.11  christos 		eyd += isleap;
    981  1.11  christos 	/* if in range, convert to months and days in month */
    982  1.11  christos 	if (eyd >= 0 && eyd < 367) {
    983  1.11  christos 		res.hi = (eyd * 67 + 32) >> 11;
    984  1.11  christos 		res.lo = eyd - ((489 * res.hi + 8) >> 4);
    985   1.1  christos 	}
    986   1.1  christos 
    987   1.1  christos 	return res;
    988   1.1  christos }
    989   1.1  christos 
    990   1.1  christos /*
    991   1.1  christos  *---------------------------------------------------------------------
    992   1.1  christos  * Convert a RD into the date part of a 'struct calendar'.
    993   1.1  christos  *---------------------------------------------------------------------
    994   1.1  christos  */
    995   1.1  christos int
    996   1.1  christos ntpcal_rd_to_date(
    997   1.1  christos 	struct calendar *jd,
    998   1.1  christos 	int32_t		 rd
    999   1.1  christos 	)
   1000   1.1  christos {
   1001   1.1  christos 	ntpcal_split split;
   1002   1.7  christos 	int	     leapy;
   1003   1.7  christos 	u_int	     ymask;
   1004   1.1  christos 
   1005  1.11  christos 	/* Get day-of-week first. It's simply the RD (mod 7)... */
   1006  1.11  christos 	jd->weekday = i32mod7(rd);
   1007   1.7  christos 
   1008   1.7  christos 	split = ntpcal_split_eradays(rd - 1, &leapy);
   1009   1.7  christos 	/* Get year and day-of-year, with overflow check. If any of the
   1010   1.7  christos 	 * upper 16 bits is set after shifting to unity-based years, we
   1011   1.7  christos 	 * will have an overflow when converting to an unsigned 16bit
   1012   1.7  christos 	 * year. Shifting to the right is OK here, since it does not
   1013   1.7  christos 	 * matter if the shift is logic or arithmetic.
   1014   1.7  christos 	 */
   1015   1.7  christos 	split.hi += 1;
   1016   1.7  christos 	ymask = 0u - ((split.hi >> 16) == 0);
   1017   1.7  christos 	jd->year = (uint16_t)(split.hi & ymask);
   1018   1.1  christos 	jd->yearday = (uint16_t)split.lo + 1;
   1019   1.1  christos 
   1020   1.1  christos 	/* convert to month and mday */
   1021   1.7  christos 	split = ntpcal_split_yeardays(split.lo, leapy);
   1022   1.1  christos 	jd->month    = (uint8_t)split.hi + 1;
   1023   1.1  christos 	jd->monthday = (uint8_t)split.lo + 1;
   1024   1.1  christos 
   1025   1.7  christos 	return ymask ? leapy : -1;
   1026   1.1  christos }
   1027   1.1  christos 
   1028   1.1  christos /*
   1029   1.1  christos  *---------------------------------------------------------------------
   1030   1.1  christos  * Convert a RD into the date part of a 'struct tm'.
   1031   1.1  christos  *---------------------------------------------------------------------
   1032   1.1  christos  */
   1033   1.1  christos int
   1034   1.1  christos ntpcal_rd_to_tm(
   1035   1.1  christos 	struct tm  *utm,
   1036   1.1  christos 	int32_t	    rd
   1037   1.1  christos 	)
   1038   1.1  christos {
   1039   1.1  christos 	ntpcal_split split;
   1040   1.7  christos 	int	     leapy;
   1041   1.1  christos 
   1042   1.1  christos 	/* get day-of-week first */
   1043  1.11  christos 	utm->tm_wday = i32mod7(rd);
   1044   1.1  christos 
   1045   1.1  christos 	/* get year and day-of-year */
   1046   1.7  christos 	split = ntpcal_split_eradays(rd - 1, &leapy);
   1047   1.1  christos 	utm->tm_year = split.hi - 1899;
   1048   1.1  christos 	utm->tm_yday = split.lo;	/* 0-based */
   1049   1.1  christos 
   1050   1.1  christos 	/* convert to month and mday */
   1051   1.7  christos 	split = ntpcal_split_yeardays(split.lo, leapy);
   1052   1.1  christos 	utm->tm_mon  = split.hi;	/* 0-based */
   1053   1.1  christos 	utm->tm_mday = split.lo + 1;	/* 1-based */
   1054   1.1  christos 
   1055   1.7  christos 	return leapy;
   1056   1.1  christos }
   1057   1.1  christos 
   1058   1.1  christos /*
   1059   1.1  christos  *---------------------------------------------------------------------
   1060   1.1  christos  * Take a value of seconds since midnight and split it into hhmmss in a
   1061   1.1  christos  * 'struct calendar'.
   1062   1.1  christos  *---------------------------------------------------------------------
   1063   1.1  christos  */
   1064   1.1  christos int32_t
   1065   1.1  christos ntpcal_daysec_to_date(
   1066   1.1  christos 	struct calendar *jd,
   1067   1.1  christos 	int32_t		sec
   1068   1.1  christos 	)
   1069   1.1  christos {
   1070   1.1  christos 	int32_t days;
   1071   1.1  christos 	int   ts[3];
   1072   1.5  christos 
   1073   1.1  christos 	days = priv_timesplit(ts, sec);
   1074   1.1  christos 	jd->hour   = (uint8_t)ts[0];
   1075   1.1  christos 	jd->minute = (uint8_t)ts[1];
   1076   1.1  christos 	jd->second = (uint8_t)ts[2];
   1077   1.1  christos 
   1078   1.1  christos 	return days;
   1079   1.1  christos }
   1080   1.1  christos 
   1081   1.1  christos /*
   1082   1.1  christos  *---------------------------------------------------------------------
   1083   1.1  christos  * Take a value of seconds since midnight and split it into hhmmss in a
   1084   1.1  christos  * 'struct tm'.
   1085   1.1  christos  *---------------------------------------------------------------------
   1086   1.1  christos  */
   1087   1.1  christos int32_t
   1088   1.1  christos ntpcal_daysec_to_tm(
   1089   1.1  christos 	struct tm *utm,
   1090   1.1  christos 	int32_t	   sec
   1091   1.1  christos 	)
   1092   1.1  christos {
   1093   1.1  christos 	int32_t days;
   1094   1.1  christos 	int32_t ts[3];
   1095   1.5  christos 
   1096   1.1  christos 	days = priv_timesplit(ts, sec);
   1097   1.1  christos 	utm->tm_hour = ts[0];
   1098   1.1  christos 	utm->tm_min  = ts[1];
   1099   1.1  christos 	utm->tm_sec  = ts[2];
   1100   1.1  christos 
   1101   1.1  christos 	return days;
   1102   1.1  christos }
   1103   1.1  christos 
   1104   1.1  christos /*
   1105   1.1  christos  *---------------------------------------------------------------------
   1106   1.1  christos  * take a split representation for day/second-of-day and day offset
   1107   1.1  christos  * and convert it to a 'struct calendar'. The seconds will be normalised
   1108   1.1  christos  * into the range of a day, and the day will be adjusted accordingly.
   1109   1.1  christos  *
   1110   1.1  christos  * returns >0 if the result is in a leap year, 0 if in a regular
   1111   1.1  christos  * year and <0 if the result did not fit into the calendar struct.
   1112   1.1  christos  *---------------------------------------------------------------------
   1113   1.1  christos  */
   1114   1.1  christos int
   1115   1.1  christos ntpcal_daysplit_to_date(
   1116   1.1  christos 	struct calendar	   *jd,
   1117   1.1  christos 	const ntpcal_split *ds,
   1118   1.1  christos 	int32_t		    dof
   1119   1.1  christos 	)
   1120   1.1  christos {
   1121   1.1  christos 	dof += ntpcal_daysec_to_date(jd, ds->lo);
   1122   1.1  christos 	return ntpcal_rd_to_date(jd, ds->hi + dof);
   1123   1.1  christos }
   1124   1.1  christos 
   1125   1.1  christos /*
   1126   1.1  christos  *---------------------------------------------------------------------
   1127   1.1  christos  * take a split representation for day/second-of-day and day offset
   1128   1.1  christos  * and convert it to a 'struct tm'. The seconds will be normalised
   1129   1.1  christos  * into the range of a day, and the day will be adjusted accordingly.
   1130   1.1  christos  *
   1131   1.1  christos  * returns 1 if the result is in a leap year and zero if in a regular
   1132   1.1  christos  * year.
   1133   1.1  christos  *---------------------------------------------------------------------
   1134   1.1  christos  */
   1135   1.1  christos int
   1136   1.1  christos ntpcal_daysplit_to_tm(
   1137   1.1  christos 	struct tm	   *utm,
   1138   1.1  christos 	const ntpcal_split *ds ,
   1139   1.1  christos 	int32_t		    dof
   1140   1.1  christos 	)
   1141   1.1  christos {
   1142   1.1  christos 	dof += ntpcal_daysec_to_tm(utm, ds->lo);
   1143   1.1  christos 
   1144   1.1  christos 	return ntpcal_rd_to_tm(utm, ds->hi + dof);
   1145   1.1  christos }
   1146   1.1  christos 
   1147   1.1  christos /*
   1148   1.1  christos  *---------------------------------------------------------------------
   1149   1.1  christos  * Take a UN*X time and convert to a calendar structure.
   1150   1.1  christos  *---------------------------------------------------------------------
   1151   1.1  christos  */
   1152   1.1  christos int
   1153   1.1  christos ntpcal_time_to_date(
   1154   1.1  christos 	struct calendar	*jd,
   1155   1.1  christos 	const vint64	*ts
   1156   1.1  christos 	)
   1157   1.1  christos {
   1158   1.1  christos 	ntpcal_split ds;
   1159   1.1  christos 
   1160   1.1  christos 	ds = ntpcal_daysplit(ts);
   1161   1.1  christos 	ds.hi += ntpcal_daysec_to_date(jd, ds.lo);
   1162   1.1  christos 	ds.hi += DAY_UNIX_STARTS;
   1163   1.1  christos 
   1164   1.1  christos 	return ntpcal_rd_to_date(jd, ds.hi);
   1165   1.1  christos }
   1166   1.1  christos 
   1167   1.1  christos 
   1168   1.1  christos /*
   1169   1.9  christos  * ====================================================================
   1170   1.1  christos  *
   1171   1.1  christos  * merging composite entities
   1172   1.1  christos  *
   1173   1.9  christos  * ====================================================================
   1174   1.1  christos  */
   1175   1.1  christos 
   1176  1.11  christos #if !defined(HAVE_INT64)
   1177  1.11  christos /* multiplication helper. Seconds in days and weeks are multiples of 128,
   1178  1.11  christos  * and without that factor fit well into 16 bit. So a multiplication
   1179  1.11  christos  * of 32bit by 16bit and some shifting can be used on pure 32bit machines
   1180  1.11  christos  * with compilers that do not support 64bit integers.
   1181  1.11  christos  *
   1182  1.11  christos  * Calculate ( hi * mul * 128 ) + lo
   1183  1.11  christos  */
   1184  1.11  christos static vint64
   1185  1.11  christos _dwjoin(
   1186  1.11  christos 	uint16_t	mul,
   1187  1.11  christos 	int32_t		hi,
   1188  1.11  christos 	int32_t		lo
   1189  1.11  christos 	)
   1190  1.11  christos {
   1191  1.11  christos 	vint64		res;
   1192  1.11  christos 	uint32_t	p1, p2, sf;
   1193  1.11  christos 
   1194  1.11  christos 	/* get sign flag and absolute value of 'hi' in p1 */
   1195  1.11  christos 	sf = (uint32_t)-(hi < 0);
   1196  1.11  christos 	p1 = ((uint32_t)hi + sf) ^ sf;
   1197  1.11  christos 
   1198  1.11  christos 	/* assemble major units: res <- |hi| * mul */
   1199  1.11  christos 	res.D_s.lo = (p1 & 0xFFFF) * mul;
   1200  1.11  christos 	res.D_s.hi = 0;
   1201  1.11  christos 	p1 = (p1 >> 16) * mul;
   1202  1.11  christos 	p2 = p1 >> 16;
   1203  1.11  christos 	p1 = p1 << 16;
   1204  1.11  christos 	M_ADD(res.D_s.hi, res.D_s.lo, p2, p1);
   1205  1.11  christos 
   1206  1.11  christos 	/* mul by 128, using shift: res <-- res << 7 */
   1207  1.11  christos 	res.D_s.hi = (res.D_s.hi << 7) | (res.D_s.lo >> 25);
   1208  1.11  christos 	res.D_s.lo = (res.D_s.lo << 7);
   1209  1.11  christos 
   1210  1.11  christos 	/* fix up sign: res <-- (res + [sf|sf]) ^ [sf|sf] */
   1211  1.11  christos 	M_ADD(res.D_s.hi, res.D_s.lo, sf, sf);
   1212  1.11  christos 	res.D_s.lo ^= sf;
   1213  1.11  christos 	res.D_s.hi ^= sf;
   1214  1.11  christos 
   1215  1.11  christos 	/* properly add seconds: res <-- res + [sx(lo)|lo] */
   1216  1.11  christos 	p2 = (uint32_t)-(lo < 0);
   1217  1.11  christos 	p1 = (uint32_t)lo;
   1218  1.11  christos 	M_ADD(res.D_s.hi, res.D_s.lo, p2, p1);
   1219  1.11  christos 	return res;
   1220  1.11  christos }
   1221  1.11  christos #endif
   1222  1.11  christos 
   1223   1.1  christos /*
   1224   1.1  christos  *---------------------------------------------------------------------
   1225   1.1  christos  * Merge a number of days and a number of seconds into seconds,
   1226   1.1  christos  * expressed in 64 bits to avoid overflow.
   1227   1.1  christos  *---------------------------------------------------------------------
   1228   1.1  christos  */
   1229   1.1  christos vint64
   1230   1.1  christos ntpcal_dayjoin(
   1231   1.1  christos 	int32_t days,
   1232   1.1  christos 	int32_t secs
   1233   1.1  christos 	)
   1234   1.1  christos {
   1235   1.1  christos 	vint64 res;
   1236   1.1  christos 
   1237   1.7  christos #   if defined(HAVE_INT64)
   1238   1.1  christos 
   1239   1.1  christos 	res.q_s	 = days;
   1240   1.1  christos 	res.q_s *= SECSPERDAY;
   1241   1.1  christos 	res.q_s += secs;
   1242   1.1  christos 
   1243   1.7  christos #   else
   1244   1.1  christos 
   1245  1.11  christos 	res = _dwjoin(675, days, secs);
   1246   1.1  christos 
   1247  1.11  christos #   endif
   1248  1.11  christos 
   1249  1.11  christos 	return res;
   1250  1.11  christos }
   1251  1.11  christos 
   1252  1.11  christos /*
   1253  1.11  christos  *---------------------------------------------------------------------
   1254  1.11  christos  * Merge a number of weeks and a number of seconds into seconds,
   1255  1.11  christos  * expressed in 64 bits to avoid overflow.
   1256  1.11  christos  *---------------------------------------------------------------------
   1257  1.11  christos  */
   1258  1.11  christos vint64
   1259  1.11  christos ntpcal_weekjoin(
   1260  1.11  christos 	int32_t week,
   1261  1.11  christos 	int32_t secs
   1262  1.11  christos 	)
   1263  1.11  christos {
   1264  1.11  christos 	vint64 res;
   1265   1.1  christos 
   1266  1.11  christos #   if defined(HAVE_INT64)
   1267   1.1  christos 
   1268  1.11  christos 	res.q_s	 = week;
   1269  1.11  christos 	res.q_s *= SECSPERWEEK;
   1270  1.11  christos 	res.q_s += secs;
   1271   1.1  christos 
   1272  1.11  christos #   else
   1273   1.5  christos 
   1274  1.11  christos 	res = _dwjoin(4725, week, secs);
   1275   1.1  christos 
   1276   1.7  christos #   endif
   1277   1.1  christos 
   1278   1.1  christos 	return res;
   1279   1.1  christos }
   1280   1.1  christos 
   1281   1.1  christos /*
   1282   1.1  christos  *---------------------------------------------------------------------
   1283   1.7  christos  * get leap years since epoch in elapsed years
   1284   1.1  christos  *---------------------------------------------------------------------
   1285   1.1  christos  */
   1286   1.1  christos int32_t
   1287   1.7  christos ntpcal_leapyears_in_years(
   1288   1.1  christos 	int32_t years
   1289   1.1  christos 	)
   1290   1.1  christos {
   1291   1.7  christos 	/* We use the in-out-in algorithm here, using the one's
   1292   1.7  christos 	 * complement division trick for negative numbers. The chained
   1293   1.7  christos 	 * division sequence by 4/25/4 gives the compiler the chance to
   1294   1.7  christos 	 * get away with only one true division and doing shifts otherwise.
   1295   1.7  christos 	 */
   1296   1.7  christos 
   1297  1.11  christos 	uint32_t sf32, sum, uyear;
   1298   1.1  christos 
   1299  1.11  christos 	sf32  = int32_sflag(years);
   1300  1.11  christos 	uyear = (uint32_t)years;
   1301  1.11  christos 	uyear ^= sf32;
   1302   1.7  christos 
   1303   1.7  christos 	sum  = (uyear /=  4u);	/*   4yr rule --> IN  */
   1304   1.7  christos 	sum -= (uyear /= 25u);	/* 100yr rule --> OUT */
   1305   1.7  christos 	sum += (uyear /=  4u);	/* 400yr rule --> IN  */
   1306   1.1  christos 
   1307   1.7  christos 	/* Thanks to the alternation of IN/OUT/IN we can do the sum
   1308   1.7  christos 	 * directly and have a single one's complement operation
   1309   1.7  christos 	 * here. (Only if the years are negative, of course.) Otherwise
   1310   1.7  christos 	 * the one's complement would have to be done when
   1311   1.7  christos 	 * adding/subtracting the terms.
   1312   1.1  christos 	 */
   1313  1.11  christos 	return uint32_2cpl_to_int32(sf32 ^ sum);
   1314   1.7  christos }
   1315   1.7  christos 
   1316   1.7  christos /*
   1317   1.7  christos  *---------------------------------------------------------------------
   1318   1.7  christos  * Convert elapsed years in Era into elapsed days in Era.
   1319   1.7  christos  *---------------------------------------------------------------------
   1320   1.7  christos  */
   1321   1.7  christos int32_t
   1322   1.7  christos ntpcal_days_in_years(
   1323   1.7  christos 	int32_t years
   1324   1.7  christos 	)
   1325   1.7  christos {
   1326   1.7  christos 	return years * DAYSPERYEAR + ntpcal_leapyears_in_years(years);
   1327   1.1  christos }
   1328   1.1  christos 
   1329   1.1  christos /*
   1330   1.1  christos  *---------------------------------------------------------------------
   1331   1.1  christos  * Convert a number of elapsed month in a year into elapsed days in year.
   1332   1.1  christos  *
   1333   1.1  christos  * The month will be normalized, and 'res.hi' will contain the
   1334   1.1  christos  * excessive years that must be considered when converting the years,
   1335   1.1  christos  * while 'res.lo' will contain the number of elapsed days since start
   1336   1.1  christos  * of the year.
   1337   1.1  christos  *
   1338   1.1  christos  * This code uses the shifted-month-approach to convert month to days,
   1339   1.1  christos  * because then there is no need to have explicit leap year
   1340   1.1  christos  * information.	 The slight disadvantage is that for most month values
   1341   1.1  christos  * the result is a negative value, and the year excess is one; the
   1342   1.1  christos  * conversion is then simply based on the start of the following year.
   1343   1.1  christos  *---------------------------------------------------------------------
   1344   1.1  christos  */
   1345   1.1  christos ntpcal_split
   1346   1.1  christos ntpcal_days_in_months(
   1347   1.1  christos 	int32_t m
   1348   1.1  christos 	)
   1349   1.1  christos {
   1350   1.1  christos 	ntpcal_split res;
   1351   1.1  christos 
   1352  1.11  christos 	/* Add ten months with proper year adjustment. */
   1353  1.11  christos 	if (m < 2) {
   1354  1.11  christos 	    res.lo  = m + 10;
   1355  1.11  christos 	    res.hi  = 0;
   1356  1.11  christos 	} else {
   1357  1.11  christos 	    res.lo  = m - 2;
   1358  1.11  christos 	    res.hi  = 1;
   1359  1.11  christos 	}
   1360   1.7  christos 
   1361  1.11  christos 	/* Possibly normalise by floor division. This does not hapen for
   1362  1.11  christos 	 * input in normal range. */
   1363   1.1  christos 	if (res.lo < 0 || res.lo >= 12) {
   1364  1.11  christos 		uint32_t mu, Q, sf32;
   1365  1.11  christos 		sf32 = int32_sflag(res.lo);
   1366  1.11  christos 		mu   = (uint32_t)res.lo;
   1367  1.11  christos 		Q    = sf32 ^ ((sf32 ^ mu) / 12u);
   1368  1.11  christos 
   1369   1.7  christos 		res.hi += uint32_2cpl_to_int32(Q);
   1370  1.11  christos 		res.lo	= mu - Q * 12u;
   1371   1.1  christos 	}
   1372  1.11  christos 
   1373  1.11  christos 	/* Get cummulated days in year with unshift. Use the fractional
   1374  1.11  christos 	 * interpolation with smallest possible power of two in the
   1375  1.11  christos 	 * divider.
   1376  1.11  christos 	 */
   1377  1.11  christos 	res.lo = ((res.lo * 979 + 16) >> 5) - 306;
   1378   1.1  christos 
   1379   1.1  christos 	return res;
   1380   1.1  christos }
   1381   1.1  christos 
   1382   1.1  christos /*
   1383   1.1  christos  *---------------------------------------------------------------------
   1384   1.1  christos  * Convert ELAPSED years/months/days of gregorian calendar to elapsed
   1385   1.1  christos  * days in Gregorian epoch.
   1386   1.1  christos  *
   1387   1.1  christos  * If you want to convert years and days-of-year, just give a month of
   1388   1.1  christos  * zero.
   1389   1.1  christos  *---------------------------------------------------------------------
   1390   1.1  christos  */
   1391   1.1  christos int32_t
   1392   1.1  christos ntpcal_edate_to_eradays(
   1393   1.1  christos 	int32_t years,
   1394   1.1  christos 	int32_t mons,
   1395   1.1  christos 	int32_t mdays
   1396   1.1  christos 	)
   1397   1.1  christos {
   1398   1.1  christos 	ntpcal_split tmp;
   1399   1.1  christos 	int32_t	     res;
   1400   1.1  christos 
   1401   1.1  christos 	if (mons) {
   1402   1.1  christos 		tmp = ntpcal_days_in_months(mons);
   1403   1.1  christos 		res = ntpcal_days_in_years(years + tmp.hi) + tmp.lo;
   1404   1.1  christos 	} else
   1405   1.1  christos 		res = ntpcal_days_in_years(years);
   1406   1.1  christos 	res += mdays;
   1407   1.1  christos 
   1408   1.1  christos 	return res;
   1409   1.1  christos }
   1410   1.1  christos 
   1411   1.1  christos /*
   1412   1.1  christos  *---------------------------------------------------------------------
   1413   1.1  christos  * Convert ELAPSED years/months/days of gregorian calendar to elapsed
   1414   1.1  christos  * days in year.
   1415   1.1  christos  *
   1416   1.9  christos  * Note: This will give the true difference to the start of the given
   1417   1.9  christos  * year, even if months & days are off-scale.
   1418   1.1  christos  *---------------------------------------------------------------------
   1419   1.1  christos  */
   1420   1.1  christos int32_t
   1421   1.1  christos ntpcal_edate_to_yeardays(
   1422   1.1  christos 	int32_t years,
   1423   1.1  christos 	int32_t mons,
   1424   1.1  christos 	int32_t mdays
   1425   1.1  christos 	)
   1426   1.1  christos {
   1427   1.1  christos 	ntpcal_split tmp;
   1428   1.1  christos 
   1429   1.1  christos 	if (0 <= mons && mons < 12) {
   1430  1.11  christos 		if (mons >= 2)
   1431  1.11  christos 			mdays -= 2 - is_leapyear(years+1);
   1432  1.11  christos 		mdays += (489 * mons + 8) >> 4;
   1433   1.1  christos 	} else {
   1434   1.1  christos 		tmp = ntpcal_days_in_months(mons);
   1435   1.1  christos 		mdays += tmp.lo
   1436   1.1  christos 		       + ntpcal_days_in_years(years + tmp.hi)
   1437   1.1  christos 		       - ntpcal_days_in_years(years);
   1438   1.1  christos 	}
   1439   1.1  christos 
   1440   1.1  christos 	return mdays;
   1441   1.1  christos }
   1442   1.1  christos 
   1443   1.1  christos /*
   1444   1.1  christos  *---------------------------------------------------------------------
   1445   1.1  christos  * Convert elapsed days and the hour/minute/second information into
   1446   1.1  christos  * total seconds.
   1447   1.1  christos  *
   1448   1.1  christos  * If 'isvalid' is not NULL, do a range check on the time specification
   1449   1.1  christos  * and tell if the time input is in the normal range, permitting for a
   1450   1.1  christos  * single leapsecond.
   1451   1.1  christos  *---------------------------------------------------------------------
   1452   1.1  christos  */
   1453   1.1  christos int32_t
   1454   1.1  christos ntpcal_etime_to_seconds(
   1455   1.1  christos 	int32_t hours,
   1456   1.1  christos 	int32_t minutes,
   1457   1.1  christos 	int32_t seconds
   1458   1.1  christos 	)
   1459   1.1  christos {
   1460   1.1  christos 	int32_t res;
   1461   1.1  christos 
   1462   1.1  christos 	res = (hours * MINSPERHR + minutes) * SECSPERMIN + seconds;
   1463   1.1  christos 
   1464   1.1  christos 	return res;
   1465   1.1  christos }
   1466   1.1  christos 
   1467   1.1  christos /*
   1468   1.1  christos  *---------------------------------------------------------------------
   1469   1.1  christos  * Convert the date part of a 'struct tm' (that is, year, month,
   1470   1.1  christos  * day-of-month) into the RD of that day.
   1471   1.1  christos  *---------------------------------------------------------------------
   1472   1.1  christos  */
   1473   1.1  christos int32_t
   1474   1.1  christos ntpcal_tm_to_rd(
   1475   1.1  christos 	const struct tm *utm
   1476   1.1  christos 	)
   1477   1.1  christos {
   1478   1.1  christos 	return ntpcal_edate_to_eradays(utm->tm_year + 1899,
   1479   1.1  christos 				       utm->tm_mon,
   1480   1.1  christos 				       utm->tm_mday - 1) + 1;
   1481   1.1  christos }
   1482   1.1  christos 
   1483   1.1  christos /*
   1484   1.1  christos  *---------------------------------------------------------------------
   1485   1.1  christos  * Convert the date part of a 'struct calendar' (that is, year, month,
   1486   1.1  christos  * day-of-month) into the RD of that day.
   1487   1.1  christos  *---------------------------------------------------------------------
   1488   1.1  christos  */
   1489   1.1  christos int32_t
   1490   1.1  christos ntpcal_date_to_rd(
   1491   1.1  christos 	const struct calendar *jd
   1492   1.1  christos 	)
   1493   1.1  christos {
   1494   1.1  christos 	return ntpcal_edate_to_eradays((int32_t)jd->year - 1,
   1495   1.1  christos 				       (int32_t)jd->month - 1,
   1496   1.1  christos 				       (int32_t)jd->monthday - 1) + 1;
   1497   1.1  christos }
   1498   1.1  christos 
   1499   1.1  christos /*
   1500   1.1  christos  *---------------------------------------------------------------------
   1501   1.1  christos  * convert a year number to rata die of year start
   1502   1.1  christos  *---------------------------------------------------------------------
   1503   1.1  christos  */
   1504   1.1  christos int32_t
   1505   1.1  christos ntpcal_year_to_ystart(
   1506   1.1  christos 	int32_t year
   1507   1.1  christos 	)
   1508   1.1  christos {
   1509   1.1  christos 	return ntpcal_days_in_years(year - 1) + 1;
   1510   1.1  christos }
   1511   1.1  christos 
   1512   1.1  christos /*
   1513   1.1  christos  *---------------------------------------------------------------------
   1514   1.1  christos  * For a given RD, get the RD of the associated year start,
   1515   1.1  christos  * that is, the RD of the last January,1st on or before that day.
   1516   1.1  christos  *---------------------------------------------------------------------
   1517   1.1  christos  */
   1518   1.1  christos int32_t
   1519   1.1  christos ntpcal_rd_to_ystart(
   1520   1.1  christos 	int32_t rd
   1521   1.1  christos 	)
   1522   1.1  christos {
   1523   1.1  christos 	/*
   1524   1.1  christos 	 * Rather simple exercise: split the day number into elapsed
   1525   1.1  christos 	 * years and elapsed days, then remove the elapsed days from the
   1526   1.1  christos 	 * input value. Nice'n sweet...
   1527   1.1  christos 	 */
   1528   1.1  christos 	return rd - ntpcal_split_eradays(rd - 1, NULL).lo;
   1529   1.1  christos }
   1530   1.1  christos 
   1531   1.1  christos /*
   1532   1.1  christos  *---------------------------------------------------------------------
   1533   1.1  christos  * For a given RD, get the RD of the associated month start.
   1534   1.1  christos  *---------------------------------------------------------------------
   1535   1.1  christos  */
   1536   1.1  christos int32_t
   1537   1.1  christos ntpcal_rd_to_mstart(
   1538   1.1  christos 	int32_t rd
   1539   1.1  christos 	)
   1540   1.1  christos {
   1541   1.1  christos 	ntpcal_split split;
   1542   1.1  christos 	int	     leaps;
   1543   1.1  christos 
   1544   1.1  christos 	split = ntpcal_split_eradays(rd - 1, &leaps);
   1545   1.1  christos 	split = ntpcal_split_yeardays(split.lo, leaps);
   1546   1.1  christos 
   1547   1.1  christos 	return rd - split.lo;
   1548   1.1  christos }
   1549   1.1  christos 
   1550   1.1  christos /*
   1551   1.1  christos  *---------------------------------------------------------------------
   1552   1.1  christos  * take a 'struct calendar' and get the seconds-of-day from it.
   1553   1.1  christos  *---------------------------------------------------------------------
   1554   1.1  christos  */
   1555   1.1  christos int32_t
   1556   1.1  christos ntpcal_date_to_daysec(
   1557   1.1  christos 	const struct calendar *jd
   1558   1.1  christos 	)
   1559   1.1  christos {
   1560   1.1  christos 	return ntpcal_etime_to_seconds(jd->hour, jd->minute,
   1561   1.1  christos 				       jd->second);
   1562   1.1  christos }
   1563   1.1  christos 
   1564   1.1  christos /*
   1565   1.1  christos  *---------------------------------------------------------------------
   1566   1.1  christos  * take a 'struct tm' and get the seconds-of-day from it.
   1567   1.1  christos  *---------------------------------------------------------------------
   1568   1.1  christos  */
   1569   1.1  christos int32_t
   1570   1.1  christos ntpcal_tm_to_daysec(
   1571   1.1  christos 	const struct tm *utm
   1572   1.1  christos 	)
   1573   1.1  christos {
   1574   1.1  christos 	return ntpcal_etime_to_seconds(utm->tm_hour, utm->tm_min,
   1575   1.1  christos 				       utm->tm_sec);
   1576   1.1  christos }
   1577   1.1  christos 
   1578   1.1  christos /*
   1579   1.1  christos  *---------------------------------------------------------------------
   1580   1.1  christos  * take a 'struct calendar' and convert it to a 'time_t'
   1581   1.1  christos  *---------------------------------------------------------------------
   1582   1.1  christos  */
   1583   1.1  christos time_t
   1584   1.1  christos ntpcal_date_to_time(
   1585   1.1  christos 	const struct calendar *jd
   1586   1.1  christos 	)
   1587   1.1  christos {
   1588  1.11  christos 	vint64	join;
   1589   1.1  christos 	int32_t days, secs;
   1590   1.1  christos 
   1591   1.1  christos 	days = ntpcal_date_to_rd(jd) - DAY_UNIX_STARTS;
   1592   1.1  christos 	secs = ntpcal_date_to_daysec(jd);
   1593   1.1  christos 	join = ntpcal_dayjoin(days, secs);
   1594   1.1  christos 
   1595   1.1  christos 	return vint64_to_time(&join);
   1596   1.1  christos }
   1597   1.1  christos 
   1598   1.1  christos 
   1599   1.1  christos /*
   1600   1.9  christos  * ====================================================================
   1601   1.1  christos  *
   1602   1.1  christos  * extended and unchecked variants of caljulian/caltontp
   1603   1.1  christos  *
   1604   1.9  christos  * ====================================================================
   1605   1.1  christos  */
   1606   1.1  christos int
   1607   1.4  christos ntpcal_ntp64_to_date(
   1608   1.4  christos 	struct calendar *jd,
   1609  1.11  christos 	const vint64	*ntp
   1610   1.4  christos 	)
   1611   1.4  christos {
   1612   1.4  christos 	ntpcal_split ds;
   1613   1.5  christos 
   1614   1.4  christos 	ds = ntpcal_daysplit(ntp);
   1615   1.4  christos 	ds.hi += ntpcal_daysec_to_date(jd, ds.lo);
   1616   1.4  christos 
   1617   1.4  christos 	return ntpcal_rd_to_date(jd, ds.hi + DAY_NTP_STARTS);
   1618   1.4  christos }
   1619   1.4  christos 
   1620   1.4  christos int
   1621   1.1  christos ntpcal_ntp_to_date(
   1622   1.1  christos 	struct calendar *jd,
   1623   1.1  christos 	uint32_t	 ntp,
   1624   1.1  christos 	const time_t	*piv
   1625   1.1  christos 	)
   1626   1.1  christos {
   1627   1.4  christos 	vint64	ntp64;
   1628   1.5  christos 
   1629   1.1  christos 	/*
   1630   1.1  christos 	 * Unfold ntp time around current time into NTP domain. Split
   1631   1.1  christos 	 * into days and seconds, shift days into CE domain and
   1632   1.1  christos 	 * process the parts.
   1633   1.1  christos 	 */
   1634   1.4  christos 	ntp64 = ntpcal_ntp_to_ntp(ntp, piv);
   1635   1.4  christos 	return ntpcal_ntp64_to_date(jd, &ntp64);
   1636   1.4  christos }
   1637   1.4  christos 
   1638   1.1  christos 
   1639   1.4  christos vint64
   1640   1.4  christos ntpcal_date_to_ntp64(
   1641   1.4  christos 	const struct calendar *jd
   1642   1.4  christos 	)
   1643   1.4  christos {
   1644   1.4  christos 	/*
   1645   1.4  christos 	 * Convert date to NTP. Ignore yearday, use d/m/y only.
   1646   1.4  christos 	 */
   1647   1.4  christos 	return ntpcal_dayjoin(ntpcal_date_to_rd(jd) - DAY_NTP_STARTS,
   1648   1.4  christos 			      ntpcal_date_to_daysec(jd));
   1649   1.1  christos }
   1650   1.1  christos 
   1651   1.1  christos 
   1652   1.1  christos uint32_t
   1653   1.1  christos ntpcal_date_to_ntp(
   1654   1.1  christos 	const struct calendar *jd
   1655   1.1  christos 	)
   1656   1.1  christos {
   1657   1.1  christos 	/*
   1658  1.11  christos 	 * Get lower half of 64bit NTP timestamp from date/time.
   1659   1.1  christos 	 */
   1660   1.4  christos 	return ntpcal_date_to_ntp64(jd).d_s.lo;
   1661   1.1  christos }
   1662   1.1  christos 
   1663   1.4  christos 
   1664   1.4  christos 
   1665   1.1  christos /*
   1666   1.9  christos  * ====================================================================
   1667   1.1  christos  *
   1668   1.1  christos  * day-of-week calculations
   1669   1.1  christos  *
   1670   1.9  christos  * ====================================================================
   1671   1.1  christos  */
   1672   1.1  christos /*
   1673   1.1  christos  * Given a RataDie and a day-of-week, calculate a RDN that is reater-than,
   1674   1.1  christos  * greater-or equal, closest, less-or-equal or less-than the given RDN
   1675   1.1  christos  * and denotes the given day-of-week
   1676   1.1  christos  */
   1677   1.1  christos int32_t
   1678   1.1  christos ntpcal_weekday_gt(
   1679   1.1  christos 	int32_t rdn,
   1680   1.1  christos 	int32_t dow
   1681   1.1  christos 	)
   1682   1.1  christos {
   1683   1.1  christos 	return ntpcal_periodic_extend(rdn+1, dow, 7);
   1684   1.1  christos }
   1685   1.1  christos 
   1686   1.1  christos int32_t
   1687   1.1  christos ntpcal_weekday_ge(
   1688   1.1  christos 	int32_t rdn,
   1689   1.1  christos 	int32_t dow
   1690   1.1  christos 	)
   1691   1.1  christos {
   1692   1.1  christos 	return ntpcal_periodic_extend(rdn, dow, 7);
   1693   1.1  christos }
   1694   1.1  christos 
   1695   1.1  christos int32_t
   1696   1.1  christos ntpcal_weekday_close(
   1697   1.1  christos 	int32_t rdn,
   1698   1.1  christos 	int32_t dow
   1699   1.1  christos 	)
   1700   1.1  christos {
   1701   1.1  christos 	return ntpcal_periodic_extend(rdn-3, dow, 7);
   1702   1.1  christos }
   1703   1.1  christos 
   1704   1.1  christos int32_t
   1705   1.1  christos ntpcal_weekday_le(
   1706   1.1  christos 	int32_t rdn,
   1707   1.1  christos 	int32_t dow
   1708   1.1  christos 	)
   1709   1.1  christos {
   1710   1.1  christos 	return ntpcal_periodic_extend(rdn, dow, -7);
   1711   1.1  christos }
   1712   1.1  christos 
   1713   1.1  christos int32_t
   1714   1.1  christos ntpcal_weekday_lt(
   1715   1.1  christos 	int32_t rdn,
   1716   1.1  christos 	int32_t dow
   1717   1.1  christos 	)
   1718   1.1  christos {
   1719   1.1  christos 	return ntpcal_periodic_extend(rdn-1, dow, -7);
   1720   1.1  christos }
   1721   1.1  christos 
   1722   1.1  christos /*
   1723   1.9  christos  * ====================================================================
   1724   1.1  christos  *
   1725   1.1  christos  * ISO week-calendar conversions
   1726   1.1  christos  *
   1727   1.1  christos  * The ISO8601 calendar defines a calendar of years, weeks and weekdays.
   1728   1.1  christos  * It is related to the Gregorian calendar, and a ISO year starts at the
   1729   1.1  christos  * Monday closest to Jan,1st of the corresponding Gregorian year.  A ISO
   1730   1.1  christos  * calendar year has always 52 or 53 weeks, and like the Grogrian
   1731   1.1  christos  * calendar the ISO8601 calendar repeats itself every 400 years, or
   1732   1.1  christos  * 146097 days, or 20871 weeks.
   1733   1.1  christos  *
   1734   1.1  christos  * While it is possible to write ISO calendar functions based on the
   1735   1.1  christos  * Gregorian calendar functions, the following implementation takes a
   1736   1.1  christos  * different approach, based directly on years and weeks.
   1737   1.1  christos  *
   1738   1.1  christos  * Analysis of the tabulated data shows that it is not possible to
   1739   1.1  christos  * interpolate from years to weeks over a full 400 year range; cyclic
   1740   1.1  christos  * shifts over 400 years do not provide a solution here. But it *is*
   1741   1.1  christos  * possible to interpolate over every single century of the 400-year
   1742   1.1  christos  * cycle. (The centennial leap year rule seems to be the culprit here.)
   1743   1.1  christos  *
   1744   1.1  christos  * It can be shown that a conversion from years to weeks can be done
   1745   1.1  christos  * using a linear transformation of the form
   1746   1.1  christos  *
   1747   1.1  christos  *   w = floor( y * a + b )
   1748   1.1  christos  *
   1749   1.1  christos  * where the slope a must hold to
   1750   1.1  christos  *
   1751   1.1  christos  *  52.1780821918 <= a < 52.1791044776
   1752   1.1  christos  *
   1753   1.1  christos  * and b must be chosen according to the selected slope and the number
   1754   1.1  christos  * of the century in a 400-year period.
   1755   1.1  christos  *
   1756   1.1  christos  * The inverse calculation can also be done in this way. Careful scaling
   1757   1.1  christos  * provides an unlimited set of integer coefficients a,k,b that enable
   1758   1.1  christos  * us to write the calulation in the form
   1759   1.1  christos  *
   1760   1.1  christos  *   w = (y * a	 + b ) / k
   1761   1.1  christos  *   y = (w * a' + b') / k'
   1762   1.1  christos  *
   1763  1.11  christos  * In this implementation the values of k and k' are chosen to be the
   1764   1.1  christos  * smallest possible powers of two, so the division can be implemented
   1765   1.1  christos  * as shifts if the optimiser chooses to do so.
   1766   1.1  christos  *
   1767   1.9  christos  * ====================================================================
   1768   1.1  christos  */
   1769   1.1  christos 
   1770   1.1  christos /*
   1771   1.1  christos  * Given a number of elapsed (ISO-)years since the begin of the
   1772   1.1  christos  * christian era, return the number of elapsed weeks corresponding to
   1773   1.1  christos  * the number of years.
   1774   1.1  christos  */
   1775   1.1  christos int32_t
   1776   1.1  christos isocal_weeks_in_years(
   1777   1.1  christos 	int32_t years
   1778   1.1  christos 	)
   1779  1.11  christos {
   1780   1.1  christos 	/*
   1781   1.1  christos 	 * use: w = (y * 53431 + b[c]) / 1024 as interpolation
   1782   1.1  christos 	 */
   1783   1.7  christos 	static const uint16_t bctab[4] = { 157, 449, 597, 889 };
   1784   1.7  christos 
   1785  1.11  christos 	int32_t	 cs, cw;
   1786  1.11  christos 	uint32_t cc, ci, yu, sf32;
   1787  1.11  christos 
   1788  1.11  christos 	sf32 = int32_sflag(years);
   1789  1.11  christos 	yu   = (uint32_t)years;
   1790   1.1  christos 
   1791   1.7  christos 	/* split off centuries, using floor division */
   1792  1.11  christos 	cc  = sf32 ^ ((sf32 ^ yu) / 100u);
   1793   1.7  christos 	yu -= cc * 100u;
   1794   1.7  christos 
   1795   1.7  christos 	/* calculate century cycles shift and cycle index:
   1796   1.7  christos 	 * Assuming a century is 5217 weeks, we have to add a cycle
   1797   1.7  christos 	 * shift that is 3 for every 4 centuries, because 3 of the four
   1798   1.7  christos 	 * centuries have 5218 weeks. So '(cc*3 + 1) / 4' is the actual
   1799   1.7  christos 	 * correction, and the second century is the defective one.
   1800   1.7  christos 	 *
   1801   1.7  christos 	 * Needs floor division by 4, which is done with masking and
   1802   1.7  christos 	 * shifting.
   1803   1.7  christos 	 */
   1804   1.7  christos 	ci = cc * 3u + 1;
   1805  1.11  christos 	cs = uint32_2cpl_to_int32(sf32 ^ ((sf32 ^ ci) >> 2));
   1806  1.11  christos 	ci = ci & 3u;
   1807  1.11  christos 
   1808   1.7  christos 	/* Get weeks in century. Can use plain division here as all ops
   1809   1.7  christos 	 * are >= 0,  and let the compiler sort out the possible
   1810   1.7  christos 	 * optimisations.
   1811   1.7  christos 	 */
   1812   1.7  christos 	cw = (yu * 53431u + bctab[ci]) / 1024u;
   1813   1.1  christos 
   1814   1.7  christos 	return uint32_2cpl_to_int32(cc) * 5217 + cs + cw;
   1815   1.1  christos }
   1816   1.1  christos 
   1817   1.1  christos /*
   1818   1.1  christos  * Given a number of elapsed weeks since the begin of the christian
   1819   1.1  christos  * era, split this number into the number of elapsed years in res.hi
   1820   1.1  christos  * and the excessive number of weeks in res.lo. (That is, res.lo is
   1821   1.1  christos  * the number of elapsed weeks in the remaining partial year.)
   1822   1.1  christos  */
   1823   1.1  christos ntpcal_split
   1824   1.1  christos isocal_split_eraweeks(
   1825   1.1  christos 	int32_t weeks
   1826   1.1  christos 	)
   1827   1.1  christos {
   1828   1.1  christos 	/*
   1829   1.1  christos 	 * use: y = (w * 157 + b[c]) / 8192 as interpolation
   1830   1.1  christos 	 */
   1831   1.7  christos 
   1832   1.7  christos 	static const uint16_t bctab[4] = { 85, 130, 17, 62 };
   1833   1.7  christos 
   1834   1.1  christos 	ntpcal_split res;
   1835  1.11  christos 	int32_t	 cc, ci;
   1836  1.11  christos 	uint32_t sw, cy, Q;
   1837  1.11  christos 
   1838  1.11  christos 	/* Use two fast cycle-split divisions again. Herew e want to
   1839  1.11  christos 	 * execute '(weeks * 4 + 2) /% 20871' under floor division rules
   1840  1.11  christos 	 * in the first step.
   1841  1.11  christos 	 *
   1842  1.11  christos 	 * This is of course (again) susceptible to internal overflow if
   1843  1.11  christos 	 * coded directly in 32bit. And again we use 64bit division on
   1844  1.11  christos 	 * a 64bit target and exact division after calculating the
   1845  1.11  christos 	 * remainder first on a 32bit target. With the smaller divider,
   1846  1.11  christos 	 * that's even a bit neater.
   1847  1.11  christos 	 */
   1848  1.11  christos #   if defined(HAVE_64BITREGS)
   1849  1.11  christos 
   1850  1.11  christos 	/* Full floor division with 64bit values. */
   1851  1.11  christos 	uint64_t sf64, sw64;
   1852  1.11  christos 	sf64 = (uint64_t)-(weeks < 0);
   1853  1.11  christos 	sw64 = ((uint64_t)weeks << 2) | 2u;
   1854  1.11  christos 	Q    = (uint32_t)(sf64 ^ ((sf64 ^ sw64) / GREGORIAN_CYCLE_WEEKS));
   1855  1.11  christos 	sw   = (uint32_t)(sw64 - Q * GREGORIAN_CYCLE_WEEKS);
   1856  1.11  christos 
   1857  1.11  christos #   else
   1858  1.11  christos 
   1859  1.11  christos 	/* Exact division after calculating the remainder via partial
   1860  1.11  christos 	 * reduction by digit sum.
   1861  1.11  christos 	 * (-2^33) % 20871     --> 5491	     : the sign bit value
   1862  1.11  christos 	 * ( 2^20) % 20871     --> 5026	     : the upper digit value
   1863  1.11  christos 	 * modinv(20871, 2^32) --> 330081335 : the inverse
   1864  1.11  christos 	 */
   1865  1.11  christos 	uint32_t ux = ((uint32_t)weeks << 2) | 2;
   1866  1.11  christos 	sw  = (weeks < 0) ? 5491u : 0u;		  /* sign dgt */
   1867  1.11  christos 	sw += ((weeks >> 18) & 0x01FFFu) * 5026u; /* hi dgt (src!) */
   1868  1.11  christos 	sw += (ux & 0xFFFFFu);			  /* lo dgt */
   1869  1.11  christos 	sw %= GREGORIAN_CYCLE_WEEKS;		  /* full reduction */
   1870  1.11  christos 	Q   = (ux  - sw) * 330081335u;		  /* exact div */
   1871  1.11  christos 
   1872  1.11  christos #   endif
   1873   1.1  christos 
   1874  1.11  christos 	ci  = Q & 3u;
   1875   1.7  christos 	cc  = uint32_2cpl_to_int32(Q);
   1876   1.7  christos 
   1877   1.7  christos 	/* Split off years; sw >= 0 here! The scaled weeks in the years
   1878   1.7  christos 	 * are scaled up by 157 afterwards.
   1879  1.11  christos 	 */
   1880   1.7  christos 	sw  = (sw / 4u) * 157u + bctab[ci];
   1881  1.11  christos 	cy  = sw / 8192u;	/* sw >> 13 , let the compiler sort it out */
   1882  1.11  christos 	sw  = sw % 8192u;	/* sw & 8191, let the compiler sort it out */
   1883   1.1  christos 
   1884   1.7  christos 	/* assemble elapsed years and downscale the elapsed weeks in
   1885   1.7  christos 	 * the year.
   1886   1.7  christos 	 */
   1887   1.7  christos 	res.hi = 100*cc + cy;
   1888   1.7  christos 	res.lo = sw / 157u;
   1889   1.5  christos 
   1890   1.1  christos 	return res;
   1891   1.1  christos }
   1892   1.1  christos 
   1893   1.1  christos /*
   1894   1.1  christos  * Given a second in the NTP time scale and a pivot, expand the NTP
   1895   1.1  christos  * time stamp around the pivot and convert into an ISO calendar time
   1896   1.1  christos  * stamp.
   1897   1.1  christos  */
   1898   1.1  christos int
   1899   1.4  christos isocal_ntp64_to_date(
   1900   1.1  christos 	struct isodate *id,
   1901   1.4  christos 	const vint64   *ntp
   1902   1.1  christos 	)
   1903   1.1  christos {
   1904   1.1  christos 	ntpcal_split ds;
   1905  1.11  christos 	int32_t	     ts[3];
   1906  1.11  christos 	uint32_t     uw, ud, sf32;
   1907   1.5  christos 
   1908   1.1  christos 	/*
   1909   1.4  christos 	 * Split NTP time into days and seconds, shift days into CE
   1910   1.4  christos 	 * domain and process the parts.
   1911   1.1  christos 	 */
   1912   1.4  christos 	ds = ntpcal_daysplit(ntp);
   1913   1.1  christos 
   1914   1.1  christos 	/* split time part */
   1915   1.1  christos 	ds.hi += priv_timesplit(ts, ds.lo);
   1916   1.1  christos 	id->hour   = (uint8_t)ts[0];
   1917   1.1  christos 	id->minute = (uint8_t)ts[1];
   1918   1.1  christos 	id->second = (uint8_t)ts[2];
   1919   1.1  christos 
   1920   1.7  christos 	/* split days into days and weeks, using floor division in unsigned */
   1921   1.7  christos 	ds.hi += DAY_NTP_STARTS - 1; /* shift from NTP to RDN */
   1922  1.11  christos 	sf32 = int32_sflag(ds.hi);
   1923  1.11  christos 	ud   = (uint32_t)ds.hi;
   1924  1.11  christos 	uw   = sf32 ^ ((sf32 ^ ud) / DAYSPERWEEK);
   1925  1.11  christos 	ud  -= uw * DAYSPERWEEK;
   1926  1.11  christos 
   1927   1.7  christos 	ds.hi = uint32_2cpl_to_int32(uw);
   1928   1.7  christos 	ds.lo = ud;
   1929   1.7  christos 
   1930   1.1  christos 	id->weekday = (uint8_t)ds.lo + 1;	/* weekday result    */
   1931   1.1  christos 
   1932   1.7  christos 	/* get year and week in year */
   1933   1.1  christos 	ds = isocal_split_eraweeks(ds.hi);	/* elapsed years&week*/
   1934   1.1  christos 	id->year = (uint16_t)ds.hi + 1;		/* shift to current  */
   1935   1.1  christos 	id->week = (uint8_t )ds.lo + 1;
   1936   1.1  christos 
   1937   1.2  christos 	return (ds.hi >= 0 && ds.hi < 0x0000FFFF);
   1938   1.1  christos }
   1939   1.1  christos 
   1940   1.4  christos int
   1941   1.4  christos isocal_ntp_to_date(
   1942   1.4  christos 	struct isodate *id,
   1943   1.4  christos 	uint32_t	ntp,
   1944   1.4  christos 	const time_t   *piv
   1945   1.4  christos 	)
   1946   1.4  christos {
   1947   1.4  christos 	vint64	ntp64;
   1948   1.5  christos 
   1949   1.4  christos 	/*
   1950   1.4  christos 	 * Unfold ntp time around current time into NTP domain, then
   1951   1.4  christos 	 * convert the full time stamp.
   1952   1.4  christos 	 */
   1953   1.4  christos 	ntp64 = ntpcal_ntp_to_ntp(ntp, piv);
   1954   1.4  christos 	return isocal_ntp64_to_date(id, &ntp64);
   1955   1.4  christos }
   1956   1.4  christos 
   1957   1.1  christos /*
   1958   1.1  christos  * Convert a ISO date spec into a second in the NTP time scale,
   1959   1.1  christos  * properly truncated to 32 bit.
   1960   1.1  christos  */
   1961   1.4  christos vint64
   1962   1.4  christos isocal_date_to_ntp64(
   1963   1.1  christos 	const struct isodate *id
   1964   1.1  christos 	)
   1965   1.1  christos {
   1966   1.1  christos 	int32_t weeks, days, secs;
   1967   1.1  christos 
   1968   1.1  christos 	weeks = isocal_weeks_in_years((int32_t)id->year - 1)
   1969   1.1  christos 	      + (int32_t)id->week - 1;
   1970   1.1  christos 	days = weeks * 7 + (int32_t)id->weekday;
   1971   1.1  christos 	/* days is RDN of ISO date now */
   1972   1.1  christos 	secs = ntpcal_etime_to_seconds(id->hour, id->minute, id->second);
   1973   1.1  christos 
   1974   1.4  christos 	return ntpcal_dayjoin(days - DAY_NTP_STARTS, secs);
   1975   1.4  christos }
   1976   1.4  christos 
   1977   1.4  christos uint32_t
   1978   1.4  christos isocal_date_to_ntp(
   1979   1.4  christos 	const struct isodate *id
   1980   1.4  christos 	)
   1981   1.4  christos {
   1982   1.4  christos 	/*
   1983  1.11  christos 	 * Get lower half of 64bit NTP timestamp from date/time.
   1984   1.4  christos 	 */
   1985   1.4  christos 	return isocal_date_to_ntp64(id).d_s.lo;
   1986   1.1  christos }
   1987   1.1  christos 
   1988  1.10  christos /*
   1989  1.10  christos  * ====================================================================
   1990  1.10  christos  * 'basedate' support functions
   1991  1.10  christos  * ====================================================================
   1992  1.10  christos  */
   1993  1.10  christos 
   1994  1.10  christos static int32_t s_baseday = NTP_TO_UNIX_DAYS;
   1995  1.11  christos static int32_t s_gpsweek = 0;
   1996  1.10  christos 
   1997  1.10  christos int32_t
   1998  1.10  christos basedate_eval_buildstamp(void)
   1999  1.10  christos {
   2000  1.10  christos 	struct calendar jd;
   2001  1.10  christos 	int32_t		ed;
   2002  1.11  christos 
   2003  1.10  christos 	if (!ntpcal_get_build_date(&jd))
   2004  1.10  christos 		return NTP_TO_UNIX_DAYS;
   2005  1.10  christos 
   2006  1.10  christos 	/* The time zone of the build stamp is unspecified; we remove
   2007  1.10  christos 	 * one day to provide a certain slack. And in case somebody
   2008  1.10  christos 	 * fiddled with the system clock, we make sure we do not go
   2009  1.10  christos 	 * before the UNIX epoch (1970-01-01). It's probably not possible
   2010  1.10  christos 	 * to do this to the clock on most systems, but there are other
   2011  1.10  christos 	 * ways to tweak the build stamp.
   2012  1.10  christos 	 */
   2013  1.10  christos 	jd.monthday -= 1;
   2014  1.10  christos 	ed = ntpcal_date_to_rd(&jd) - DAY_NTP_STARTS;
   2015  1.10  christos 	return (ed < NTP_TO_UNIX_DAYS) ? NTP_TO_UNIX_DAYS : ed;
   2016  1.10  christos }
   2017  1.10  christos 
   2018  1.10  christos int32_t
   2019  1.10  christos basedate_eval_string(
   2020  1.10  christos 	const char * str
   2021  1.10  christos 	)
   2022  1.10  christos {
   2023  1.10  christos 	u_short	y,m,d;
   2024  1.10  christos 	u_long	ned;
   2025  1.10  christos 	int	rc, nc;
   2026  1.10  christos 	size_t	sl;
   2027  1.10  christos 
   2028  1.11  christos 	sl = strlen(str);
   2029  1.10  christos 	rc = sscanf(str, "%4hu-%2hu-%2hu%n", &y, &m, &d, &nc);
   2030  1.10  christos 	if (rc == 3 && (size_t)nc == sl) {
   2031  1.10  christos 		if (m >= 1 && m <= 12 && d >= 1 && d <= 31)
   2032  1.10  christos 			return ntpcal_edate_to_eradays(y-1, m-1, d)
   2033  1.10  christos 			    - DAY_NTP_STARTS;
   2034  1.10  christos 		goto buildstamp;
   2035  1.10  christos 	}
   2036  1.10  christos 
   2037  1.10  christos 	rc = sscanf(str, "%lu%n", &ned, &nc);
   2038  1.10  christos 	if (rc == 1 && (size_t)nc == sl) {
   2039  1.10  christos 		if (ned <= INT32_MAX)
   2040  1.10  christos 			return (int32_t)ned;
   2041  1.10  christos 		goto buildstamp;
   2042  1.10  christos 	}
   2043  1.10  christos 
   2044  1.10  christos   buildstamp:
   2045  1.10  christos 	msyslog(LOG_WARNING,
   2046  1.10  christos 		"basedate string \"%s\" invalid, build date substituted!",
   2047  1.10  christos 		str);
   2048  1.10  christos 	return basedate_eval_buildstamp();
   2049  1.10  christos }
   2050  1.10  christos 
   2051  1.10  christos uint32_t
   2052  1.10  christos basedate_get_day(void)
   2053  1.10  christos {
   2054  1.10  christos 	return s_baseday;
   2055  1.10  christos }
   2056  1.10  christos 
   2057  1.10  christos int32_t
   2058  1.10  christos basedate_set_day(
   2059  1.10  christos 	int32_t day
   2060  1.10  christos 	)
   2061  1.10  christos {
   2062  1.10  christos 	struct calendar	jd;
   2063  1.10  christos 	int32_t		retv;
   2064  1.10  christos 
   2065  1.11  christos 	/* set NTP base date for NTP era unfolding */
   2066  1.10  christos 	if (day < NTP_TO_UNIX_DAYS) {
   2067  1.10  christos 		msyslog(LOG_WARNING,
   2068  1.10  christos 			"baseday_set_day: invalid day (%lu), UNIX epoch substituted",
   2069  1.10  christos 			(unsigned long)day);
   2070  1.10  christos 		day = NTP_TO_UNIX_DAYS;
   2071  1.10  christos 	}
   2072  1.11  christos 	retv = s_baseday;
   2073  1.10  christos 	s_baseday = day;
   2074  1.10  christos 	ntpcal_rd_to_date(&jd, day + DAY_NTP_STARTS);
   2075  1.10  christos 	msyslog(LOG_INFO, "basedate set to %04hu-%02hu-%02hu",
   2076  1.10  christos 		jd.year, (u_short)jd.month, (u_short)jd.monthday);
   2077  1.11  christos 
   2078  1.11  christos 	/* set GPS base week for GPS week unfolding */
   2079  1.11  christos 	day = ntpcal_weekday_ge(day + DAY_NTP_STARTS, CAL_SUNDAY)
   2080  1.11  christos 	    - DAY_NTP_STARTS;
   2081  1.11  christos 	if (day < NTP_TO_GPS_DAYS)
   2082  1.11  christos 	    day = NTP_TO_GPS_DAYS;
   2083  1.11  christos 	s_gpsweek = (day - NTP_TO_GPS_DAYS) / DAYSPERWEEK;
   2084  1.11  christos 	ntpcal_rd_to_date(&jd, day + DAY_NTP_STARTS);
   2085  1.11  christos 	msyslog(LOG_INFO, "gps base set to %04hu-%02hu-%02hu (week %d)",
   2086  1.11  christos 		jd.year, (u_short)jd.month, (u_short)jd.monthday, s_gpsweek);
   2087  1.11  christos 
   2088  1.10  christos 	return retv;
   2089  1.10  christos }
   2090  1.10  christos 
   2091  1.10  christos time_t
   2092  1.10  christos basedate_get_eracenter(void)
   2093  1.10  christos {
   2094  1.10  christos 	time_t retv;
   2095  1.10  christos 	retv  = (time_t)(s_baseday - NTP_TO_UNIX_DAYS);
   2096  1.10  christos 	retv *= SECSPERDAY;
   2097  1.10  christos 	retv += (UINT32_C(1) << 31);
   2098  1.10  christos 	return retv;
   2099  1.10  christos }
   2100  1.10  christos 
   2101  1.10  christos time_t
   2102  1.10  christos basedate_get_erabase(void)
   2103  1.10  christos {
   2104  1.10  christos 	time_t retv;
   2105  1.10  christos 	retv  = (time_t)(s_baseday - NTP_TO_UNIX_DAYS);
   2106  1.10  christos 	retv *= SECSPERDAY;
   2107  1.10  christos 	return retv;
   2108  1.10  christos }
   2109  1.10  christos 
   2110  1.11  christos uint32_t
   2111  1.11  christos basedate_get_gpsweek(void)
   2112  1.11  christos {
   2113  1.11  christos     return s_gpsweek;
   2114  1.11  christos }
   2115  1.11  christos 
   2116  1.11  christos uint32_t
   2117  1.11  christos basedate_expand_gpsweek(
   2118  1.11  christos     unsigned short weekno
   2119  1.11  christos     )
   2120  1.11  christos {
   2121  1.11  christos     /* We do a fast modulus expansion here. Since all quantities are
   2122  1.11  christos      * unsigned and we cannot go before the start of the GPS epoch
   2123  1.11  christos      * anyway, and since the truncated GPS week number is 10 bit, the
   2124  1.11  christos      * expansion becomes a simple sub/and/add sequence.
   2125  1.11  christos      */
   2126  1.11  christos     #if GPSWEEKS != 1024
   2127  1.11  christos     # error GPSWEEKS defined wrong -- should be 1024!
   2128  1.11  christos     #endif
   2129  1.11  christos 
   2130  1.11  christos     uint32_t diff;
   2131  1.11  christos     diff = ((uint32_t)weekno - s_gpsweek) & (GPSWEEKS - 1);
   2132  1.11  christos     return s_gpsweek + diff;
   2133  1.11  christos }
   2134  1.11  christos 
   2135  1.11  christos /*
   2136  1.11  christos  * ====================================================================
   2137  1.11  christos  * misc. helpers
   2138  1.11  christos  * ====================================================================
   2139  1.11  christos  */
   2140  1.11  christos 
   2141  1.11  christos /* --------------------------------------------------------------------
   2142  1.11  christos  * reconstruct the centrury from a truncated date and a day-of-week
   2143  1.11  christos  *
   2144  1.11  christos  * Given a date with truncated year (2-digit, 0..99) and a day-of-week
   2145  1.11  christos  * from 1(Mon) to 7(Sun), recover the full year between 1900AD and 2300AD.
   2146  1.11  christos  */
   2147  1.11  christos int32_t
   2148  1.11  christos ntpcal_expand_century(
   2149  1.11  christos 	uint32_t y,
   2150  1.11  christos 	uint32_t m,
   2151  1.11  christos 	uint32_t d,
   2152  1.11  christos 	uint32_t wd)
   2153  1.11  christos {
   2154  1.11  christos 	/* This algorithm is short but tricky... It's related to
   2155  1.11  christos 	 * Zeller's congruence, partially done backwards.
   2156  1.11  christos 	 *
   2157  1.11  christos 	 * A few facts to remember:
   2158  1.11  christos 	 *  1) The Gregorian calendar has a cycle of 400 years.
   2159  1.11  christos 	 *  2) The weekday of the 1st day of a century shifts by 5 days
   2160  1.11  christos 	 *     during a great cycle.
   2161  1.11  christos 	 *  3) For calendar math, a century starts with the 1st year,
   2162  1.11  christos 	 *     which is year 1, !not! zero.
   2163  1.11  christos 	 *
   2164  1.11  christos 	 * So we start with taking the weekday difference (mod 7)
   2165  1.11  christos 	 * between the truncated date (which is taken as an absolute
   2166  1.11  christos 	 * date in the 1st century in the proleptic calendar) and the
   2167  1.11  christos 	 * weekday given.
   2168  1.11  christos 	 *
   2169  1.11  christos 	 * When dividing this residual by 5, we obtain the number of
   2170  1.11  christos 	 * centuries to add to the base. But since the residual is (mod
   2171  1.11  christos 	 * 7), we have to make this an exact division by multiplication
   2172  1.11  christos 	 * with the modular inverse of 5 (mod 7), which is 3:
   2173  1.11  christos 	 *    3*5 === 1 (mod 7).
   2174  1.11  christos 	 *
   2175  1.11  christos 	 * If this yields a result of 4/5/6, the given date/day-of-week
   2176  1.11  christos 	 * combination is impossible, and we return zero as resulting
   2177  1.11  christos 	 * year to indicate failure.
   2178  1.11  christos 	 *
   2179  1.11  christos 	 * Then we remap the century to the range starting with year
   2180  1.11  christos 	 * 1900.
   2181  1.11  christos 	 */
   2182  1.11  christos 
   2183  1.11  christos 	uint32_t c;
   2184  1.11  christos 
   2185  1.11  christos 	/* check basic constraints */
   2186  1.11  christos 	if ((y >= 100u) || (--m >= 12u) || (--d >= 31u))
   2187  1.11  christos 		return 0;
   2188  1.11  christos 
   2189  1.11  christos 	if ((m += 10u) >= 12u)		/* shift base to prev. March,1st */
   2190  1.11  christos 		m -= 12u;
   2191  1.11  christos 	else if (--y >= 100u)
   2192  1.11  christos 		y += 100u;
   2193  1.11  christos 	d += y + (y >> 2) + 2u;		/* year share */
   2194  1.11  christos 	d += (m * 83u + 16u) >> 5;	/* month share */
   2195  1.11  christos 
   2196  1.11  christos 	/* get (wd - d), shifted to positive value, and multiply with
   2197  1.11  christos 	 * 3(mod 7). (Exact division, see to comment)
   2198  1.11  christos 	 * Note: 1) d <= 184 at this point.
   2199  1.11  christos 	 *	 2) 252 % 7 == 0, but 'wd' is off by one since we did
   2200  1.11  christos 	 *	    '--d' above, so we add just 251 here!
   2201  1.11  christos 	 */
   2202  1.11  christos 	c = u32mod7(3 * (251u + wd - d));
   2203  1.11  christos 	if (c > 3u)
   2204  1.11  christos 		return 0;
   2205  1.11  christos 
   2206  1.11  christos 	if ((m > 9u) && (++y >= 100u)) {/* undo base shift */
   2207  1.11  christos 		y -= 100u;
   2208  1.11  christos 		c = (c + 1) & 3u;
   2209  1.11  christos 	}
   2210  1.11  christos 	y += (c * 100u);		/* combine into 1st cycle */
   2211  1.11  christos 	y += (y < 300u) ? 2000 : 1600;	/* map to destination era */
   2212  1.11  christos 	return (int)y;
   2213  1.11  christos }
   2214  1.11  christos 
   2215  1.11  christos char *
   2216  1.11  christos ntpcal_iso8601std(
   2217  1.11  christos 	char *		buf,
   2218  1.11  christos 	size_t		len,
   2219  1.11  christos 	TcCivilDate *	cdp
   2220  1.11  christos 	)
   2221  1.11  christos {
   2222  1.11  christos 	if (!buf) {
   2223  1.11  christos 		LIB_GETBUF(buf);
   2224  1.11  christos 		len = LIB_BUFLENGTH;
   2225  1.11  christos 	}
   2226  1.11  christos 	if (len) {
   2227  1.11  christos 		int slen = snprintf(buf, len, "%04u-%02u-%02uT%02u:%02u:%02u",
   2228  1.11  christos 			       cdp->year, cdp->month, cdp->monthday,
   2229  1.11  christos 			       cdp->hour, cdp->minute, cdp->second);
   2230  1.11  christos 		if (slen < 0)
   2231  1.11  christos 			*buf = '\0';
   2232  1.11  christos 	}
   2233  1.11  christos 	return buf;
   2234  1.11  christos }
   2235  1.11  christos 
   2236   1.1  christos /* -*-EOF-*- */
   2237