[ntp:questions] Re: Clock accuracy & auto setting : digital television does a crap job of providing time services...

Terje Mathisen terje.mathisen at hda.hydro.com
Thu May 4 06:52:51 UTC 2006

user at domain.invalid wrote:
> Max,
> Have you seen the white paper "The NTP Era and Era Numbering" on the
> NTP project page at www.ntp.org
> http://www.eecis.udel.edu/~mills/y2k.html? It includes a 128-bit date
> format, which  has enough seconds bits to measure the age of the
> Universe until the Sun grows dim and enough fraction bits to measure
> the time a photon crosses an atomic nucleus. The mapping to and from
> this format and NTP timestamps is transparent, even when the NTP era
> rolls in 2036, 2172, ...

I just started reading that paper, and I've found a bug/typo:

> The era number is the integer quotient 2^32 / s and the timstamp is
> the integer s mod 2^32.

The first operations should of course be s / 2^32, not the reciprocal!

BTW, it is only when working with unsigned integers that the C standard 
guarantees that subtraction of two values will behave as required by 
NTP, in your paper you implicitly acknowledge this by stating the need 
for twos-complement arithmetic. :-)

It seems to me that for absolute maximum portability, the subtractions 
could be done on unsigned values, then the result inspected:

If the high (sign) bit is set, negate the 64-bit result manually (using 
twos-complement rules) and remember the sign bit. Next convert the 
(small) positive value to double, then re-apply the correct sign bit:

double ntp_diff(uint32_t ah, uint32_t al, uint32_t bh, uint32_t bl)
/* Calculate A-B and return the result as a double: */
   uint32_t dl, dh;
   double d, sign;

   dl = al - bl;
   dh = ah - bh;
   if (dl > al) { /* Wrap-around, so borrow: */

   sign = 1.0;
   if (dh & 0x80000000) { /* Negative difference? */
     sign = -1.0;
     /* Negate by inverting all bits... */
     dl = ~dl;
     dh = ~dh;
     /* ... and increment the result, taking care of any carries: */
     if (++dl == 0) {
       if (dh == 0x80000000) { /* Maximal negative value: -2^31 */
         return -65536.0*32768.0;
   d = (double) dl;
   d *= 1.0/(65536.0*65536.0); /* Shift the fractional bits down */
   d += (double) dh;

   d *= sign;

   return d;

(I believe that this is probably one of the smaller problems you'd have 
if/when porting NTP to something like a 60-bit sign-magnitude machine. :-)

- <Terje.Mathisen at hda.hydro.com>
"almost all programming can be viewed as an exercise in caching"

More information about the questions mailing list