154359Sroberto/* 254359Sroberto * ntp_calendar.h - definitions for the calendar time-of-day routine 354359Sroberto */ 454359Sroberto#ifndef NTP_CALENDAR_H 554359Sroberto#define NTP_CALENDAR_H 654359Sroberto 7280849Scy#include <time.h> 8280849Scy 954359Sroberto#include "ntp_types.h" 1054359Sroberto 11280849Scy/* gregorian calendar date */ 1254359Srobertostruct calendar { 13280849Scy uint16_t year; /* year (A.D.) */ 14280849Scy uint16_t yearday; /* day of year, 1 = January 1 */ 15280849Scy uint8_t month; /* month, 1 = January */ 16280849Scy uint8_t monthday; /* day of month */ 17280849Scy uint8_t hour; /* hour of day, midnight = 0 */ 18280849Scy uint8_t minute; /* minute of hour */ 19280849Scy uint8_t second; /* second of minute */ 20280849Scy uint8_t weekday; /* 0..7, 0=Sunday */ 2154359Sroberto}; 22358659Scytypedef struct calendar TCivilDate; 23358659Scytypedef struct calendar const TcCivilDate; 2454359Sroberto 25280849Scy/* ISO week calendar date */ 26280849Scystruct isodate { 27280849Scy uint16_t year; /* year (A.D.) */ 28280849Scy uint8_t week; /* 1..53, week in year */ 29280849Scy uint8_t weekday; /* 1..7, 1=Monday */ 30280849Scy uint8_t hour; /* hour of day, midnight = 0 */ 31280849Scy uint8_t minute; /* minute of hour */ 32280849Scy uint8_t second; /* second of minute */ 33280849Scy}; 34358659Scytypedef struct isodate TIsoDate; 35358659Scytypedef struct isodate const TcIsoDate; 36280849Scy 37280849Scy/* general split representation */ 38280849Scytypedef struct { 39280849Scy int32_t hi; 40280849Scy int32_t lo; 41280849Scy} ntpcal_split; 42280849Scy 43280849Scytypedef time_t (*systime_func_ptr)(time_t *); 44280849Scy 4554359Sroberto/* 46280849Scy * set the function for getting the system time. This is mostly used for 47280849Scy * unit testing to provide a fixed / shifted time stamp. Setting the 48280849Scy * value to NULL restores the original function, that is, 'time()', 49280849Scy * which is also the automatic default. 5054359Sroberto */ 51280849Scyextern systime_func_ptr ntpcal_set_timefunc(systime_func_ptr); 52280849Scy 53280849Scy/* 54280849Scy * days-of-week 55280849Scy */ 56280849Scy#define CAL_SUNDAY 0 57280849Scy#define CAL_MONDAY 1 58280849Scy#define CAL_TUESDAY 2 59280849Scy#define CAL_WEDNESDAY 3 60280849Scy#define CAL_THURSDAY 4 61280849Scy#define CAL_FRIDAY 5 62280849Scy#define CAL_SATURDAY 6 63280849Scy#define CAL_SUNDAY7 7 /* also sunday */ 64280849Scy 65280849Scy/* 66280849Scy * Days in each month. 30 days hath September... 67280849Scy */ 6854359Sroberto#define JAN 31 6954359Sroberto#define FEB 28 7054359Sroberto#define FEBLEAP 29 7154359Sroberto#define MAR 31 7254359Sroberto#define APR 30 7354359Sroberto#define MAY 31 7454359Sroberto#define JUN 30 7554359Sroberto#define JUL 31 7654359Sroberto#define AUG 31 7754359Sroberto#define SEP 30 7854359Sroberto#define OCT 31 7954359Sroberto#define NOV 30 8054359Sroberto#define DEC 31 8154359Sroberto 8254359Sroberto/* 83280849Scy * We deal in a 4 year cycle starting at March 1, 1900. We assume 8454359Sroberto * we will only want to deal with dates since then, and not to exceed 8554359Sroberto * the rollover day in 2036. 8654359Sroberto */ 8754359Sroberto#define SECSPERMIN (60) /* seconds per minute */ 8854359Sroberto#define MINSPERHR (60) /* minutes per hour */ 8954359Sroberto#define HRSPERDAY (24) /* hours per day */ 90282408Scy#define DAYSPERWEEK (7) /* days per week */ 9154359Sroberto#define DAYSPERYEAR (365) /* days per year */ 9254359Sroberto 93280849Scy#define SECSPERHR (SECSPERMIN * MINSPERHR) 94280849Scy#define SECSPERDAY (SECSPERHR * HRSPERDAY) 95282408Scy#define SECSPERWEEK (DAYSPERWEEK * SECSPERDAY) 96280849Scy#define SECSPERYEAR (365 * SECSPERDAY) /* regular year */ 9754359Sroberto#define SECSPERLEAPYEAR (366 * SECSPERDAY) /* leap year */ 98282408Scy#define SECSPERAVGYEAR 31556952 /* mean year length over 400yrs */ 9954359Sroberto 100344884Scy#define GPSWEEKS 1024 /* GPS week cycle */ 10154359Sroberto/* 102280849Scy * Gross hacks. I have illicit knowlege that there won't be overflows 10354359Sroberto * here, the compiler often can't tell this. 10454359Sroberto */ 105280849Scy#define TIMES60(val) ((((val)<<4) - (val))<<2) /* *(16 - 1) * 4 */ 10654359Sroberto#define TIMES24(val) (((val)<<4) + ((val)<<3)) /* *16 + *8 */ 107280849Scy#define TIMES7(val) (((val)<<3) - (val)) /* *8 - *1 */ 10854359Sroberto#define TIMESDPERC(val) (((val)<<10) + ((val)<<8) \ 10954359Sroberto + ((val)<<7) + ((val)<<5) \ 11054359Sroberto + ((val)<<4) + ((val)<<2) + (val)) /* *big* hack */ 11154359Sroberto 112280849Scy 113280849Scyextern const char * const months[12]; 114280849Scyextern const char * const daynames[7]; 115280849Scy 116358659Scyextern char * ntpcal_iso8601std(char*, size_t, struct calendar const*); 117280849Scyextern void caljulian (uint32_t, struct calendar *); 118280849Scyextern uint32_t caltontp (const struct calendar *); 119280849Scy 12054359Sroberto/* 121280849Scy * Convert between 'time_t' and 'vint64' 12254359Sroberto */ 123280849Scyextern vint64 time_to_vint64(const time_t *); 124282408Scyextern time_t vint64_to_time(const vint64 *); 12554359Sroberto 12654359Sroberto/* 127280849Scy * Get the build date & time. ATTENTION: The time zone is not specified! 128280849Scy * This depends entirely on the C compilers' capabilities to properly 129280849Scy * expand the '__TIME__' and '__DATE__' macros, as required by the C 130280849Scy * standard. 13154359Sroberto */ 132280849Scyextern int 133280849Scyntpcal_get_build_date(struct calendar * /* jd */); 13454359Sroberto 135280849Scy/* 136280849Scy * Convert a timestamp in NTP scale to a time_t value in the UN*X 137280849Scy * scale with proper epoch unfolding around a given pivot or the 138280849Scy * current system time. 139280849Scy */ 140280849Scyextern vint64 141280849Scyntpcal_ntp_to_time(uint32_t /* ntp */, const time_t * /* pivot */); 14254359Sroberto 143280849Scy/* 144280849Scy * Convert a timestamp in NTP scale to a 64bit seconds value in the NTP 145280849Scy * scale with proper epoch unfolding around a given pivot or the current 146280849Scy * system time. 147280849Scy * Note: The pivot must be given in UN*X time scale! 148280849Scy */ 149280849Scyextern vint64 150280849Scyntpcal_ntp_to_ntp(uint32_t /* ntp */, const time_t * /* pivot */); 15154359Sroberto 15254359Sroberto/* 153280849Scy * Split a time stamp in seconds into elapsed days and elapsed seconds 154280849Scy * since midnight. 155280849Scy */ 156280849Scyextern ntpcal_split 157280849Scyntpcal_daysplit(const vint64 *); 158280849Scy 159280849Scy/* 160358659Scy * Split a time stamp in seconds into elapsed weeks and elapsed seconds 161358659Scy * since start of week. 162358659Scy */ 163358659Scyextern ntpcal_split 164358659Scyntpcal_weeksplit(const vint64 *); 165358659Scy 166358659Scy/* 167280849Scy * Merge a number of days and a number of seconds into seconds, 168280849Scy * expressed in 64 bits to avoid overflow. 169280849Scy */ 170280849Scyextern vint64 171280849Scyntpcal_dayjoin(int32_t /* days */, int32_t /* seconds */); 172280849Scy 173358659Scy/* 174358659Scy * Merge a number of weeks and a number of seconds into seconds, 175358659Scy * expressed in 64 bits to avoid overflow. 176358659Scy */ 177358659Scyextern vint64 178358659Scyntpcal_weekjoin(int32_t /* weeks */, int32_t /* seconds */); 179358659Scy 180289764Sglebius/* Get the number of leap years since epoch for the number of elapsed 181289764Sglebius * full years 182289764Sglebius */ 183289764Sglebiusextern int32_t 184289764Sglebiusntpcal_leapyears_in_years(int32_t /* years */); 185289764Sglebius 186280849Scy/* 187280849Scy * Convert elapsed years in Era into elapsed days in Era. 188280849Scy */ 189280849Scyextern int32_t 190280849Scyntpcal_days_in_years(int32_t /* years */); 191280849Scy 192280849Scy/* 193280849Scy * Convert a number of elapsed month in a year into elapsed days 194280849Scy * in year. 195280849Scy * 196280849Scy * The month will be normalized, and 'res.hi' will contain the 197280849Scy * excessive years that must be considered when converting the years, 198280849Scy * while 'res.lo' will contain the days since start of the 199280849Scy * year. (Expect the resulting days to be negative, with a positive 200280849Scy * excess! But then, we need no leap year flag, either...) 201280849Scy */ 202280849Scyextern ntpcal_split 203280849Scyntpcal_days_in_months(int32_t /* months */); 204280849Scy 205280849Scy/* 206280849Scy * Convert ELAPSED years/months/days of gregorian calendar to elapsed 207280849Scy * days in Gregorian epoch. No range checks done here! 208280849Scy */ 209280849Scyextern int32_t 210280849Scyntpcal_edate_to_eradays(int32_t /* years */, int32_t /* months */, int32_t /* mdays */); 211280849Scy 212280849Scy/* 213280849Scy * Convert a time spec to seconds. No range checks done here! 214280849Scy */ 215280849Scyextern int32_t 216280849Scyntpcal_etime_to_seconds(int32_t /* hours */, int32_t /* minutes */, int32_t /* seconds */); 217280849Scy 218280849Scy/* 219280849Scy * Convert ELAPSED years/months/days of gregorian calendar to elapsed 220280849Scy * days in year. 221280849Scy * 222280849Scy * Note: This will give the true difference to the start of the given year, 223280849Scy * even if months & days are off-scale. 224280849Scy */ 225280849Scyextern int32_t 226280849Scyntpcal_edate_to_yeardays(int32_t /* years */, int32_t /* months */, int32_t /* mdays */); 227280849Scy 228280849Scy/* 229280849Scy * Convert the date part of a 'struct tm' (that is, year, month, 230280849Scy * day-of-month) into the RataDie of that day. 231280849Scy */ 232280849Scyextern int32_t 233280849Scyntpcal_tm_to_rd(const struct tm * /* utm */); 234280849Scy 235280849Scy/* 236280849Scy * Convert the date part of a 'struct calendar' (that is, year, month, 237280849Scy * day-of-month) into the RataDie of that day. 238280849Scy */ 239280849Scyextern int32_t 240280849Scyntpcal_date_to_rd(const struct calendar * /* jt */); 241280849Scy 242280849Scy/* 243280849Scy * Given the number of elapsed days in the calendar era, split this 244280849Scy * number into the number of elapsed years in 'res.quot' and the 245280849Scy * number of elapsed days of that year in 'res.rem'. 246280849Scy * 247280849Scy * if 'isleapyear' is not NULL, it will receive an integer that is 0 248280849Scy * for regular years and a non-zero value for leap years. 249289764Sglebius * 250289764Sglebius * The input is limited to [-2^30, 2^30-1]. If the days exceed this 251289764Sglebius * range, errno is set to EDOM and the result is saturated. 252280849Scy */ 253280849Scyextern ntpcal_split 254280849Scyntpcal_split_eradays(int32_t /* days */, int/*BOOL*/ * /* isleapyear */); 255280849Scy 256280849Scy/* 257280849Scy * Given a number of elapsed days in a year and a leap year indicator, 258280849Scy * split the number of elapsed days into the number of elapsed months 259280849Scy * in 'res.quot' and the number of elapsed days of that month in 260280849Scy * 'res.rem'. 261280849Scy */ 262280849Scyextern ntpcal_split 263280849Scyntpcal_split_yeardays(int32_t /* eyd */, int/*BOOL*/ /* isleapyear */); 264280849Scy 265280849Scy/* 266280849Scy * Convert a RataDie number into the date part of a 'struct 267280849Scy * calendar'. Return 0 if the year is regular year, !0 if the year is 268280849Scy * a leap year. 269280849Scy */ 270280849Scyextern int/*BOOL*/ 271280849Scyntpcal_rd_to_date(struct calendar * /* jt */, int32_t /* rd */); 272280849Scy 273280849Scy/* 274280849Scy * Convert a RataDie number into the date part of a 'struct 275280849Scy * tm'. Return 0 if the year is regular year, !0 if the year is a leap 276280849Scy * year. 277280849Scy */ 278280849Scyextern int/*BOOL*/ 279280849Scyntpcal_rd_to_tm(struct tm * /* utm */, int32_t /* rd */); 280280849Scy 281280849Scy/* 282280849Scy * Take a value of seconds since midnight and split it into hhmmss in 283280849Scy * a 'struct calendar'. Return excessive days. 284280849Scy */ 285280849Scyextern int32_t 286280849Scyntpcal_daysec_to_date(struct calendar * /* jt */, int32_t /* secs */); 287280849Scy 288280849Scy/* 289280849Scy * Take the time part of a 'struct calendar' and return the seconds 290280849Scy * since midnight. 291280849Scy */ 292280849Scyextern int32_t 293280849Scyntpcal_date_to_daysec(const struct calendar *); 294280849Scy 295280849Scy/* 296280849Scy * Take a value of seconds since midnight and split it into hhmmss in 297280849Scy * a 'struct tm'. Return excessive days. 298280849Scy */ 299280849Scyextern int32_t 300280849Scyntpcal_daysec_to_tm(struct tm * /* utm */, int32_t /* secs */); 301280849Scy 302280849Scyextern int32_t 303280849Scyntpcal_tm_to_daysec(const struct tm * /* utm */); 304280849Scy 305280849Scy/* 306280849Scy * convert a year number to rata die of year start 307280849Scy */ 308280849Scyextern int32_t 309280849Scyntpcal_year_to_ystart(int32_t /* year */); 310280849Scy 311280849Scy/* 312280849Scy * For a given RataDie, get the RataDie of the associated year start, 313280849Scy * that is, the RataDie of the last January,1st on or before that day. 314280849Scy */ 315280849Scyextern int32_t 316280849Scyntpcal_rd_to_ystart(int32_t /* rd */); 317280849Scy 318280849Scy/* 319280849Scy * convert a RataDie to the RataDie of start of the calendar month. 320280849Scy */ 321280849Scyextern int32_t 322280849Scyntpcal_rd_to_mstart(int32_t /* year */); 323280849Scy 324280849Scy 325280849Scyextern int 326280849Scyntpcal_daysplit_to_date(struct calendar * /* jt */, 327280849Scy const ntpcal_split * /* ds */, int32_t /* dof */); 328280849Scy 329280849Scyextern int 330280849Scyntpcal_daysplit_to_tm(struct tm * /* utm */, const ntpcal_split * /* ds */, 331280849Scy int32_t /* dof */); 332280849Scy 333280849Scyextern int 334280849Scyntpcal_time_to_date(struct calendar * /* jd */, const vint64 * /* ts */); 335280849Scy 336280849Scyextern int32_t 337280849Scyntpcal_periodic_extend(int32_t /* pivot */, int32_t /* value */, 338280849Scy int32_t /* cycle */); 339280849Scy 340280849Scyextern int 341280849Scyntpcal_ntp64_to_date(struct calendar * /* jd */, const vint64 * /* ntp */); 342280849Scy 343280849Scyextern int 344280849Scyntpcal_ntp_to_date(struct calendar * /* jd */, uint32_t /* ntp */, 345280849Scy const time_t * /* pivot */); 346280849Scy 347280849Scyextern vint64 348280849Scyntpcal_date_to_ntp64(const struct calendar * /* jd */); 349280849Scy 350280849Scyextern uint32_t 351280849Scyntpcal_date_to_ntp(const struct calendar * /* jd */); 352280849Scy 353280849Scyextern time_t 354280849Scyntpcal_date_to_time(const struct calendar * /* jd */); 355280849Scy 356280849Scy/* 357280849Scy * ISO week-calendar conversions 358280849Scy */ 359280849Scyextern int32_t 360280849Scyisocal_weeks_in_years(int32_t /* years */); 361280849Scy 362289764Sglebius/* 363289764Sglebius * The input is limited to [-2^30, 2^30-1]. If the weeks exceed this 364289764Sglebius * range, errno is set to EDOM and the result is saturated. 365289764Sglebius */ 366280849Scyextern ntpcal_split 367280849Scyisocal_split_eraweeks(int32_t /* weeks */); 368280849Scy 369280849Scyextern int 370280849Scyisocal_ntp64_to_date(struct isodate * /* id */, const vint64 * /* ntp */); 371280849Scy 372280849Scyextern int 373280849Scyisocal_ntp_to_date(struct isodate * /* id */, uint32_t /* ntp */, 374280849Scy const time_t * /* pivot */); 375280849Scy 376280849Scyextern vint64 377280849Scyisocal_date_to_ntp64(const struct isodate * /* id */); 378280849Scy 379280849Scyextern uint32_t 380280849Scyisocal_date_to_ntp(const struct isodate * /* id */); 381280849Scy 382280849Scy 383280849Scy/* 384280849Scy * day-of-week calculations 385280849Scy * 386280849Scy * Given a RataDie and a day-of-week, calculate a RDN that is reater-than, 387280849Scy * greater-or equal, closest, less-or-equal or less-than the given RDN 388280849Scy * and denotes the given day-of-week 389280849Scy */ 390280849Scyextern int32_t 391280849Scyntpcal_weekday_gt(int32_t /* rdn */, int32_t /* dow */); 392280849Scy 393280849Scyextern int32_t 394280849Scyntpcal_weekday_ge(int32_t /* rdn */, int32_t /* dow */); 395280849Scy 396280849Scyextern int32_t 397280849Scyntpcal_weekday_close(int32_t /* rdn */, int32_t /* dow */); 398280849Scy 399280849Scyextern int32_t 400280849Scyntpcal_weekday_le(int32_t /* rdn */, int32_t /* dow */); 401280849Scy 402280849Scyextern int32_t 403280849Scyntpcal_weekday_lt(int32_t /* rdn */, int32_t /* dow */); 404280849Scy 405330106Sdelphij 406280849Scy/* 407330106Sdelphij * handling of base date spec 408330106Sdelphij */ 409330106Sdelphijextern int32_t 410330106Sdelphijbasedate_eval_buildstamp(void); 411330106Sdelphij 412330106Sdelphijextern int32_t 413330106Sdelphijbasedate_eval_string(const char *str); 414330106Sdelphij 415330106Sdelphijextern int32_t 416330106Sdelphijbasedate_set_day(int32_t dayno); 417330106Sdelphij 418330106Sdelphijextern uint32_t 419330106Sdelphijbasedate_get_day(void); 420330106Sdelphij 421330106Sdelphijextern time_t 422330106Sdelphijbasedate_get_eracenter(void); 423330106Sdelphij 424330106Sdelphijextern time_t 425330106Sdelphijbasedate_get_erabase(void); 426330106Sdelphij 427344884Scyextern uint32_t 428344884Scybasedate_get_gpsweek(void); 429330106Sdelphij 430344884Scyextern uint32_t 431344884Scybasedate_expand_gpsweek(unsigned short weekno); 432344884Scy 433330106Sdelphij/* 43454359Sroberto * Additional support stuff for Ed Rheingold's calendrical calculations 43554359Sroberto */ 43654359Sroberto 43754359Sroberto/* 438344884Scy * Start day of NTP time as days past 0000-12-31 in the proleptic 439344884Scy * Gregorian calendar. (So 0001-01-01 is day number 1; this is the Rata 440344884Scy * Die counting scheme used by Ed Rheingold in his book "Calendrical 441344884Scy * Calculations".) 44254359Sroberto */ 443280849Scy#define DAY_NTP_STARTS 693596 444280849Scy 44554359Sroberto/* 446280849Scy * Start day of the UNIX epoch. This is the Rata Die of 1970-01-01. 44754359Sroberto */ 448280849Scy#define DAY_UNIX_STARTS 719163 44954359Sroberto 45054359Sroberto/* 451344884Scy * Start day of the GPS epoch. This is the Rata Die of 1980-01-06 452344884Scy */ 453358659Scy#define DAY_GPS_STARTS 722820 454344884Scy 455344884Scy/* 456280849Scy * Difference between UN*X and NTP epoch (25567). 45754359Sroberto */ 458280849Scy#define NTP_TO_UNIX_DAYS (DAY_UNIX_STARTS - DAY_NTP_STARTS) 45954359Sroberto 46054359Sroberto/* 461344884Scy * Difference between GPS and NTP epoch (29224) 462344884Scy */ 463344884Scy#define NTP_TO_GPS_DAYS (DAY_GPS_STARTS - DAY_NTP_STARTS) 464344884Scy 465344884Scy/* 466280849Scy * Days in a normal 4 year leap year calendar cycle (1461). 46754359Sroberto */ 468344884Scy#define GREGORIAN_NORMAL_LEAP_CYCLE_DAYS (4 * 365 + 1) 46954359Sroberto 470280849Scy/* 471280849Scy * Days in a normal 100 year leap year calendar (36524). We lose a 472280849Scy * leap day in years evenly divisible by 100 but not by 400. 473280849Scy */ 474280849Scy#define GREGORIAN_NORMAL_CENTURY_DAYS \ 475280849Scy (25 * GREGORIAN_NORMAL_LEAP_CYCLE_DAYS - 1) 47654359Sroberto 477280849Scy/* 478280849Scy * The Gregorian calendar is based on a 400 year cycle. This is the 479280849Scy * number of days in each cycle (146097). We gain a leap day in years 480280849Scy * divisible by 400 relative to the "normal" century. 481280849Scy */ 482280849Scy#define GREGORIAN_CYCLE_DAYS (4 * GREGORIAN_NORMAL_CENTURY_DAYS + 1) 483280849Scy 484280849Scy/* 485280849Scy * Number of weeks in 400 years (20871). 486280849Scy */ 487280849Scy#define GREGORIAN_CYCLE_WEEKS (GREGORIAN_CYCLE_DAYS / 7) 488280849Scy 489358659Scy/* 490358659Scy * Is a Greogorian calendar year a leap year? The obvious solution is to 491358659Scy * test the expression 492358659Scy * 493358659Scy * (y % 4 == 0) && ((y % 100 != 0) || (y % 400 == 0)) 494358659Scy * 495358659Scy * This needs (in theory) 2 true divisions -- most compilers check the 496358659Scy * (mod 4) condition by doing a bit test. Some compilers have been 497358659Scy * even observed to partially fuse the (mod 100) and (mod 400) test, 498358659Scy * but there is an alternative formula that gives the compiler even 499358659Scy * better chances: 500358659Scy * 501358659Scy * (y % 4 == 0) && ((y % 16 == 0) || (y % 25 != 0)) 502358659Scy * 503358659Scy * The order of checks is chosen so that the shorcut evaluation can fix 504358659Scy * the result as soon as possible. And the compiler has to do only one 505358659Scy * true division here -- the (mod 4) and (mod 16) can be done with 506358659Scy * direct bit tests. *If* the compiler chooses to do so. 507358659Scy * 508358659Scy * The deduction is as follows: rewrite the standard formula as 509358659Scy * (y % 4 == 0) && ((y % 4*25 != 0) || (y % 16*25 == 0)) 510358659Scy * 511358659Scy * then split the congruences: 512358659Scy * (y % 4 == 0) && ((y % 4 != 0 || y % 25 != 0) || (y % 16 == 0 && y % 25 == 0)) 513358659Scy * 514358659Scy * eliminate the 1st inner term, as it is provably false: 515358659Scy * (y % 4 == 0) && (y % 25 != 0 || (y % 16 == 0 && y % 25 == 0)) 516358659Scy * 517358659Scy * Use the distributive laws on the second major group: 518358659Scy * (y % 4 == 0) && ((y % 25 != 0 || y % 16 == 0) && (y % 25 != 0 || y % 25 == 0)) 519358659Scy * 520358659Scy * Eliminate the constant term, reorder, and voila: 521358659Scy */ 522280849Scy 523358659Scystatic inline int 524358659Scyis_leapyear(int32_t y) { 525358659Scy return !(y % 4) && (!(y % 16) || (y % 25)); 526358659Scy} 527358659Scy/* The (mod 4) test eliminates 3/4 (or 12/16) of all values. 528358659Scy * The (mod 16) test eliminates another 1/16 of all values. 529358659Scy * 3/16 of all values reach the final division. 530358659Scy * Assuming that the true division is the most costly operation, this 531358659Scy * sequence should give most bang for the buck. 532358659Scy */ 533358659Scy 534358659Scy/* misc */ 535358659Scyextern int u32mod7(uint32_t x); 536358659Scyextern int i32mod7(int32_t x); 537358659Scyextern uint32_t i32fmod(int32_t x, uint32_t d); 538358659Scy 539358659Scyextern int32_t ntpcal_expand_century(uint32_t y, uint32_t m, uint32_t d, uint32_t wd); 540358659Scy 54154359Sroberto#endif 542