Left uncorrected, the local clock runs at the offset and
frequency resulting from its last update. An update is produced by an event that results in a valid clock selection. It consists of a
signed 48-bit integer in whole milliseconds and fraction, with fraction point to the left of bit 32. If the magnitude is greater than
the maximum aperture CLOCK.MAX, a step adjustment is required, in which case proceed as described later. Otherwise, a gradual phase
adjustment is performed. Normally, the update is computed by the NTP algorithms described previously; however, if the PPS counter is
greater than zero, the value of the PPS-Adjust register is used instead. Let u be a 32-bit quantity with bits 0-31 set as bits 16-47
of the update. If some of the low-order bits of the update are unimplemented, they are set as the value of the sign bit. These
operations move the fraction point of u to the left of bit 16 and minimize the effects of truncation and roundoff errors. Let b be the
number of leading zeros of the absolute value of the Compliance register and let c be the number of leading zeros of the Watchdog
counter, both of which are easily computed by compact loops. Then, set b to
b = b - 16 + CLOCK.COMP
and clamp it to be not less than zero. This represents the logarithm of the loop time constant. Then, set c to
c = 10 - c
and clamp it to be not greater than NTP.MAXPOLL - NTP.MINPOLL. This represents the logarithm of the integration interval since the
last update. The clamps insure stable operation under typical conditions encountered in the Internet. Then, compute new values for the
Clock-Adjust and Skew-Compensation registers
x = u >> b ,
y = y + (u >> (b + b - c)).
Finally, compute the exponential average
z = z + (u << (b + CLOCK.MULT) - z) >> CLOCK.WEIGHT,
where the left shift realigns the fraction point for greater precision and ease of computation.
At each adjustment interval the final clock correction consisting of two components is determined. The first (phase) component
consists of the quantity
x >> CLOCK.PHASE> ,
which is then subtracted from the previous contents of the Clock-Adjust register to form the new contents of that register. The second
(frequency) component consists of the quantity
y >> CLOCK.FREQ.
The sum of the phase and frequency components is the final clock correction, which is then added to the Clock register. Finally, the
Watchdog counter is set to zero. Operation continues in this way until a
new correction is introduced.
The value of b computed above can be used to update the poll interval system variable (sys.poll). This functions as an adaptive
parameter that provides a very valuable feature which reduces the polling overhead, especially if the clock-combining algorithm
described in Appendix F is used:
sys.poll <-- b + NTP.MINPOLL.
Under conditions when update noise is high or the hardware oscillator frequency is changing relatively rapidly due to environmental
conditions, the magnitude of the compliance increases. With the parameters specified, this causes the loop bandwidth (reciprocal of
time constant) to increase and the poll interval to decrease, eventually to NTP.MINPOLL seconds. When noise is low and the hardware
oscillator very stable, the compliance decreases, which causes the loop bandwidth to decrease and the poll interval to increase,
eventually to NTP.MAXPOLL seconds.
The parameters in Table 6 have been selected so that, under good conditions with updates in the order of a few milliseconds, a
precision of a millisecond per day (about .01 ppm or 10-8), can be achieved. Care is required in the implementation to insure
monotonicity of the Clock register and to preserve the highest precision while minimizing the propagation of roundoff errors. Since
all of the multiply/divide operations (except those involved with the 1-pps pulses) computed in real time can be approximated by
bitwise-shift operations, it is not necessary to implement a full multiply/divide capability in hardware or
In the various implementations of NTP for many Unix-based systems it has been the common experience that the single most important
factor affecting local-clock stability is the matching of the phase and frequency coefficients to the particular kernel
implementation. It is vital that these coefficients be engineered according to the model values, for otherwise the PLL can fail to
track normal oscillator
variations and can even become unstable.