1284990Scy#include "config.h"
2284990Scy
3284990Scy#include "ntp_stdlib.h"
4284990Scy#include "ntp_fp.h"
5284990Scy
6284990Scy#include "unity.h"
7284990Scy
8284990Scy#include <float.h>
9284990Scy#include <math.h>
10284990Scy
11284990Scy
12293893Sglebius/*
13293893Sglebius   replaced:	TEST_ASSERT_EQUAL_MEMORY(&a, &b, sizeof(a))
14293893Sglebius   with:	TEST_ASSERT_EQUAL_l_fp(a, b).
15293893Sglebius   It's safer this way, because structs can be compared even if they
16293893Sglebius   aren't initiated with memset (due to padding bytes).
17289999Sglebius*/
18293893Sglebius#define TEST_ASSERT_EQUAL_l_fp(a, b) {					\
19293893Sglebius	TEST_ASSERT_EQUAL_MESSAGE(a.l_i, b.l_i, "Field l_i");		\
20293893Sglebius	TEST_ASSERT_EQUAL_UINT_MESSAGE(a.l_uf, b.l_uf, "Field l_uf");	\
21284990Scy}
22284990Scy
23284990Scy
24289999Sglebiustypedef struct  {
25289999Sglebius	uint32_t h, l;
26289999Sglebius} lfp_hl;
27284990Scy
28284990Scy
29293893Sglebiusint	l_fp_scmp(const l_fp first, const l_fp second);
30293893Sglebiusint	l_fp_ucmp(const l_fp first, l_fp second);
31293893Sglebiusl_fp	l_fp_init(int32 i, u_int32 f);
32293893Sglebiusl_fp	l_fp_add(const l_fp first, const l_fp second);
33293893Sglebiusl_fp	l_fp_subtract(const l_fp first, const l_fp second);
34293893Sglebiusl_fp	l_fp_negate(const l_fp first);
35293893Sglebiusl_fp	l_fp_abs(const l_fp first);
36293893Sglebiusint	l_fp_signum(const l_fp first);
37293893Sglebiusdouble	l_fp_convert_to_double(const l_fp first);
38293893Sglebiusl_fp	l_fp_init_from_double( double rhs);
39293893Sglebiusvoid	l_fp_swap(l_fp * first, l_fp *second);
40293893Sglebiusbool	l_isgt(const l_fp first, const l_fp second);
41293893Sglebiusbool	l_isgtu(const l_fp first, const l_fp second);
42293893Sglebiusbool	l_ishis(const l_fp first, const l_fp second);
43293893Sglebiusbool	l_isgeq(const l_fp first, const l_fp second);
44293893Sglebiusbool	l_isequ(const l_fp first, const l_fp second);
45293893Sglebiusdouble	eps(double d);
46284990Scy
47284990Scy
48289999Sglebiusvoid test_AdditionLR(void);
49289999Sglebiusvoid test_AdditionRL(void);
50289999Sglebiusvoid test_SubtractionLR(void);
51289999Sglebiusvoid test_SubtractionRL(void);
52289999Sglebiusvoid test_Negation(void);
53289999Sglebiusvoid test_Absolute(void);
54289999Sglebiusvoid test_FDF_RoundTrip(void);
55289999Sglebiusvoid test_SignedRelOps(void);
56289999Sglebiusvoid test_UnsignedRelOps(void);
57284990Scy
58284990Scy
59289999Sglebiusstatic int cmp_work(u_int32 a[3], u_int32 b[3]);
60284990Scy
61284990Scy//----------------------------------------------------------------------
62284990Scy// reference comparision
63284990Scy// This is implementad as a full signed MP-subtract in 3 limbs, where
64284990Scy// the operands are zero or sign extended before the subtraction is
65284990Scy// executed.
66284990Scy//----------------------------------------------------------------------
67289999Sglebius
68289999Sglebiusint
69289999Sglebiusl_fp_scmp(const l_fp first, const l_fp second)
70284990Scy{
71284990Scy	u_int32 a[3], b[3];
72293893Sglebius
73284990Scy	const l_fp op1 = first;
74284990Scy	const l_fp op2 = second;
75293893Sglebius
76284990Scy	a[0] = op1.l_uf; a[1] = op1.l_ui; a[2] = 0;
77284990Scy	b[0] = op2.l_uf; b[1] = op2.l_ui; b[2] = 0;
78284990Scy
79284990Scy	a[2] -= (op1.l_i < 0);
80284990Scy	b[2] -= (op2.l_i < 0);
81284990Scy
82284990Scy	return cmp_work(a,b);
83284990Scy}
84284990Scy
85289999Sglebiusint
86293893Sglebiusl_fp_ucmp(const l_fp first, l_fp second)
87284990Scy{
88284990Scy	u_int32 a[3], b[3];
89284990Scy	const l_fp op1 = first;
90284990Scy	const l_fp op2 = second;
91293893Sglebius
92284990Scy	a[0] = op1.l_uf; a[1] = op1.l_ui; a[2] = 0;
93284990Scy	b[0] = op2.l_uf; b[1] = op2.l_ui; b[2] = 0;
94284990Scy
95284990Scy	return cmp_work(a,b);
96284990Scy}
97284990Scy
98289999Sglebius// maybe rename it to lf_cmp_work
99289999Sglebiusint
100289999Sglebiuscmp_work(u_int32 a[3], u_int32 b[3])
101284990Scy{
102284990Scy	u_int32 cy, idx, tmp;
103284990Scy	for (cy = idx = 0; idx < 3; ++idx) {
104284990Scy		tmp = a[idx]; cy  = (a[idx] -=   cy  ) > tmp;
105284990Scy		tmp = a[idx]; cy |= (a[idx] -= b[idx]) > tmp;
106284990Scy	}
107284990Scy	if (a[2])
108284990Scy		return -1;
109284990Scy	return a[0] || a[1];
110284990Scy}
111284990Scy
112284990Scy
113284990Scy//----------------------------------------------------------------------
114284990Scy// imlementation of the LFP stuff
115284990Scy// This should be easy enough...
116284990Scy//----------------------------------------------------------------------
117284990Scy
118289999Sglebiusl_fp
119289999Sglebiusl_fp_init(int32 i, u_int32 f)
120284990Scy{
121284990Scy	l_fp temp;
122284990Scy	temp.l_i  = i;
123284990Scy	temp.l_uf = f;
124284990Scy
125284990Scy	return temp;
126284990Scy}
127284990Scy
128289999Sglebiusl_fp
129289999Sglebiusl_fp_add(const l_fp first, const l_fp second)
130284990Scy{
131289999Sglebius	l_fp temp = first;
132284990Scy	L_ADD(&temp, &second);
133289999Sglebius
134284990Scy	return temp;
135284990Scy}
136284990Scy
137289999Sglebiusl_fp
138289999Sglebiusl_fp_subtract(const l_fp first, const l_fp second)
139284990Scy{
140289999Sglebius	l_fp temp = first;
141284990Scy	L_SUB(&temp, &second);
142293893Sglebius
143284990Scy	return temp;
144284990Scy}
145284990Scy
146289999Sglebiusl_fp
147289999Sglebiusl_fp_negate(const l_fp first)
148284990Scy{
149289999Sglebius	l_fp temp = first;
150284990Scy	L_NEG(&temp);
151293893Sglebius
152284990Scy	return temp;
153284990Scy}
154284990Scy
155289999Sglebiusl_fp
156289999Sglebiusl_fp_abs(const l_fp first)
157284990Scy{
158284990Scy	l_fp temp = first;
159284990Scy	if (L_ISNEG(&temp))
160284990Scy		L_NEG(&temp);
161284990Scy	return temp;
162284990Scy}
163284990Scy
164289999Sglebiusint
165289999Sglebiusl_fp_signum(const l_fp first)
166284990Scy{
167284990Scy	if (first.l_ui & 0x80000000u)
168284990Scy		return -1;
169284990Scy	return (first.l_ui || first.l_uf);
170284990Scy}
171284990Scy
172289999Sglebiusdouble
173289999Sglebiusl_fp_convert_to_double(const l_fp first)
174284990Scy{
175284990Scy	double res;
176284990Scy	LFPTOD(&first, res);
177284990Scy	return res;
178284990Scy}
179284990Scy
180289999Sglebiusl_fp
181289999Sglebiusl_fp_init_from_double( double rhs)
182284990Scy{
183284990Scy	l_fp temp;
184284990Scy	DTOLFP(rhs, &temp);
185284990Scy	return temp;
186284990Scy}
187284990Scy
188289999Sglebiusvoid
189293893Sglebiusl_fp_swap(l_fp * first, l_fp *second)
190293893Sglebius{
191284990Scy	l_fp temp = *second;
192284990Scy
193284990Scy	*second = *first;
194284990Scy	*first = temp;
195293893Sglebius
196293893Sglebius	return;
197284990Scy}
198284990Scy
199289999Sglebius//----------------------------------------------------------------------
200289999Sglebius// testing the relational macros works better with proper predicate
201289999Sglebius// formatting functions; it slows down the tests a bit, but makes for
202289999Sglebius// readable failure messages.
203289999Sglebius//----------------------------------------------------------------------
204284990Scy
205289999Sglebius
206289999Sglebiusbool
207293893Sglebiusl_isgt (const l_fp first, const l_fp second)
208293893Sglebius{
209293893Sglebius
210289999Sglebius	return L_ISGT(&first, &second);
211284990Scy}
212284990Scy
213289999Sglebiusbool
214293893Sglebiusl_isgtu(const l_fp first, const l_fp second)
215293893Sglebius{
216293893Sglebius
217289999Sglebius	return L_ISGTU(&first, &second);
218289999Sglebius}
219284990Scy
220289999Sglebiusbool
221293893Sglebiusl_ishis(const l_fp first, const l_fp second)
222293893Sglebius{
223293893Sglebius
224289999Sglebius	return L_ISHIS(&first, &second);
225284990Scy}
226284990Scy
227289999Sglebiusbool
228293893Sglebiusl_isgeq(const l_fp first, const l_fp second)
229293893Sglebius{
230293893Sglebius
231289999Sglebius	return L_ISGEQ(&first, &second);
232284990Scy}
233284990Scy
234289999Sglebiusbool
235293893Sglebiusl_isequ(const l_fp first, const l_fp second)
236293893Sglebius{
237293893Sglebius
238289999Sglebius	return L_ISEQU(&first, &second);
239284990Scy}
240284990Scy
241284990Scy
242284990Scy//----------------------------------------------------------------------
243284990Scy// test data table for add/sub and compare
244284990Scy//----------------------------------------------------------------------
245284990Scy
246284990Scy
247284990Scystatic const lfp_hl addsub_tab[][3] = {
248284990Scy	// trivial idendity:
249284990Scy	{{0 ,0         }, { 0,0         }, { 0,0}},
250284990Scy	// with carry from fraction and sign change:
251284990Scy	{{-1,0x80000000}, { 0,0x80000000}, { 0,0}},
252284990Scy	// without carry from fraction
253284990Scy	{{ 1,0x40000000}, { 1,0x40000000}, { 2,0x80000000}},
254284990Scy	// with carry from fraction:
255284990Scy	{{ 1,0xC0000000}, { 1,0xC0000000}, { 3,0x80000000}},
256284990Scy	// with carry from fraction and sign change:
257284990Scy	{{0x7FFFFFFF, 0x7FFFFFFF}, {0x7FFFFFFF,0x7FFFFFFF}, {0xFFFFFFFE,0xFFFFFFFE}},
258284990Scy	// two tests w/o carry (used for l_fp<-->double):
259284990Scy	{{0x55555555,0xAAAAAAAA}, {0x11111111,0x11111111}, {0x66666666,0xBBBBBBBB}},
260284990Scy	{{0x55555555,0x55555555}, {0x11111111,0x11111111}, {0x66666666,0x66666666}},
261284990Scy	// wide-range test, triggers compare trouble
262284990Scy	{{0x80000000,0x00000001}, {0xFFFFFFFF,0xFFFFFFFE}, {0x7FFFFFFF,0xFFFFFFFF}}
263284990Scy};
264284990Scystatic const size_t addsub_cnt = (sizeof(addsub_tab)/sizeof(addsub_tab[0]));
265284990Scystatic const size_t addsub_tot = (sizeof(addsub_tab)/sizeof(addsub_tab[0][0]));
266284990Scy
267284990Scy
268284990Scy
269284990Scy//----------------------------------------------------------------------
270284990Scy// epsilon estimation for the precision of a conversion double --> l_fp
271284990Scy//
272284990Scy// The error estimation limit is as follows:
273284990Scy//  * The 'l_fp' fixed point fraction has 32 bits precision, so we allow
274284990Scy//    for the LSB to toggle by clamping the epsilon to be at least 2^(-31)
275284990Scy//
276284990Scy//  * The double mantissa has a precsion 54 bits, so the other minimum is
277284990Scy//    dval * (2^(-53))
278284990Scy//
279284990Scy//  The maximum of those two boundaries is used for the check.
280284990Scy//
281284990Scy// Note: once there are more than 54 bits between the highest and lowest
282284990Scy// '1'-bit of the l_fp value, the roundtrip *will* create truncation
283284990Scy// errors. This is an inherent property caused by the 54-bit mantissa of
284284990Scy// the 'double' type.
285289999Sglebiusdouble
286289999Sglebiuseps(double d)
287284990Scy{
288293893Sglebius
289289999Sglebius	return fmax(ldexp(1.0, -31), ldexp(fabs(d), -53));
290284990Scy}
291284990Scy
292284990Scy//----------------------------------------------------------------------
293284990Scy// test addition
294284990Scy//----------------------------------------------------------------------
295289999Sglebiusvoid
296293893Sglebiustest_AdditionLR(void)
297293893Sglebius{
298289999Sglebius	size_t idx = 0;
299293893Sglebius
300289999Sglebius	for (idx = 0; idx < addsub_cnt; ++idx) {
301284990Scy		l_fp op1 = l_fp_init(addsub_tab[idx][0].h, addsub_tab[idx][0].l);
302284990Scy		l_fp op2 = l_fp_init(addsub_tab[idx][1].h, addsub_tab[idx][1].l);
303293893Sglebius		l_fp e_res = l_fp_init(addsub_tab[idx][2].h, addsub_tab[idx][2].l);
304293893Sglebius		l_fp res = l_fp_add(op1, op2);
305284990Scy
306293893Sglebius		TEST_ASSERT_EQUAL_l_fp(e_res, res);
307293893Sglebius	}
308293893Sglebius	return;
309284990Scy}
310284990Scy
311289999Sglebiusvoid
312293893Sglebiustest_AdditionRL(void)
313293893Sglebius{
314289999Sglebius	size_t idx = 0;
315293893Sglebius
316289999Sglebius	for (idx = 0; idx < addsub_cnt; ++idx) {
317284990Scy		l_fp op2 = l_fp_init(addsub_tab[idx][0].h, addsub_tab[idx][0].l);
318284990Scy		l_fp op1 = l_fp_init(addsub_tab[idx][1].h, addsub_tab[idx][1].l);
319293893Sglebius		l_fp e_res = l_fp_init(addsub_tab[idx][2].h, addsub_tab[idx][2].l);
320289999Sglebius		l_fp res = l_fp_add(op1, op2);
321284990Scy
322293893Sglebius		TEST_ASSERT_EQUAL_l_fp(e_res, res);
323293893Sglebius	}
324293893Sglebius	return;
325284990Scy}
326284990Scy
327284990Scy
328284990Scy//----------------------------------------------------------------------
329284990Scy// test subtraction
330284990Scy//----------------------------------------------------------------------
331289999Sglebiusvoid
332293893Sglebiustest_SubtractionLR(void)
333293893Sglebius{
334289999Sglebius	size_t idx = 0;
335293893Sglebius
336289999Sglebius	for (idx = 0; idx < addsub_cnt; ++idx) {
337284990Scy		l_fp op2 = l_fp_init(addsub_tab[idx][0].h, addsub_tab[idx][0].l);
338293893Sglebius		l_fp e_res = l_fp_init(addsub_tab[idx][1].h, addsub_tab[idx][1].l);
339284990Scy		l_fp op1 = l_fp_init(addsub_tab[idx][2].h, addsub_tab[idx][2].l);
340289999Sglebius		l_fp res = l_fp_subtract(op1, op2);
341293893Sglebius
342293893Sglebius		TEST_ASSERT_EQUAL_l_fp(e_res, res);
343293893Sglebius	}
344293893Sglebius	return;
345284990Scy}
346284990Scy
347289999Sglebiusvoid
348293893Sglebiustest_SubtractionRL(void)
349293893Sglebius{
350289999Sglebius	size_t idx = 0;
351293893Sglebius
352289999Sglebius	for (idx = 0; idx < addsub_cnt; ++idx) {
353293893Sglebius		l_fp e_res = l_fp_init(addsub_tab[idx][0].h, addsub_tab[idx][0].l);
354284990Scy		l_fp op2 = l_fp_init(addsub_tab[idx][1].h, addsub_tab[idx][1].l);
355284990Scy		l_fp op1 = l_fp_init(addsub_tab[idx][2].h, addsub_tab[idx][2].l);
356289999Sglebius		l_fp res = l_fp_subtract(op1, op2);
357284990Scy
358293893Sglebius		TEST_ASSERT_EQUAL_l_fp(e_res, res);
359293893Sglebius	}
360293893Sglebius	return;
361284990Scy}
362284990Scy
363284990Scy//----------------------------------------------------------------------
364284990Scy// test negation
365284990Scy//----------------------------------------------------------------------
366284990Scy
367289999Sglebiusvoid
368293893Sglebiustest_Negation(void)
369293893Sglebius{
370293893Sglebius	size_t idx = 0;
371284990Scy
372289999Sglebius	for (idx = 0; idx < addsub_cnt; ++idx) {
373284990Scy		l_fp op1 = l_fp_init(addsub_tab[idx][0].h, addsub_tab[idx][0].l);
374284990Scy		l_fp op2 = l_fp_negate(op1);
375284990Scy		l_fp sum = l_fp_add(op1, op2);
376293893Sglebius
377289999Sglebius		l_fp zero = l_fp_init(0, 0);
378284990Scy
379289999Sglebius		TEST_ASSERT_EQUAL_l_fp(zero, sum);
380293893Sglebius	}
381293893Sglebius	return;
382284990Scy}
383284990Scy
384284990Scy
385284990Scy
386284990Scy//----------------------------------------------------------------------
387284990Scy// test absolute value
388284990Scy//----------------------------------------------------------------------
389289999Sglebiusvoid
390293893Sglebiustest_Absolute(void)
391293893Sglebius{
392289999Sglebius	size_t idx = 0;
393293893Sglebius
394289999Sglebius	for (idx = 0; idx < addsub_cnt; ++idx) {
395284990Scy		l_fp op1 = l_fp_init(addsub_tab[idx][0].h, addsub_tab[idx][0].l);
396284990Scy		l_fp op2 = l_fp_abs(op1);
397284990Scy
398293893Sglebius		TEST_ASSERT_TRUE(l_fp_signum(op2) >= 0);
399284990Scy
400284990Scy		if (l_fp_signum(op1) >= 0)
401293893Sglebius			op1 = l_fp_subtract(op1, op2);
402284990Scy		else
403289999Sglebius			op1 = l_fp_add(op1, op2);
404293893Sglebius
405289999Sglebius		l_fp zero = l_fp_init(0, 0);
406293893Sglebius
407289999Sglebius		TEST_ASSERT_EQUAL_l_fp(zero, op1);
408284990Scy	}
409284990Scy
410284990Scy	// There is one special case we have to check: the minimum
411284990Scy	// value cannot be negated, or, to be more precise, the
412284990Scy	// negation reproduces the original pattern.
413284990Scy	l_fp minVal = l_fp_init(0x80000000, 0x00000000);
414284990Scy	l_fp minAbs = l_fp_abs(minVal);
415284990Scy	TEST_ASSERT_EQUAL(-1, l_fp_signum(minVal));
416284990Scy
417289999Sglebius	TEST_ASSERT_EQUAL_l_fp(minVal, minAbs);
418293893Sglebius
419293893Sglebius	return;
420284990Scy}
421284990Scy
422284990Scy
423284990Scy//----------------------------------------------------------------------
424284990Scy// fp -> double -> fp rountrip test
425284990Scy//----------------------------------------------------------------------
426289999Sglebiusvoid
427293893Sglebiustest_FDF_RoundTrip(void)
428293893Sglebius{
429293893Sglebius	size_t idx = 0;
430293893Sglebius
431284990Scy	// since a l_fp has 64 bits in it's mantissa and a double has
432284990Scy	// only 54 bits available (including the hidden '1') we have to
433284990Scy	// make a few concessions on the roundtrip precision. The 'eps()'
434284990Scy	// function makes an educated guess about the avilable precision
435284990Scy	// and checks the difference in the two 'l_fp' values against
436284990Scy	// that limit.
437293893Sglebius
438289999Sglebius	for (idx = 0; idx < addsub_cnt; ++idx) {
439284990Scy		l_fp op1 = l_fp_init(addsub_tab[idx][0].h, addsub_tab[idx][0].l);
440284990Scy		double op2 = l_fp_convert_to_double(op1);
441284990Scy		l_fp op3 = l_fp_init_from_double(op2);
442284990Scy
443289999Sglebius		l_fp temp = l_fp_subtract(op1, op3);
444284990Scy		double d = l_fp_convert_to_double(temp);
445293893Sglebius		TEST_ASSERT_DOUBLE_WITHIN(eps(op2), 0.0, fabs(d));
446293893Sglebius	}
447293893Sglebius
448293893Sglebius	return;
449284990Scy}
450284990Scy
451284990Scy
452284990Scy//----------------------------------------------------------------------
453284990Scy// test the compare stuff
454284990Scy//
455284990Scy// This uses the local compare and checks if the operations using the
456284990Scy// macros in 'ntp_fp.h' produce mathing results.
457284990Scy// ----------------------------------------------------------------------
458289999Sglebiusvoid
459293893Sglebiustest_SignedRelOps(void)
460293893Sglebius{
461284990Scy	const lfp_hl * tv = (&addsub_tab[0][0]);
462284990Scy	size_t lc ;
463293893Sglebius
464289999Sglebius	for (lc = addsub_tot - 1; lc; --lc, ++tv) {
465289999Sglebius		l_fp op1 = l_fp_init(tv[0].h, tv[0].l);
466289999Sglebius		l_fp op2 = l_fp_init(tv[1].h, tv[1].l);
467293893Sglebius		int cmp = l_fp_scmp(op1, op2);
468293893Sglebius
469284990Scy		switch (cmp) {
470284990Scy		case -1:
471284990Scy			//printf("op1:%d %d, op2:%d %d\n",op1.l_uf,op1.l_ui,op2.l_uf,op2.l_ui);
472289999Sglebius			l_fp_swap(&op1, &op2);
473284990Scy			//printf("op1:%d %d, op2:%d %d\n",op1.l_uf,op1.l_ui,op2.l_uf,op2.l_ui);
474284990Scy		case 1:
475289999Sglebius			TEST_ASSERT_TRUE (l_isgt(op1, op2));
476289999Sglebius			TEST_ASSERT_FALSE(l_isgt(op2, op1));
477284990Scy
478289999Sglebius			TEST_ASSERT_TRUE (l_isgeq(op1, op2));
479289999Sglebius			TEST_ASSERT_FALSE(l_isgeq(op2, op1));
480284990Scy
481289999Sglebius			TEST_ASSERT_FALSE(l_isequ(op1, op2));
482289999Sglebius			TEST_ASSERT_FALSE(l_isequ(op2, op1));
483284990Scy			break;
484284990Scy		case 0:
485289999Sglebius			TEST_ASSERT_FALSE(l_isgt(op1, op2));
486289999Sglebius			TEST_ASSERT_FALSE(l_isgt(op2, op1));
487284990Scy
488289999Sglebius			TEST_ASSERT_TRUE (l_isgeq(op1, op2));
489289999Sglebius			TEST_ASSERT_TRUE (l_isgeq(op2, op1));
490284990Scy
491289999Sglebius			TEST_ASSERT_TRUE (l_isequ(op1, op2));
492289999Sglebius			TEST_ASSERT_TRUE (l_isequ(op2, op1));
493284990Scy			break;
494284990Scy		default:
495293893Sglebius			TEST_FAIL_MESSAGE("unexpected UCMP result: ");
496284990Scy		}
497284990Scy	}
498293893Sglebius
499293893Sglebius	return;
500284990Scy}
501284990Scy
502289999Sglebiusvoid
503293893Sglebiustest_UnsignedRelOps(void)
504293893Sglebius{
505293893Sglebius	const lfp_hl * tv =(&addsub_tab[0][0]);
506284990Scy	size_t lc;
507293893Sglebius
508289999Sglebius	for (lc = addsub_tot - 1; lc; --lc, ++tv) {
509289999Sglebius		l_fp op1 = l_fp_init(tv[0].h, tv[0].l);
510289999Sglebius		l_fp op2 = l_fp_init(tv[1].h, tv[1].l);
511289999Sglebius		int cmp = l_fp_ucmp(op1, op2);
512284990Scy
513284990Scy		switch (cmp) {
514284990Scy		case -1:
515284990Scy			//printf("op1:%d %d, op2:%d %d\n",op1.l_uf,op1.l_ui,op2.l_uf,op2.l_ui);
516284990Scy			l_fp_swap(&op1, &op2);
517284990Scy			//printf("op1:%d %d, op2:%d %d\n",op1.l_uf,op1.l_ui,op2.l_uf,op2.l_ui);
518284990Scy		case 1:
519289999Sglebius			TEST_ASSERT_TRUE (l_isgtu(op1, op2));
520289999Sglebius			TEST_ASSERT_FALSE(l_isgtu(op2, op1));
521284990Scy
522289999Sglebius			TEST_ASSERT_TRUE (l_ishis(op1, op2));
523289999Sglebius			TEST_ASSERT_FALSE(l_ishis(op2, op1));
524284990Scy			break;
525284990Scy		case 0:
526289999Sglebius			TEST_ASSERT_FALSE(l_isgtu(op1, op2));
527289999Sglebius			TEST_ASSERT_FALSE(l_isgtu(op2, op1));
528284990Scy
529289999Sglebius			TEST_ASSERT_TRUE (l_ishis(op1, op2));
530289999Sglebius			TEST_ASSERT_TRUE (l_ishis(op2, op1));
531284990Scy			break;
532284990Scy		default:
533293893Sglebius			TEST_FAIL_MESSAGE("unexpected UCMP result: ");
534284990Scy		}
535284990Scy	}
536293893Sglebius
537293893Sglebius	return;
538284990Scy}
539293893Sglebius
540284990Scy/*
541284990Scy*/
542284990Scy
543284990Scy//----------------------------------------------------------------------
544284990Scy// that's all folks... but feel free to add things!
545284990Scy//----------------------------------------------------------------------
546