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