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