source: trunk/third/xntp/include/ntp_fp.h @ 10832

Revision 10832, 9.9 KB checked in by brlewis, 27 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r10831, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * ntp_fp.h - definitions for NTP fixed point arithmetic
3 */
4
5#include <sys/types.h>
6#include <sys/socket.h>
7#include <netinet/in.h>
8
9#include "ntp_types.h"
10
11/*
12 * NTP uses two fixed point formats.  The first (l_fp) is the "long" format
13 * and is 64 bits long with the decimal between bits 31 and 32.  This
14 * is used for time stamps in the NTP packet header (in network byte
15 * order) and for internal computations of offsets (in local host byte
16 * order).  We use the same structure for both signed and unsigned values,
17 * which is a big hack but saves rewriting all the operators twice.  Just
18 * to confuse this, we also sometimes just carry the fractional part in
19 * calculations, in both signed and unsigned forms.  Anyway, an l_fp looks
20 * like:
21 *
22 *    0                   1                   2                   3
23 *    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
24 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25 *   |                         Integral Part                         |
26 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
27 *   |                         Fractional Part                       |
28 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29 *
30 */
31typedef struct {
32        union {
33                u_int32 Xl_ui;
34                int32 Xl_i;
35        } Ul_i;
36        union {
37                u_int32 Xl_uf;
38                int32 Xl_f;
39        } Ul_f;
40} l_fp;
41
42#define l_ui    Ul_i.Xl_ui              /* unsigned integral part */
43#define l_i     Ul_i.Xl_i               /* signed integral part */
44#define l_uf    Ul_f.Xl_uf              /* unsigned fractional part */
45#define l_f     Ul_f.Xl_f               /* signed fractional part */
46
47/*
48 * Fractional precision (of an l_fp) is actually the number of
49 * bits in a long.
50 */
51#define FRACTION_PREC   (32)
52
53
54/*
55 * The second fixed point format is 32 bits, with the decimal between
56 * bits 15 and 16.  There is a signed version (s_fp) and an unsigned
57 * version (u_fp).  This is used to represent synchronizing distance
58 * and synchronizing dispersion in the NTP packet header (again, in
59 * network byte order) and internally to hold both distance and
60 * dispersion values (in local byte order).  In network byte order
61 * it looks like:
62 *
63 *    0                   1                   2                   3
64 *    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
65 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66 *   |            Integer Part       |     Fraction Part             |
67 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
68 *
69 */
70typedef int32 s_fp;
71typedef u_int32 u_fp;
72
73/*
74 * A unit second in fp format.  Actually 2**(half_the_bits_in_a_long)
75 */
76#define FP_SECOND       (0x10000)
77
78/*
79 * Byte order conversions
80 */
81#define HTONS_FP(x)     (htonl(x))
82#define HTONL_FP(h, n)  do { (n)->l_ui = htonl((h)->l_ui); \
83                             (n)->l_uf = htonl((h)->l_uf); } while (0)
84#define NTOHS_FP(x)     (ntohl(x))
85#define NTOHL_FP(n, h)  do { (h)->l_ui = ntohl((n)->l_ui); \
86                             (h)->l_uf = ntohl((n)->l_uf); } while (0)
87#define NTOHL_MFP(ni, nf, hi, hf) \
88        do { (hi) = ntohl(ni); (hf) = ntohl(nf); } while (0)
89#define HTONL_MFP(hi, hf, ni, nf) \
90        do { (ni) = ntohl(hi); (nf) = ntohl(hf); } while (0)
91
92/* funny ones.  Converts ts fractions to net order ts */
93#define HTONL_UF(uf, nts) \
94        do { (nts)->l_ui = 0; (nts)->l_uf = htonl(uf); } while (0)
95#define HTONL_F(f, nts) do { (nts)->l_uf = htonl(f); \
96                                if ((f) & 0x80000000) \
97                                        (nts)->l_i = -1; \
98                                else \
99                                        (nts)->l_i = 0; \
100                        } while (0)
101
102/*
103 * Conversions between the two fixed point types
104 */
105#define MFPTOFP(x_i, x_f)       (((x_i) >= 0x00010000) ? 0x7fffffff : \
106                                (((x_i) <= -0x00010000) ? 0x80000000 : \
107                                (((x_i)<<16) | (((x_f)>>16)&0xffff))))
108#define LFPTOFP(v)              MFPTOFP((v)->l_i, (v)->l_f)
109
110#define UFPTOLFP(x, v) ((v)->l_ui = (u_fp)(x)>>16, (v)->l_uf = (x)<<16)
111#define FPTOLFP(x, v)  (UFPTOLFP((x), (v)), (x) < 0 ? (v)->l_ui -= 0x10000 : 0)
112
113#define MAXLFP(v) ((v)->l_ui = 0x7fffffff, (v)->l_uf = 0xffffffff)
114#define MINLFP(v) ((v)->l_ui = 0x80000000, (v)->l_uf = 0)
115
116/*
117 * Primitive operations on long fixed point values.  If these are
118 * reminiscent of assembler op codes it's only because some may
119 * be replaced by inline assembler for particular machines someday.
120 * These are the (kind of inefficient) run-anywhere versions.
121 */
122#define M_NEG(v_i, v_f)         /* v = -v */ \
123        do { \
124                if ((v_f) == 0) \
125                        (v_i) = -((s_fp)(v_i)); \
126                else { \
127                        (v_f) = -((s_fp)(v_f)); \
128                        (v_i) = ~(v_i); \
129                } \
130        } while(0)
131
132#define M_NEGM(r_i, r_f, a_i, a_f)      /* r = -a */ \
133        do { \
134                if ((a_f) == 0) { \
135                        (r_f) = 0; \
136                        (r_i) = -(a_i); \
137                } else { \
138                        (r_f) = -(a_f); \
139                        (r_i) = ~(a_i); \
140                } \
141        } while(0)
142
143#define M_ADD(r_i, r_f, a_i, a_f)       /* r += a */ \
144        do { \
145                register u_int32 lo_tmp; \
146                register u_int32 hi_tmp; \
147                \
148                lo_tmp = ((r_f) & 0xffff) + ((a_f) & 0xffff); \
149                hi_tmp = (((r_f) >> 16) & 0xffff) + (((a_f) >> 16) & 0xffff); \
150                if (lo_tmp & 0x10000) \
151                        hi_tmp++; \
152                (r_f) = ((hi_tmp & 0xffff) << 16) | (lo_tmp & 0xffff); \
153                \
154                (r_i) += (a_i); \
155                if (hi_tmp & 0x10000) \
156                        (r_i)++; \
157        } while (0)
158
159#define M_ADD3(r_ovr, r_i, r_f, a_ovr, a_i, a_f) /* r += a, three word */ \
160        do { \
161                register u_int32 lo_tmp; \
162                register u_int32 hi_tmp; \
163                \
164                lo_tmp = ((r_f) & 0xffff) + ((a_f) & 0xffff); \
165                hi_tmp = (((r_f) >> 16) & 0xffff) + (((a_f) >> 16) & 0xffff); \
166                if (lo_tmp & 0x10000) \
167                        hi_tmp++; \
168                (r_f) = ((hi_tmp & 0xffff) << 16) | (lo_tmp & 0xffff); \
169                \
170                lo_tmp = ((r_i) & 0xffff) + ((a_i) & 0xffff); \
171                if (hi_tmp & 0x10000) \
172                        lo_tmp++; \
173                hi_tmp = (((r_i) >> 16) & 0xffff) + (((a_i) >> 16) & 0xffff); \
174                if (lo_tmp & 0x10000) \
175                        hi_tmp++; \
176                (r_i) = ((hi_tmp & 0xffff) << 16) | (lo_tmp & 0xffff); \
177                \
178                (r_ovr) += (a_ovr); \
179                if (hi_tmp & 0x10000) \
180                        (r_ovr)++; \
181        } while (0)
182
183#define M_SUB(r_i, r_f, a_i, a_f)       /* r -= a */ \
184        do { \
185                register u_int32 lo_tmp; \
186                register u_int32 hi_tmp; \
187                \
188                if ((a_f) == 0) { \
189                        (r_i) -= (a_i); \
190                } else { \
191                        lo_tmp = ((r_f) & 0xffff) + ((-((s_fp)(a_f))) & 0xffff); \
192                        hi_tmp = (((r_f) >> 16) & 0xffff) \
193                            + (((-((s_fp)(a_f))) >> 16) & 0xffff); \
194                        if (lo_tmp & 0x10000) \
195                                hi_tmp++; \
196                        (r_f) = ((hi_tmp & 0xffff) << 16) | (lo_tmp & 0xffff); \
197                        \
198                        (r_i) += ~(a_i); \
199                        if (hi_tmp & 0x10000) \
200                                (r_i)++; \
201                } \
202        } while (0)
203
204#define M_RSHIFTU(v_i, v_f)             /* v >>= 1, v is unsigned */ \
205        do { \
206                (v_f) = (u_int32)(v_f) >> 1; \
207                if ((v_i) & 01) \
208                        (v_f) |= 0x80000000; \
209                (v_i) = (u_int32)(v_i) >> 1; \
210        } while (0)
211
212#define M_RSHIFT(v_i, v_f)              /* v >>= 1, v is signed */ \
213        do { \
214                (v_f) = (u_int32)(v_f) >> 1; \
215                if ((v_i) & 01) \
216                        (v_f) |= 0x80000000; \
217                if ((v_i) & 0x80000000) \
218                        (v_i) = ((v_i) >> 1) | 0x80000000; \
219                else \
220                        (v_i) = (v_i) >> 1; \
221        } while (0)
222
223#define M_LSHIFT(v_i, v_f)              /* v <<= 1 */ \
224        do { \
225                (v_i) <<= 1; \
226                if ((v_f) & 0x80000000) \
227                        (v_i) |= 0x1; \
228                (v_f) <<= 1; \
229        } while (0)
230
231#define M_LSHIFT3(v_ovr, v_i, v_f)      /* v <<= 1, with overflow */ \
232        do { \
233                (v_ovr) <<= 1; \
234                if ((v_i) & 0x80000000) \
235                        (v_ovr) |= 0x1; \
236                (v_i) <<= 1; \
237                if ((v_f) & 0x80000000) \
238                        (v_i) |= 0x1; \
239                (v_f) <<= 1; \
240        } while (0)
241
242#define M_ADDUF(r_i, r_f, uf)           /* r += uf, uf is u_int32 fraction */ \
243        M_ADD((r_i), (r_f), 0, (uf))    /* let optimizer worry about it */
244
245#define M_SUBUF(r_i, r_f, uf)           /* r -= uf, uf is u_int32 fraction */ \
246        M_SUB((r_i), (r_f), 0, (uf))    /* let optimizer worry about it */
247
248#define M_ADDF(r_i, r_f, f)             /* r += f, f is a int32 fraction */ \
249        do { \
250                if ((f) > 0) \
251                        M_ADD((r_i), (r_f), 0, (f)); \
252                else if ((f) < 0) \
253                        M_ADD((r_i), (r_f), (-1), (f));\
254        } while(0)
255
256#define M_ISNEG(v_i, v_f)               /* v < 0 */ \
257        (((v_i) & 0x80000000) != 0)
258
259#define M_ISHIS(a_i, a_f, b_i, b_f)     /* a >= b unsigned */ \
260        (((u_int32)(a_i)) > ((u_int32)(b_i)) || \
261          ((a_i) == (b_i) && ((u_int32)(a_f)) >= ((u_int32)(b_f))))
262
263#define M_ISGEQ(a_i, a_f, b_i, b_f)     /* a >= b signed */ \
264        (((int32)(a_i)) > ((int32)(b_i)) || \
265          ((a_i) == (b_i) && ((u_int32)(a_f)) >= ((u_int32)(b_f))))
266
267#define M_ISEQU(a_i, a_f, b_i, b_f)     /* a == b unsigned */ \
268        ((a_i) == (b_i) && (a_f) == (b_f))
269
270/*
271 * Operations on the long fp format
272 */
273#define L_ADD(r, a)     M_ADD((r)->l_ui, (r)->l_uf, (a)->l_ui, (a)->l_uf)
274#define L_SUB(r, a)     M_SUB((r)->l_ui, (r)->l_uf, (a)->l_ui, (a)->l_uf)
275#define L_NEG(v)        M_NEG((v)->l_ui, (v)->l_uf)
276#define L_ADDUF(r, uf)  M_ADDUF((r)->l_ui, (r)->l_uf, (uf))
277#define L_SUBUF(r, uf)  M_SUBUF((r)->l_ui, (r)->l_uf, (uf))
278#define L_ADDF(r, f)    M_ADDF((r)->l_ui, (r)->l_uf, (f))
279#define L_RSHIFT(v)     M_RSHIFT((v)->l_i, (v)->l_uf)
280#define L_RSHIFTU(v)    M_RSHIFT((v)->l_ui, (v)->l_uf)
281#define L_LSHIFT(v)     M_LSHIFT((v)->l_ui, (v)->l_uf)
282#define L_CLR(v)        ((v)->l_ui = (v)->l_uf = 0)
283
284#define L_ISNEG(v)      (((v)->l_ui & 0x80000000) != 0)
285#define L_ISZERO(v)     ((v)->l_ui == 0 && (v)->l_uf == 0)
286#define L_ISHIS(a, b)   ((a)->l_ui > (b)->l_ui || \
287                          ((a)->l_ui == (b)->l_ui && (a)->l_uf >= (b)->l_uf))
288#define L_ISGEQ(a, b)   ((a)->l_i > (b)->l_i || \
289                          ((a)->l_i == (b)->l_i && (a)->l_uf >= (b)->l_uf))
290#define L_ISEQU(a, b)   M_ISEQU((a)->l_ui, (a)->l_uf, (b)->l_ui, (b)->l_uf)
291
292extern  char *  dofptoa         P((u_fp, int, int, int));
293extern  char *  dolfptoa        P((u_long, u_long, int, int, int));
294
295extern  int     atolfp          P((const char *, l_fp *));
296extern  int     buftvtots       P((const char *, l_fp *));
297extern  char *  fptoa           P((s_fp, int));
298extern  char *  fptoms          P((s_fp, int));
299extern  char *  fptoms          P((s_fp, int));
300extern  int     hextolfp        P((const char *, l_fp *));
301extern  int     mstolfp         P((const char *, l_fp *));
302extern  char *  prettydate      P((l_fp *));
303extern  char *  uglydate        P((l_fp *));
304
305extern  void    get_systime     P((l_fp *));
306extern  int     step_systime    P((l_fp *));
307extern  int     step_systime_real P((l_fp *));
308extern  int     adj_systime     P((l_fp *));
309
310#define lfptoa(_fpv, _ndec)     mfptoa((_fpv)->l_ui, (_fpv)->l_uf, (_ndec))
311#define lfptoms(_fpv, _ndec)    mfptoms((_fpv)->l_ui, (_fpv)->l_uf, (_ndec))
312
313#define ntoa(_sin)              numtoa((_sin)->sin_addr.s_addr)
314#define ntohost(_sin)           numtohost((_sin)->sin_addr.s_addr)
315
316#define ufptoa(_fpv, _ndec)     dofptoa((_fpv), 0, (_ndec), 0)
317#define ufptoms(_fpv, _ndec)    dofptoa((_fpv), 0, (_ndec), 1)
318#define ulfptoa(_fpv, _ndec)    dolfptoa((_fpv)->l_ui, (_fpv)->l_uf, 0, (_ndec), 0)
319#define ulfptoms(_fpv, _ndec)   dolfptoa((_fpv)->l_ui, (_fpv)->l_uf, 0, (_ndec), 1)
320#define umfptoa(_fpi, _fpf, _ndec) dolfptoa((_fpi), (_fpf), 0, (_ndec), 0)
Note: See TracBrowser for help on using the repository browser.