ntp_fp.h revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* Copyright (c) 1996 by Sun Microsystems, Inc.
* All Rights Reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* ntp_fp.h - definitions for NTP fixed point arithmetic
*/
#include "ntp_types.h"
/*
* NTP uses two fixed point formats. The first (l_fp) is the "long" format
* and is 64 bits long with the decimal between bits 31 and 32. This
* is used for time stamps in the NTP packet header (in network byte
* order) and for internal computations of offsets (in local host byte
* order). We use the same structure for both signed and unsigned values,
* which is a big hack but saves rewriting all the operators twice. Just
* to confuse this, we also sometimes just carry the fractional part in
* calculations, in both signed and unsigned forms. Anyway, an l_fp looks
* like:
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Integral Part |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Fractional Part |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
typedef struct {
union {
} Ul_i;
union {
} Ul_f;
} l_fp;
/*
* Fractional precision (of an l_fp) is actually the number of
* bits in a long.
*/
#define FRACTION_PREC (32)
/*
* The second fixed point format is 32 bits, with the decimal between
* bits 15 and 16. There is a signed version (s_fp) and an unsigned
* version (u_fp). This is used to represent synchronizing distance
* and synchronizing dispersion in the NTP packet header (again, in
* network byte order) and internally to hold both distance and
* dispersion values (in local byte order). In network byte order
* it looks like:
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Integer Part | Fraction Part |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
/*
* A unit second in fp format. Actually 2**(half_the_bits_in_a_long)
*/
#define FP_SECOND (0x10000)
/*
* Byte order conversions
*/
/* funny ones. Converts ts fractions to net order ts */
if ((f) & 0x80000000) \
else \
} while (0)
/*
* Conversions between the two fixed point types
*/
/*
* Primitive operations on long fixed point values. If these are
* reminiscent of assembler op codes it's only because some may
* be replaced by inline assembler for particular machines someday.
* These are the (kind of inefficient) run-anywhere versions.
*/
do { \
if ((v_f) == 0) \
else { \
} \
} while(0)
do { \
if ((a_f) == 0) { \
(r_f) = 0; \
} else { \
} \
} while(0)
do { \
\
if (lo_tmp & 0x10000) \
hi_tmp++; \
\
if (hi_tmp & 0x10000) \
(r_i)++; \
} while (0)
do { \
\
if (lo_tmp & 0x10000) \
hi_tmp++; \
\
if (hi_tmp & 0x10000) \
lo_tmp++; \
if (lo_tmp & 0x10000) \
hi_tmp++; \
\
if (hi_tmp & 0x10000) \
(r_ovr)++; \
} while (0)
do { \
\
if ((a_f) == 0) { \
} else { \
if (lo_tmp & 0x10000) \
hi_tmp++; \
\
if (hi_tmp & 0x10000) \
(r_i)++; \
} \
} while (0)
do { \
if ((v_i) & 01) \
(v_f) |= 0x80000000; \
} while (0)
do { \
if ((v_i) & 01) \
(v_f) |= 0x80000000; \
if ((v_i) & 0x80000000) \
else \
} while (0)
do { \
(v_i) <<= 1; \
if ((v_f) & 0x80000000) \
(v_i) |= 0x1; \
(v_f) <<= 1; \
} while (0)
do { \
(v_ovr) <<= 1; \
if ((v_i) & 0x80000000) \
(v_ovr) |= 0x1; \
(v_i) <<= 1; \
if ((v_f) & 0x80000000) \
(v_i) |= 0x1; \
(v_f) <<= 1; \
} while (0)
do { \
if ((f) > 0) \
else if ((f) < 0) \
} while(0)
(((v_i) & 0x80000000) != 0)
/*
* Operations on the long fp format
*/
extern char * prettydate P((l_fp *));
extern void get_systime P((l_fp *));
extern int step_systime P((l_fp *));
extern int step_systime_real P((l_fp *));
extern int adj_systime P((l_fp *));