lfpfunc.c revision 284990
1284990Scy#include "config.h"
2284990Scy
3284990Scy#include "ntp_stdlib.h"
4284990Scy#include "ntp_calendar.h"
5284990Scy#include "ntp_fp.h"
6284990Scy
7284990Scy#include "unity.h"
8284990Scy
9284990Scy#include <float.h>
10284990Scy#include <math.h>
11284990Scy
12284990Scy
13284990Scy//replaced TEST_ASSERT_EQUAL_MEMORY(&a,&b,sizeof(a)) with TEST_ASSERT_EQUAL_l_fp(a,b). It's safer this way, because structs can be compared even if they aren't initiated with memset (due to padding bytes)
14284990Scy#define TEST_ASSERT_EQUAL_l_fp(a, b) { \
15284990Scy    TEST_ASSERT_EQUAL_MESSAGE(a.l_i, b.l_i, "Field l_i"); \
16284990Scy    TEST_ASSERT_EQUAL_UINT_MESSAGE(a.l_uf, b.l_uf, "Field l_uf");	\
17284990Scy}
18284990Scy
19284990Scytypedef struct  {
20284990Scy	uint32_t h, l;
21284990Scy} lfp_hl;
22284990Scy
23284990Scy
24284990Scystatic int cmp_work(u_int32 a[3], u_int32 b[3]);
25284990Scy
26284990Scy/*
27284990Scy//----------------------------------------------------------------------
28284990Scy// OO-wrapper for 'l_fp'
29284990Scy//----------------------------------------------------------------------
30284990Scy
31284990Scy
32284990Scy	~LFP();
33284990Scy	LFP();
34284990Scy	LFP(const LFP& rhs);
35284990Scy	LFP(int32 i, u_int32 f);
36284990Scy
37284990Scy	LFP  operator+ (const LFP &rhs) const;
38284990Scy	LFP& operator+=(const LFP &rhs);
39284990Scy
40284990Scy	LFP  operator- (const LFP &rhs) const;
41284990Scy	LFP& operator-=(const LFP &rhs);
42284990Scy
43284990Scy	LFP& operator=(const LFP &rhs);
44284990Scy	LFP  operator-() const;
45284990Scy
46284990Scy	bool operator==(const LFP &rhs) const;
47284990Scy
48284990Scy	LFP  neg() const;
49284990Scy	LFP  abs() const;
50284990Scy	int  signum() const;
51284990Scy
52284990Scy
53284990Scy
54284990Scy	int  ucmp(const LFP & rhs) const;
55284990Scy	int  scmp(const LFP & rhs) const;
56284990Scy
57284990Scy	std::string   toString() const;
58284990Scy	std::ostream& toStream(std::ostream &oo) const;
59284990Scy
60284990Scy	operator double() const;
61284990Scy	explicit LFP(double);
62284990Scy
63284990Scy
64284990Scy	LFP(const l_fp &rhs);
65284990Scy
66284990Scy	static int cmp_work(u_int32 a[3], u_int32 b[3]);
67284990Scy
68284990Scy	l_fp _v;
69284990Scy
70284990Scy
71284990Scystatic std::ostream& operator<<(std::ostream &oo, const LFP& rhs)
72284990Scy{
73284990Scy	return rhs.toStream(oo);
74284990Scy}
75284990Scy*/
76284990Scy//----------------------------------------------------------------------
77284990Scy// reference comparision
78284990Scy// This is implementad as a full signed MP-subtract in 3 limbs, where
79284990Scy// the operands are zero or sign extended before the subtraction is
80284990Scy// executed.
81284990Scy//----------------------------------------------------------------------
82284990Scyint  l_fp_scmp(const l_fp first, const l_fp second)
83284990Scy{
84284990Scy	u_int32 a[3], b[3];
85284990Scy
86284990Scy	const l_fp op1 = first;
87284990Scy	const l_fp op2 = second;
88284990Scy	//const l_fp &op1(_v), &op2(rhs._v);
89284990Scy
90284990Scy	a[0] = op1.l_uf; a[1] = op1.l_ui; a[2] = 0;
91284990Scy	b[0] = op2.l_uf; b[1] = op2.l_ui; b[2] = 0;
92284990Scy
93284990Scy	a[2] -= (op1.l_i < 0);
94284990Scy	b[2] -= (op2.l_i < 0);
95284990Scy
96284990Scy	return cmp_work(a,b);
97284990Scy}
98284990Scy
99284990Scyint  l_fp_ucmp(const l_fp first, l_fp second )
100284990Scy{
101284990Scy	u_int32 a[3], b[3];
102284990Scy	const l_fp op1 = first;
103284990Scy	const l_fp op2 = second;
104284990Scy
105284990Scy	a[0] = op1.l_uf; a[1] = op1.l_ui; a[2] = 0;
106284990Scy	b[0] = op2.l_uf; b[1] = op2.l_ui; b[2] = 0;
107284990Scy
108284990Scy	return cmp_work(a,b);
109284990Scy}
110284990Scy
111284990Scy
112284990Scy//maybe rename it to lf_cmp_work ???
113284990Scyint cmp_work(u_int32 a[3], u_int32 b[3])
114284990Scy{
115284990Scy	u_int32 cy, idx, tmp;
116284990Scy	for (cy = idx = 0; idx < 3; ++idx) {
117284990Scy		tmp = a[idx]; cy  = (a[idx] -=   cy  ) > tmp;
118284990Scy		tmp = a[idx]; cy |= (a[idx] -= b[idx]) > tmp;
119284990Scy	}
120284990Scy	if (a[2])
121284990Scy		return -1;
122284990Scy	return a[0] || a[1];
123284990Scy}
124284990Scy
125284990Scy
126284990Scy//----------------------------------------------------------------------
127284990Scy// imlementation of the LFP stuff
128284990Scy// This should be easy enough...
129284990Scy//----------------------------------------------------------------------
130284990Scy
131284990Scy
132284990Scy
133284990Scyl_fp l_fp_init(int32 i, u_int32 f)
134284990Scy{
135284990Scy	l_fp temp;
136284990Scy	temp.l_i  = i;
137284990Scy	temp.l_uf = f;
138284990Scy
139284990Scy	return temp;
140284990Scy}
141284990Scy
142284990Scy
143284990Scy
144284990Scyl_fp l_fp_add(const l_fp first, const l_fp second)
145284990Scy{
146284990Scy	l_fp temp;
147284990Scy	temp = first;
148284990Scy	L_ADD(&temp, &second);
149284990Scy	return temp;
150284990Scy}
151284990Scy
152284990Scyl_fp l_fp_subtract(const l_fp first, const l_fp second)
153284990Scy{
154284990Scy	l_fp temp;
155284990Scy	temp = first;
156284990Scy	L_SUB(&temp, &second);
157284990Scy
158284990Scy	return temp;
159284990Scy}
160284990Scy
161284990Scyl_fp l_fp_negate(const l_fp first)
162284990Scy{
163284990Scy	l_fp temp;
164284990Scy	temp = first; //is this line really necessary?
165284990Scy	L_NEG(&temp);
166284990Scy
167284990Scy	return temp;
168284990Scy}
169284990Scy
170284990Scyl_fp l_fp_abs(const l_fp first)
171284990Scy{
172284990Scy	l_fp temp = first;
173284990Scy	if (L_ISNEG(&temp))
174284990Scy		L_NEG(&temp);
175284990Scy	return temp;
176284990Scy}
177284990Scy
178284990Scyint l_fp_signum(const l_fp first)
179284990Scy{
180284990Scy	if (first.l_ui & 0x80000000u)
181284990Scy		return -1;
182284990Scy	return (first.l_ui || first.l_uf);
183284990Scy}
184284990Scy
185284990Scydouble l_fp_convert_to_double(const l_fp first)
186284990Scy{
187284990Scy	double res;
188284990Scy	LFPTOD(&first, res);
189284990Scy	return res;
190284990Scy}
191284990Scy
192284990Scyl_fp l_fp_init_from_double( double rhs)
193284990Scy{
194284990Scy	l_fp temp;
195284990Scy	DTOLFP(rhs, &temp);
196284990Scy	return temp;
197284990Scy}
198284990Scy
199284990Scy
200284990Scy
201284990Scyvoid l_fp_swap(l_fp * first, l_fp *second){
202284990Scy	l_fp temp = *second;
203284990Scy
204284990Scy	*second = *first;
205284990Scy	*first = temp;
206284990Scy
207284990Scy}
208284990Scy
209284990Scy
210284990Scy/*
211284990ScyLFP::LFP()
212284990Scy{
213284990Scy	_v.l_ui = 0;
214284990Scy	_v.l_uf = 0;
215284990Scy}
216284990Scy
217284990Scy
218284990Scy
219284990Scystd::string
220284990ScyLFP::toString() const
221284990Scy{
222284990Scy	std::ostringstream oss;
223284990Scy	toStream(oss);
224284990Scy	return oss.str();
225284990Scy}
226284990Scy
227284990Scystd::ostream&
228284990ScyLFP::toStream(std::ostream &os) const
229284990Scy{
230284990Scy	return os
231284990Scy	    << mfptoa(_v.l_ui, _v.l_uf, 9)
232284990Scy	    << " [$" << std::setw(8) << std::setfill('0') << std::hex << _v.l_ui
233284990Scy	    <<  ':'  << std::setw(8) << std::setfill('0') << std::hex << _v.l_uf
234284990Scy	    << ']';
235284990Scy}
236284990Scy
237284990Scybool LFP::operator==(const LFP &rhs) const
238284990Scy{
239284990Scy	return L_ISEQU(&_v, &rhs._v);
240284990Scy}
241284990Scy
242284990Scy
243284990Scy
244284990Scy*/
245284990Scy
246284990Scy//----------------------------------------------------------------------
247284990Scy// testing the relational macros works better with proper predicate
248284990Scy// formatting functions; it slows down the tests a bit, but makes for
249284990Scy// readable failure messages.
250284990Scy//----------------------------------------------------------------------
251284990Scy
252284990Scy
253284990Scytypedef int bool; //typedef enum { FALSE, TRUE } boolean; -> can't use this because TRUE and FALSE are already defined
254284990Scy
255284990Scy
256284990Scybool l_isgt (const l_fp first, const l_fp second)
257284990Scy	{ return L_ISGT(&first, &second); }
258284990Scybool l_isgtu(const l_fp first, const l_fp second)
259284990Scy	{ return L_ISGTU(&first, &second); }
260284990Scybool l_ishis(const l_fp first, const l_fp second)
261284990Scy	{ return L_ISHIS(&first, &second); }
262284990Scybool l_isgeq(const l_fp first, const l_fp second)
263284990Scy	{ return L_ISGEQ(&first, &second); }
264284990Scybool l_isequ(const l_fp first, const l_fp second)
265284990Scy	{ return L_ISEQU(&first, &second); }
266284990Scy
267284990Scy
268284990Scy//----------------------------------------------------------------------
269284990Scy// test data table for add/sub and compare
270284990Scy//----------------------------------------------------------------------
271284990Scy
272284990Scy
273284990Scystatic const lfp_hl addsub_tab[][3] = {
274284990Scy	// trivial idendity:
275284990Scy	{{0 ,0         }, { 0,0         }, { 0,0}},
276284990Scy	// with carry from fraction and sign change:
277284990Scy	{{-1,0x80000000}, { 0,0x80000000}, { 0,0}},
278284990Scy	// without carry from fraction
279284990Scy	{{ 1,0x40000000}, { 1,0x40000000}, { 2,0x80000000}},
280284990Scy	// with carry from fraction:
281284990Scy	{{ 1,0xC0000000}, { 1,0xC0000000}, { 3,0x80000000}},
282284990Scy	// with carry from fraction and sign change:
283284990Scy	{{0x7FFFFFFF, 0x7FFFFFFF}, {0x7FFFFFFF,0x7FFFFFFF}, {0xFFFFFFFE,0xFFFFFFFE}},
284284990Scy	// two tests w/o carry (used for l_fp<-->double):
285284990Scy	{{0x55555555,0xAAAAAAAA}, {0x11111111,0x11111111}, {0x66666666,0xBBBBBBBB}},
286284990Scy	{{0x55555555,0x55555555}, {0x11111111,0x11111111}, {0x66666666,0x66666666}},
287284990Scy	// wide-range test, triggers compare trouble
288284990Scy	{{0x80000000,0x00000001}, {0xFFFFFFFF,0xFFFFFFFE}, {0x7FFFFFFF,0xFFFFFFFF}}
289284990Scy};
290284990Scystatic const size_t addsub_cnt = (sizeof(addsub_tab)/sizeof(addsub_tab[0]));
291284990Scystatic const size_t addsub_tot = (sizeof(addsub_tab)/sizeof(addsub_tab[0][0]));
292284990Scy
293284990Scy
294284990Scy
295284990Scy//----------------------------------------------------------------------
296284990Scy// epsilon estimation for the precision of a conversion double --> l_fp
297284990Scy//
298284990Scy// The error estimation limit is as follows:
299284990Scy//  * The 'l_fp' fixed point fraction has 32 bits precision, so we allow
300284990Scy//    for the LSB to toggle by clamping the epsilon to be at least 2^(-31)
301284990Scy//
302284990Scy//  * The double mantissa has a precsion 54 bits, so the other minimum is
303284990Scy//    dval * (2^(-53))
304284990Scy//
305284990Scy//  The maximum of those two boundaries is used for the check.
306284990Scy//
307284990Scy// Note: once there are more than 54 bits between the highest and lowest
308284990Scy// '1'-bit of the l_fp value, the roundtrip *will* create truncation
309284990Scy// errors. This is an inherent property caused by the 54-bit mantissa of
310284990Scy// the 'double' type.
311284990Scydouble eps(double d)
312284990Scy{
313284990Scy	return fmax(ldexp(1.0, -31), ldexp(fabs(d), -53)); //max<double>
314284990Scy}
315284990Scy
316284990Scy
317284990Scy
318284990Scy//----------------------------------------------------------------------
319284990Scy// test addition
320284990Scy//----------------------------------------------------------------------
321284990Scyvoid test_AdditionLR() {
322284990Scy
323284990Scy	size_t idx=0;
324284990Scy	for (idx=0; idx < addsub_cnt; ++idx) {
325284990Scy
326284990Scy
327284990Scy		l_fp op1 = l_fp_init(addsub_tab[idx][0].h, addsub_tab[idx][0].l);
328284990Scy		//LFP op1(addsub_tab[idx][0].h, addsub_tab[idx][0].l);
329284990Scy		l_fp op2 = l_fp_init(addsub_tab[idx][1].h, addsub_tab[idx][1].l);
330284990Scy		//LFP exp(addsub_tab[idx][2].h, addsub_tab[idx][2].l);
331284990Scy		l_fp exp = l_fp_init(addsub_tab[idx][2].h, addsub_tab[idx][2].l);
332284990Scy		//LFP res(op1 + op2);
333284990Scy		l_fp res = l_fp_add(op1,op2);
334284990Scy
335284990Scy		TEST_ASSERT_EQUAL_l_fp(exp,res);
336284990Scy		//TEST_ASSERT_EQUAL_MEMORY(&exp, &res,sizeof(exp));
337284990Scy	}
338284990Scy}
339284990Scy
340284990Scyvoid test_AdditionRL() {
341284990Scy
342284990Scy	size_t idx=0;
343284990Scy	for (idx=0; idx < addsub_cnt; ++idx) {
344284990Scy		l_fp op2 = l_fp_init(addsub_tab[idx][0].h, addsub_tab[idx][0].l);
345284990Scy		l_fp op1 = l_fp_init(addsub_tab[idx][1].h, addsub_tab[idx][1].l);
346284990Scy		l_fp exp = l_fp_init(addsub_tab[idx][2].h, addsub_tab[idx][2].l);
347284990Scy		l_fp res = l_fp_add(op1,op2);
348284990Scy
349284990Scy		TEST_ASSERT_EQUAL_l_fp(exp,res);
350284990Scy		//TEST_ASSERT_EQUAL_MEMORY(&exp, &res,sizeof(exp));
351284990Scy	}
352284990Scy}
353284990Scy
354284990Scy
355284990Scy
356284990Scy//----------------------------------------------------------------------
357284990Scy// test subtraction
358284990Scy//----------------------------------------------------------------------
359284990Scyvoid test_SubtractionLR() {
360284990Scy
361284990Scy	size_t idx=0;
362284990Scy	for (idx=0; idx < addsub_cnt; ++idx) {
363284990Scy		l_fp op2 = l_fp_init(addsub_tab[idx][0].h, addsub_tab[idx][0].l);
364284990Scy		l_fp exp = l_fp_init(addsub_tab[idx][1].h, addsub_tab[idx][1].l);
365284990Scy		l_fp op1 = l_fp_init(addsub_tab[idx][2].h, addsub_tab[idx][2].l);
366284990Scy		l_fp res = l_fp_subtract(op1,op2);
367284990Scy		//LFP res(op1 - op2);
368284990Scy
369284990Scy		TEST_ASSERT_EQUAL_l_fp(exp,res);
370284990Scy		//TEST_ASSERT_EQUAL_MEMORY(&exp, &res,sizeof(exp));
371284990Scy	}
372284990Scy}
373284990Scy
374284990Scyvoid test_SubtractionRL() {
375284990Scy
376284990Scy	size_t idx=0;
377284990Scy	for (idx=0; idx < addsub_cnt; ++idx) {
378284990Scy		l_fp exp = l_fp_init(addsub_tab[idx][0].h, addsub_tab[idx][0].l);
379284990Scy		l_fp op2 = l_fp_init(addsub_tab[idx][1].h, addsub_tab[idx][1].l);
380284990Scy		l_fp op1 = l_fp_init(addsub_tab[idx][2].h, addsub_tab[idx][2].l);
381284990Scy		l_fp res = l_fp_subtract(op1,op2);
382284990Scy
383284990Scy		TEST_ASSERT_EQUAL_l_fp(exp,res);
384284990Scy		//TEST_ASSERT_EQUAL_MEMORY(&exp, &res,sizeof(exp));
385284990Scy	}
386284990Scy}
387284990Scy
388284990Scy//----------------------------------------------------------------------
389284990Scy// test negation
390284990Scy//----------------------------------------------------------------------
391284990Scy
392284990Scyvoid test_Negation() {
393284990Scy
394284990Scy	size_t idx=0;
395284990Scy	for (idx=0; idx < addsub_cnt; ++idx) {
396284990Scy		l_fp op1 = l_fp_init(addsub_tab[idx][0].h, addsub_tab[idx][0].l);
397284990Scy		l_fp op2 = l_fp_negate(op1);
398284990Scy		l_fp sum = l_fp_add(op1, op2);
399284990Scy
400284990Scy		l_fp zero = l_fp_init(0,0);
401284990Scy
402284990Scy		TEST_ASSERT_EQUAL_l_fp(zero,sum);
403284990Scy		//TEST_ASSERT_EQUAL_MEMORY(&zero, &sum,sizeof(sum));
404284990Scy
405284990Scy	}
406284990Scy}
407284990Scy
408284990Scy
409284990Scy
410284990Scy//----------------------------------------------------------------------
411284990Scy// test absolute value
412284990Scy//----------------------------------------------------------------------
413284990Scyvoid test_Absolute() {
414284990Scy	size_t idx=0;
415284990Scy	for (idx=0; idx < addsub_cnt; ++idx) {
416284990Scy		l_fp op1 = l_fp_init(addsub_tab[idx][0].h, addsub_tab[idx][0].l);
417284990Scy		l_fp op2 = l_fp_abs(op1);
418284990Scy
419284990Scy		TEST_ASSERT_TRUE(l_fp_signum(op2) >= 0);
420284990Scy
421284990Scy		if (l_fp_signum(op1) >= 0)
422284990Scy			op1 = l_fp_subtract(op1,op2); //op1 -= op2;
423284990Scy
424284990Scy		else
425284990Scy			op1 = l_fp_add(op1,op2);
426284990Scy
427284990Scy		l_fp zero = l_fp_init(0,0);
428284990Scy
429284990Scy		TEST_ASSERT_EQUAL_l_fp(zero,op1);
430284990Scy		//TEST_ASSERT_EQUAL_MEMORY(&zero, &op1,sizeof(op1));
431284990Scy	}
432284990Scy
433284990Scy	// There is one special case we have to check: the minimum
434284990Scy	// value cannot be negated, or, to be more precise, the
435284990Scy	// negation reproduces the original pattern.
436284990Scy	l_fp minVal = l_fp_init(0x80000000, 0x00000000);
437284990Scy	l_fp minAbs = l_fp_abs(minVal);
438284990Scy	TEST_ASSERT_EQUAL(-1, l_fp_signum(minVal));
439284990Scy
440284990Scy	TEST_ASSERT_EQUAL_l_fp(minVal,minAbs);
441284990Scy	//TEST_ASSERT_EQUAL_MEMORY(&minVal, &minAbs,sizeof(minAbs));
442284990Scy}
443284990Scy
444284990Scy
445284990Scy//----------------------------------------------------------------------
446284990Scy// fp -> double -> fp rountrip test
447284990Scy//----------------------------------------------------------------------
448284990Scyvoid test_FDF_RoundTrip() {
449284990Scy	// since a l_fp has 64 bits in it's mantissa and a double has
450284990Scy	// only 54 bits available (including the hidden '1') we have to
451284990Scy	// make a few concessions on the roundtrip precision. The 'eps()'
452284990Scy	// function makes an educated guess about the avilable precision
453284990Scy	// and checks the difference in the two 'l_fp' values against
454284990Scy	// that limit.
455284990Scy	size_t idx=0;
456284990Scy	for (idx=0; idx < addsub_cnt; ++idx) {
457284990Scy		l_fp op1 = l_fp_init(addsub_tab[idx][0].h, addsub_tab[idx][0].l);
458284990Scy		double op2 = l_fp_convert_to_double(op1);
459284990Scy		l_fp op3 = l_fp_init_from_double(op2);
460284990Scy
461284990Scy		// for manual checks only:
462284990Scy		// std::cout << std::setprecision(16) << op2 << std::endl;
463284990Scy
464284990Scy		l_fp temp = l_fp_subtract(op1,op3);
465284990Scy		double d = l_fp_convert_to_double(temp);
466284990Scy 		TEST_ASSERT_DOUBLE_WITHIN(eps(op2),0.0, fabs(d)); //delta,epected,actual
467284990Scy
468284990Scy		//ASSERT_LE(fabs(op1-op3), eps(op2)); //unity has no equivalent of LE!!!
469284990Scy		//you could use TEST_ASSERT_TRUE(IsLE(fabs(op1-op3), eps(op2)));
470284990Scy	}
471284990Scy}
472284990Scy
473284990Scy
474284990Scy//----------------------------------------------------------------------
475284990Scy// test the compare stuff
476284990Scy//
477284990Scy// This uses the local compare and checks if the operations using the
478284990Scy// macros in 'ntp_fp.h' produce mathing results.
479284990Scy// ----------------------------------------------------------------------
480284990Scyvoid test_SignedRelOps() {
481284990Scy	//const lfp_hl * tv(&addsub_tab[0][0]);
482284990Scy	const lfp_hl * tv = (&addsub_tab[0][0]);
483284990Scy	size_t lc ;
484284990Scy	for (lc=addsub_tot-1; lc; --lc,++tv) {
485284990Scy		l_fp op1 = l_fp_init(tv[0].h,tv[0].l);
486284990Scy		l_fp op2 = l_fp_init(tv[1].h,tv[1].l);
487284990Scy		//int cmp(op1.scmp(op2));
488284990Scy		int cmp = l_fp_scmp(op1,op2);
489284990Scy
490284990Scy		switch (cmp) {
491284990Scy		case -1:
492284990Scy			//printf("op1:%d %d, op2:%d %d\n",op1.l_uf,op1.l_ui,op2.l_uf,op2.l_ui);
493284990Scy			//std::swap(op1, op2);
494284990Scy			l_fp_swap(&op1,&op2);
495284990Scy			//printf("op1:%d %d, op2:%d %d\n",op1.l_uf,op1.l_ui,op2.l_uf,op2.l_ui);
496284990Scy		case 1:
497284990Scy			TEST_ASSERT_TRUE (l_isgt(op1,op2));
498284990Scy			TEST_ASSERT_FALSE(l_isgt(op2,op1));
499284990Scy
500284990Scy			TEST_ASSERT_TRUE (l_isgeq(op1,op2));
501284990Scy			TEST_ASSERT_FALSE(l_isgeq(op2,op1));
502284990Scy
503284990Scy			TEST_ASSERT_FALSE(l_isequ(op1,op2));
504284990Scy			TEST_ASSERT_FALSE(l_isequ(op2,op1));
505284990Scy			break;
506284990Scy		case 0:
507284990Scy			TEST_ASSERT_FALSE(l_isgt(op1,op2));
508284990Scy			TEST_ASSERT_FALSE(l_isgt(op2,op1));
509284990Scy
510284990Scy			TEST_ASSERT_TRUE (l_isgeq(op1,op2));
511284990Scy			TEST_ASSERT_TRUE (l_isgeq(op2,op1));
512284990Scy
513284990Scy			TEST_ASSERT_TRUE (l_isequ(op1,op2));
514284990Scy			TEST_ASSERT_TRUE (l_isequ(op2,op1));
515284990Scy			break;
516284990Scy		default:
517284990Scy			TEST_FAIL_MESSAGE("unexpected UCMP result: " );
518284990Scy			//TEST_ASSERT_FAIL() << "unexpected SCMP result: " << cmp;
519284990Scy		}
520284990Scy	}
521284990Scy}
522284990Scy
523284990Scyvoid test_UnsignedRelOps() {
524284990Scy	const lfp_hl * tv =(&addsub_tab[0][0]);
525284990Scy	size_t lc;
526284990Scy	for (lc=addsub_tot-1; lc; --lc,++tv) {
527284990Scy		l_fp op1 = l_fp_init(tv[0].h,tv[0].l);
528284990Scy		l_fp op2 = l_fp_init(tv[1].h,tv[1].l);
529284990Scy		int cmp = l_fp_ucmp(op1,op2);
530284990Scy
531284990Scy		switch (cmp) {
532284990Scy		case -1:
533284990Scy			//printf("op1:%d %d, op2:%d %d\n",op1.l_uf,op1.l_ui,op2.l_uf,op2.l_ui);
534284990Scy			l_fp_swap(&op1, &op2);
535284990Scy			//printf("op1:%d %d, op2:%d %d\n",op1.l_uf,op1.l_ui,op2.l_uf,op2.l_ui);
536284990Scy		case 1:
537284990Scy			TEST_ASSERT_TRUE (l_isgtu(op1,op2));
538284990Scy			TEST_ASSERT_FALSE(l_isgtu(op2,op1));
539284990Scy
540284990Scy			TEST_ASSERT_TRUE (l_ishis(op1,op2));
541284990Scy			TEST_ASSERT_FALSE(l_ishis(op2,op1));
542284990Scy			break;
543284990Scy		case 0:
544284990Scy			TEST_ASSERT_FALSE(l_isgtu(op1,op2));
545284990Scy			TEST_ASSERT_FALSE(l_isgtu(op2,op1));
546284990Scy
547284990Scy			TEST_ASSERT_TRUE (l_ishis(op1,op2));
548284990Scy			TEST_ASSERT_TRUE (l_ishis(op2,op1));
549284990Scy			break;
550284990Scy		default:
551284990Scy			TEST_FAIL_MESSAGE("unexpected UCMP result: " );
552284990Scy			//FAIL() << "unexpected UCMP result: " << cmp;
553284990Scy		}
554284990Scy	}
555284990Scy}
556284990Scy/*
557284990Scy*/
558284990Scy
559284990Scy//----------------------------------------------------------------------
560284990Scy// that's all folks... but feel free to add things!
561284990Scy//----------------------------------------------------------------------
562