The clockfilter procedure is executed upon arrival of an NTP
message or other event that results in new data samples. It takes arguments of the form theta, delta, epsilon, where theta is a sample
clock offset measurement and delta and epsilon are the associated roundtrip delay and dispersion. It determines the filtered clock
offset (peer.offset), roundtrip delay (peer.delay) and dispersion (peer.dispersion). It also updates the dispersion of samples already
recorded and saves the current time (peer.update).
The basis of the clockfilter procedure is the filter shift register (peer.filter), which consists of NTP.SHIFT stages, each stage
containing a 3tuple [ theta sub i , delta sub i , epsilon sub i ], with indices numbered from zero on the left. The filter is
initialized with the value [0,0, NTP.MAXDISPERSE] in all stages by the clear procedure. New data samples are shifted into the filter
at the left end, causing first NULLs then old samples to fall off the right end. The packet procedure provides samples of the form
[theta, delta, epsilon] as new updates arrive, while the transmit procedure provides samples of the form [0,0, NTP.MAXDISPERSE] when
two poll intervals elapse without a fresh update. While the same symbols (theta ,delta ,epsilon) are used here for the arguments,
clockfilter contents and peer variables, the meaning will be clear from context. The following pseudocode describes this
procedure.
begin clockfilter procedure (theta ,delta ,epsilon)
The dispersion epsilon sub i for all valid samples in the filter register must be updated to account for the skewerror accumulation
since the last update. These samples are also inserted on a temporary list with entry format [distance,index]. The samples in the
register are shifted right one stage, with the overflow sample discarded and the new sample inserted at the leftmost stage. The
temporary list is then sorted by increasing distance. If no samples remain in the list, the procedure exits without updating the peer
variables.
for (i from NTP.SIZE  1 to 1) begin /* update dispersion */
[ theta sub i ,delta sub i ,epsilon sub i ] < [theta sub {i1} ,delta sub {i1} ,epsilon sub {i1} ];
/*
shift stage right */
epsilon sub i = epsilon sub i + phi tau;
add [ lambda sub i == epsilon sub i + { delta sub i } over 2 , i] to temporary list;
endfor;
[ theta sub 0 ,delta sub 0 ,epsilon sub 0 ] < [ theta ,delta ,epsilon ]; /* insert new sample */
add [ lambda == epsilon + { delta } over 2 ,0] to temporary list;
peer.update < sys.clock; /* reset base time */
sort temporary list by increasing [distance index];
where [distance index] represents the concatenation of the distance and index fields and distance is the highorder field. The
filter dispersion epsilon sub sigma is computed and included in the peer dispersion. Note that for this purpose the temporary list is
already sorted.
epsilon sub sigma < 0;
for (i from NTP.SHIFT  1 to 0) /* compute filter dispersion */
if (peer.dispersion sub index[i] >= NTP.MAXDISPERSE or
 theta sub i  theta sub 0  > NTP.MAXDISPERSE
epsilon sub sigma < epsilon sub sigma + NTP.MAXDISPERSE) times NTP.FILTER;
else
epsilon sub sigma < ( epsilon sub sigma +  theta sub i  theta sub 0 ) times NTP.FILTER;
The peer offset theta sub 0, delay delta sub 0 and dispersion epsilon sub 0 are chosen as the values corresponding to the
minimumdistance sample; in other words, the sample corresponding to the first entry on the temporary list, here represented as the
0th subscript.
peer.offset < theta sub 0; /* update peer variables */
peer.delay < delta sub 0;
peer.dispersion < min ( epsilon sub 0 + epsilon sub sigma , NTP.MAXDISPERSE);
end clockfilter procedure
The peer.offset and peer.delay variables represent the clock offset and roundtrip delay of the local clock relative to the peer clock.
Both of these are precision quantities and can usually be averaged over long intervals in order to improve accuracy and stability
without bias accumulation (see Appendix H). The peer.dispersion variable represents
the maximum error due to measurement error, skewerror accumulation and sample variance. All three variables are used in the
clockselection and clockcombining procedures to select the peer clock(s) used for synchronization and to maximize the accuracy and
stability of the indications.

