1284990Scy#include <config.h>
2284990Scy
3284990Scy#include <ntp.h>
4284990Scy#include <ntp_fp.h>
5293650Sglebius#include <ntp_assert.h>
6284990Scy
7284990Scy/*
8284990Scy * we want to test a refid format of:
9284990Scy * 254.x.y.x
10284990Scy *
11284990Scy * where x.y.z are 24 bits containing 2 (signed) integer bits
12284990Scy * and 22 fractional bits.
13284990Scy *
14284990Scy * we want functions to convert to/from this format, with unit tests.
15284990Scy *
16284990Scy * Interesting test cases include:
17284990Scy * 254.0.0.0
18284990Scy * 254.0.0.1
19284990Scy * 254.127.255.255
20284990Scy * 254.128.0.0
21284990Scy * 254.255.255.255
22284990Scy */
23284990Scy
24284990Scychar *progname = "";
25284990Scy
26284990Scyl_fp convertRefIDToLFP(uint32_t r);
27284990Scyuint32_t convertLFPToRefID(l_fp num);
28284990Scy
29284990Scy
30284990Scy/*
31284990Scy * The smear data in the refid is the bottom 3 bytes of the refid,
32284990Scy * 2 bits of integer
33284990Scy * 22 bits of fraction
34284990Scy */
35284990Scyl_fp
36284990ScyconvertRefIDToLFP(uint32_t r)
37284990Scy{
38284990Scy	l_fp temp;
39284990Scy
40284990Scy	r = ntohl(r);
41284990Scy
42284990Scy	printf("%03d %08x: ", (r >> 24) & 0xFF, (r & 0x00FFFFFF) );
43284990Scy
44284990Scy	temp.l_uf = (r << 10);	/* 22 fractional bits */
45284990Scy
46284990Scy	temp.l_ui = (r >> 22) & 0x3;
47284990Scy	temp.l_ui |= ~(temp.l_ui & 2) + 1;
48284990Scy
49284990Scy	return temp;
50284990Scy}
51284990Scy
52284990Scy
53284990Scyuint32_t
54284990ScyconvertLFPToRefID(l_fp num)
55284990Scy{
56284990Scy	uint32_t temp;
57284990Scy
58284990Scy	/* round the input with the highest bit to shift out from the
59284990Scy	 * fraction, then keep just two bits from the integral part.
60284990Scy	 *
61284990Scy	 * TODO: check for overflows; should we clamp/saturate or just
62284990Scy	 * complain?
63284990Scy	 */
64284990Scy	L_ADDUF(&num, 0x200);
65284990Scy	num.l_ui &= 3;
66284990Scy
67284990Scy	/* combine integral and fractional part to 24 bits */
68284990Scy	temp  = (num.l_ui << 22) | (num.l_uf >> 10);
69284990Scy
70284990Scy	/* put in the leading 254.0.0.0 */
71284990Scy	temp |= UINT32_C(0xFE000000);
72284990Scy
73284990Scy	printf("%03d %08x: ", (temp >> 24) & 0xFF, (temp & 0x00FFFFFF) );
74284990Scy
75284990Scy	return htonl(temp);
76284990Scy}
77284990Scy
78284990Scy/* Tests start here */
79284990Scy
80284990Scyvoid rtol(uint32_t r);
81284990Scy
82284990Scyvoid
83284990Scyrtol(uint32_t r)
84284990Scy{
85284990Scy	l_fp l;
86284990Scy
87284990Scy	printf("rtol: ");
88284990Scy
89284990Scy	l = convertRefIDToLFP(htonl(r));
90284990Scy	printf("refid %#x, smear %s\n", r, lfptoa(&l, 8));
91284990Scy
92284990Scy	return;
93284990Scy}
94284990Scy
95284990Scy
96284990Scyvoid rtoltor(uint32_t r);
97284990Scy
98284990Scyvoid
99284990Scyrtoltor(uint32_t r)
100284990Scy{
101284990Scy	l_fp l;
102284990Scy
103284990Scy	printf("rtoltor: ");
104284990Scy	l = convertRefIDToLFP(htonl(r));
105284990Scy
106284990Scy	r = convertLFPToRefID(l);
107284990Scy	printf("smear %s, refid %#.8x\n", lfptoa(&l, 8), ntohl(r));
108284990Scy
109284990Scy	return;
110284990Scy}
111284990Scy
112284990Scy
113284990Scyvoid ltor(l_fp l);
114284990Scy
115284990Scyvoid
116284990Scyltor(l_fp l)
117284990Scy{
118284990Scy	uint32_t r;
119284990Scy
120284990Scy	printf("ltor: ");
121284990Scy
122284990Scy	r = convertLFPToRefID(l);
123284990Scy	printf("smear %s, refid %#.8x\n", lfptoa(&l, 8), ntohl(r));
124284990Scy
125284990Scy	return;
126284990Scy}
127284990Scy
128284990Scy
129293650Sglebiusint
130284990Scymain()
131284990Scy{
132289997Sglebius	l_fp l;
133289997Sglebius	int rc;
134284990Scy
135293650Sglebius	init_lib();
136293650Sglebius
137284990Scy	rtol(0xfe800000);
138284990Scy	rtol(0xfe800001);
139284990Scy	rtol(0xfe8ffffe);
140284990Scy	rtol(0xfe8fffff);
141284990Scy	rtol(0xfef00000);
142284990Scy	rtol(0xfef00001);
143284990Scy	rtol(0xfefffffe);
144284990Scy	rtol(0xfeffffff);
145284990Scy
146284990Scy	rtol(0xfe000000);
147284990Scy	rtol(0xfe000001);
148284990Scy	rtol(0xfe6ffffe);
149284990Scy	rtol(0xfe6fffff);
150284990Scy	rtol(0xfe700000);
151284990Scy	rtol(0xfe700001);
152284990Scy	rtol(0xfe7ffffe);
153284990Scy	rtol(0xfe7fffff);
154284990Scy
155284990Scy	rtoltor(0xfe800000);
156284990Scy	rtoltor(0xfe800001);
157284990Scy	rtoltor(0xfe8ffffe);
158284990Scy	rtoltor(0xfe8fffff);
159284990Scy	rtoltor(0xfef00000);
160284990Scy	rtoltor(0xfef00001);
161284990Scy	rtoltor(0xfefffffe);
162284990Scy	rtoltor(0xfeffffff);
163284990Scy
164284990Scy	rtoltor(0xfe000000);
165284990Scy	rtoltor(0xfe000001);
166284990Scy	rtoltor(0xfe6ffffe);
167284990Scy	rtoltor(0xfe6fffff);
168284990Scy	rtoltor(0xfe700000);
169284990Scy	rtoltor(0xfe700001);
170284990Scy	rtoltor(0xfe7ffffe);
171284990Scy	rtoltor(0xfe7fffff);
172284990Scy
173289997Sglebius	rc = atolfp("-.932087", &l);
174293650Sglebius	INSIST(1 == rc);
175293650Sglebius
176289997Sglebius	ltor(l);
177289997Sglebius	rtol(0xfec458b0);
178289997Sglebius	printf("%x -> %d.%d.%d.%d\n",
179289997Sglebius		0xfec458b0,
180289997Sglebius		0xfe,
181289997Sglebius		  0xc4,
182289997Sglebius		    0x58,
183289997Sglebius		      0xb0);
184289997Sglebius
185284990Scy	return 0;
186284990Scy}
187