1 // Copyright (C) 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /******************************************************************** 4 * COPYRIGHT: 5 * Copyright (c) 1997-2011, International Business Machines Corporation and 6 * others. All Rights Reserved. 7 ********************************************************************/ 8 9 #include "tsputil.h" 10 11 #include <float.h> // DBL_MAX, DBL_MIN 12 #include "putilimp.h" 13 14 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break; 15 16 void 17 PUtilTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) 18 { 19 //if (exec) logln("TestSuite PUtilTest: "); 20 switch (index) { 21 CASE(0, testMaxMin) 22 CASE(1, testNaN) 23 CASE(2, testPositiveInfinity) 24 CASE(3, testNegativeInfinity) 25 CASE(4, testZero) 26 // CASE(, testIEEEremainder) 27 28 default: name = ""; break; //needed to end loop 29 } 30 } 31 32 #if 0 33 void 34 PUtilTest::testIEEEremainder() 35 { 36 double pinf = uprv_getInfinity(); 37 double ninf = -uprv_getInfinity(); 38 double nan = uprv_getNaN(); 39 double pzero = 0.0; 40 double nzero = 0.0; 41 42 nzero *= -1; 43 44 // simple remainder checks 45 remainderTest(7.0, 2.5, -0.5); 46 remainderTest(7.0, -2.5, -0.5); 47 #if U_PLATFORM != U_PF_OS390 48 // ### TODO: 49 // The following tests fails on S/390 with IEEE support in release builds; 50 // debug builds work. 51 // The functioning of ChoiceFormat is not affected by this bug. 52 remainderTest(-7.0, 2.5, 0.5); 53 remainderTest(-7.0, -2.5, 0.5); 54 #endif 55 remainderTest(5.0, 3.0, -1.0); 56 57 // this should work 58 //remainderTest(43.7, 2.5, 1.25); 59 60 /* 61 62 // infinity and real 63 remainderTest(pinf, 1.0, 1.25); 64 remainderTest(1.0, pinf, 1.0); 65 remainderTest(ninf, 1.0, 1.25); 66 remainderTest(1.0, ninf, 1.0); 67 68 // test infinity and nan 69 remainderTest(ninf, pinf, 1.25); 70 remainderTest(ninf, nan, 1.25); 71 remainderTest(pinf, nan, 1.25); 72 73 // test infinity and zero 74 remainderTest(pinf, pzero, 1.25); 75 remainderTest(pinf, nzero, 1.25); 76 remainderTest(ninf, pzero, 1.25); 77 remainderTest(ninf, nzero, 1.25); 78 */ 79 } 80 81 void 82 PUtilTest::remainderTest(double x, double y, double exp) 83 { 84 double result = uprv_IEEEremainder(x,y); 85 86 if( uprv_isNaN(result) && 87 ! ( uprv_isNaN(x) || uprv_isNaN(y))) { 88 errln(UnicodeString("FAIL: got NaN as result without NaN as argument")); 89 errln(UnicodeString(" IEEEremainder(") + x + ", " + y + ") is " + result + ", expected " + exp); 90 } 91 else if(result != exp) 92 errln(UnicodeString("FAIL: IEEEremainder(") + x + ", " + y + ") is " + result + ", expected " + exp); 93 else 94 logln(UnicodeString("OK: IEEEremainder(") + x + ", " + y + ") is " + result); 95 96 } 97 #endif 98 99 void 100 PUtilTest::testMaxMin() 101 { 102 double pinf = uprv_getInfinity(); 103 double ninf = -uprv_getInfinity(); 104 double nan = uprv_getNaN(); 105 double pzero = 0.0; 106 double nzero = 0.0; 107 108 nzero *= -1; 109 110 // +Inf with -Inf 111 maxMinTest(pinf, ninf, pinf, TRUE); 112 maxMinTest(pinf, ninf, ninf, FALSE); 113 114 // +Inf with +0 and -0 115 maxMinTest(pinf, pzero, pinf, TRUE); 116 maxMinTest(pinf, pzero, pzero, FALSE); 117 maxMinTest(pinf, nzero, pinf, TRUE); 118 maxMinTest(pinf, nzero, nzero, FALSE); 119 120 // -Inf with +0 and -0 121 maxMinTest(ninf, pzero, pzero, TRUE); 122 maxMinTest(ninf, pzero, ninf, FALSE); 123 maxMinTest(ninf, nzero, nzero, TRUE); 124 maxMinTest(ninf, nzero, ninf, FALSE); 125 126 // NaN with +Inf and -Inf 127 maxMinTest(pinf, nan, nan, TRUE); 128 maxMinTest(pinf, nan, nan, FALSE); 129 maxMinTest(ninf, nan, nan, TRUE); 130 maxMinTest(ninf, nan, nan, FALSE); 131 132 // NaN with NaN 133 maxMinTest(nan, nan, nan, TRUE); 134 maxMinTest(nan, nan, nan, FALSE); 135 136 // NaN with +0 and -0 137 maxMinTest(nan, pzero, nan, TRUE); 138 maxMinTest(nan, pzero, nan, FALSE); 139 maxMinTest(nan, nzero, nan, TRUE); 140 maxMinTest(nan, nzero, nan, FALSE); 141 142 // +Inf with DBL_MAX and DBL_MIN 143 maxMinTest(pinf, DBL_MAX, pinf, TRUE); 144 maxMinTest(pinf, -DBL_MAX, pinf, TRUE); 145 maxMinTest(pinf, DBL_MIN, pinf, TRUE); 146 maxMinTest(pinf, -DBL_MIN, pinf, TRUE); 147 maxMinTest(pinf, DBL_MIN, DBL_MIN, FALSE); 148 maxMinTest(pinf, -DBL_MIN, -DBL_MIN, FALSE); 149 maxMinTest(pinf, DBL_MAX, DBL_MAX, FALSE); 150 maxMinTest(pinf, -DBL_MAX, -DBL_MAX, FALSE); 151 152 // -Inf with DBL_MAX and DBL_MIN 153 maxMinTest(ninf, DBL_MAX, DBL_MAX, TRUE); 154 maxMinTest(ninf, -DBL_MAX, -DBL_MAX, TRUE); 155 maxMinTest(ninf, DBL_MIN, DBL_MIN, TRUE); 156 maxMinTest(ninf, -DBL_MIN, -DBL_MIN, TRUE); 157 maxMinTest(ninf, DBL_MIN, ninf, FALSE); 158 maxMinTest(ninf, -DBL_MIN, ninf, FALSE); 159 maxMinTest(ninf, DBL_MAX, ninf, FALSE); 160 maxMinTest(ninf, -DBL_MAX, ninf, FALSE); 161 162 // +0 with DBL_MAX and DBL_MIN 163 maxMinTest(pzero, DBL_MAX, DBL_MAX, TRUE); 164 maxMinTest(pzero, -DBL_MAX, pzero, TRUE); 165 maxMinTest(pzero, DBL_MIN, DBL_MIN, TRUE); 166 maxMinTest(pzero, -DBL_MIN, pzero, TRUE); 167 maxMinTest(pzero, DBL_MIN, pzero, FALSE); 168 maxMinTest(pzero, -DBL_MIN, -DBL_MIN, FALSE); 169 maxMinTest(pzero, DBL_MAX, pzero, FALSE); 170 maxMinTest(pzero, -DBL_MAX, -DBL_MAX, FALSE); 171 172 // -0 with DBL_MAX and DBL_MIN 173 maxMinTest(nzero, DBL_MAX, DBL_MAX, TRUE); 174 maxMinTest(nzero, -DBL_MAX, nzero, TRUE); 175 maxMinTest(nzero, DBL_MIN, DBL_MIN, TRUE); 176 maxMinTest(nzero, -DBL_MIN, nzero, TRUE); 177 maxMinTest(nzero, DBL_MIN, nzero, FALSE); 178 maxMinTest(nzero, -DBL_MIN, -DBL_MIN, FALSE); 179 maxMinTest(nzero, DBL_MAX, nzero, FALSE); 180 maxMinTest(nzero, -DBL_MAX, -DBL_MAX, FALSE); 181 } 182 183 void 184 PUtilTest::maxMinTest(double a, double b, double exp, UBool max) 185 { 186 double result = 0.0; 187 188 if(max) 189 result = uprv_fmax(a, b); 190 else 191 result = uprv_fmin(a, b); 192 193 UBool nanResultOK = (uprv_isNaN(a) || uprv_isNaN(b)); 194 195 if(uprv_isNaN(result) && ! nanResultOK) { 196 errln(UnicodeString("FAIL: got NaN as result without NaN as argument")); 197 if(max) 198 errln(UnicodeString(" max(") + a + ", " + b + ") is " + result + ", expected " + exp); 199 else 200 errln(UnicodeString(" min(") + a + ", " + b + ") is " + result + ", expected " + exp); 201 } 202 else if(result != exp && ! (uprv_isNaN(result) || uprv_isNaN(exp))) 203 if(max) 204 errln(UnicodeString("FAIL: max(") + a + ", " + b + ") is " + result + ", expected " + exp); 205 else 206 errln(UnicodeString("FAIL: min(") + a + ", " + b + ") is " + result + ", expected " + exp); 207 else { 208 if (verbose) { 209 if(max) 210 logln(UnicodeString("OK: max(") + a + ", " + b + ") is " + result); 211 else 212 logln(UnicodeString("OK: min(") + a + ", " + b + ") is " + result); 213 } 214 } 215 } 216 //============================== 217 218 // NaN is weird- comparisons with NaN _always_ return false, with the 219 // exception of !=, which _always_ returns true 220 void 221 PUtilTest::testNaN(void) 222 { 223 logln("NaN tests may show that the expected NaN!=NaN etc. is not true on some"); 224 logln("platforms; however, ICU does not rely on them because it defines"); 225 logln("and uses uprv_isNaN(). Therefore, most failing NaN tests only report warnings."); 226 227 PUtilTest::testIsNaN(); 228 PUtilTest::NaNGT(); 229 PUtilTest::NaNLT(); 230 PUtilTest::NaNGTE(); 231 PUtilTest::NaNLTE(); 232 PUtilTest::NaNE(); 233 PUtilTest::NaNNE(); 234 235 logln("End of NaN tests."); 236 } 237 238 //============================== 239 240 void 241 PUtilTest::testPositiveInfinity(void) 242 { 243 double pinf = uprv_getInfinity(); 244 double ninf = -uprv_getInfinity(); 245 double ten = 10.0; 246 247 if(uprv_isInfinite(pinf) != TRUE) { 248 errln("FAIL: isInfinite(+Infinity) returned FALSE, should be TRUE."); 249 } 250 251 if(uprv_isPositiveInfinity(pinf) != TRUE) { 252 errln("FAIL: isPositiveInfinity(+Infinity) returned FALSE, should be TRUE."); 253 } 254 255 if(uprv_isNegativeInfinity(pinf) != FALSE) { 256 errln("FAIL: isNegativeInfinity(+Infinity) returned TRUE, should be FALSE."); 257 } 258 259 if((pinf > DBL_MAX) != TRUE) { 260 errln("FAIL: +Infinity > DBL_MAX returned FALSE, should be TRUE."); 261 } 262 263 if((pinf > DBL_MIN) != TRUE) { 264 errln("FAIL: +Infinity > DBL_MIN returned FALSE, should be TRUE."); 265 } 266 267 if((pinf > ninf) != TRUE) { 268 errln("FAIL: +Infinity > -Infinity returned FALSE, should be TRUE."); 269 } 270 271 if((pinf > ten) != TRUE) { 272 errln("FAIL: +Infinity > 10.0 returned FALSE, should be TRUE."); 273 } 274 } 275 276 //============================== 277 278 void 279 PUtilTest::testNegativeInfinity(void) 280 { 281 double pinf = uprv_getInfinity(); 282 double ninf = -uprv_getInfinity(); 283 double ten = 10.0; 284 285 if(uprv_isInfinite(ninf) != TRUE) { 286 errln("FAIL: isInfinite(-Infinity) returned FALSE, should be TRUE."); 287 } 288 289 if(uprv_isNegativeInfinity(ninf) != TRUE) { 290 errln("FAIL: isNegativeInfinity(-Infinity) returned FALSE, should be TRUE."); 291 } 292 293 if(uprv_isPositiveInfinity(ninf) != FALSE) { 294 errln("FAIL: isPositiveInfinity(-Infinity) returned TRUE, should be FALSE."); 295 } 296 297 if((ninf < DBL_MAX) != TRUE) { 298 errln("FAIL: -Infinity < DBL_MAX returned FALSE, should be TRUE."); 299 } 300 301 if((ninf < DBL_MIN) != TRUE) { 302 errln("FAIL: -Infinity < DBL_MIN returned FALSE, should be TRUE."); 303 } 304 305 if((ninf < pinf) != TRUE) { 306 errln("FAIL: -Infinity < +Infinity returned FALSE, should be TRUE."); 307 } 308 309 if((ninf < ten) != TRUE) { 310 errln("FAIL: -Infinity < 10.0 returned FALSE, should be TRUE."); 311 } 312 } 313 314 //============================== 315 316 // notes about zero: 317 // -0.0 == 0.0 == TRUE 318 // -0.0 < 0.0 == FALSE 319 // generating -0.0 must be done at runtime. compiler apparently ignores sign? 320 void 321 PUtilTest::testZero(void) 322 { 323 // volatile is used to fake out the compiler optimizer. We really want to divide by 0. 324 volatile double pzero = 0.0; 325 volatile double nzero = 0.0; 326 327 nzero *= -1; 328 329 if((pzero == nzero) != TRUE) { 330 errln("FAIL: 0.0 == -0.0 returned FALSE, should be TRUE."); 331 } 332 333 if((pzero > nzero) != FALSE) { 334 errln("FAIL: 0.0 > -0.0 returned TRUE, should be FALSE."); 335 } 336 337 if((pzero >= nzero) != TRUE) { 338 errln("FAIL: 0.0 >= -0.0 returned FALSE, should be TRUE."); 339 } 340 341 if((pzero < nzero) != FALSE) { 342 errln("FAIL: 0.0 < -0.0 returned TRUE, should be FALSE."); 343 } 344 345 if((pzero <= nzero) != TRUE) { 346 errln("FAIL: 0.0 <= -0.0 returned FALSE, should be TRUE."); 347 } 348 #if U_PLATFORM != U_PF_OS400 /* OS/400 will generate divide by zero exception MCH1214 */ 349 if(uprv_isInfinite(1/pzero) != TRUE) { 350 errln("FAIL: isInfinite(1/0.0) returned FALSE, should be TRUE."); 351 } 352 353 if(uprv_isInfinite(1/nzero) != TRUE) { 354 errln("FAIL: isInfinite(1/-0.0) returned FALSE, should be TRUE."); 355 } 356 357 if(uprv_isPositiveInfinity(1/pzero) != TRUE) { 358 errln("FAIL: isPositiveInfinity(1/0.0) returned FALSE, should be TRUE."); 359 } 360 361 if(uprv_isNegativeInfinity(1/nzero) != TRUE) { 362 errln("FAIL: isNegativeInfinity(1/-0.0) returned FALSE, should be TRUE."); 363 } 364 #endif 365 } 366 367 //============================== 368 369 void 370 PUtilTest::testIsNaN(void) 371 { 372 double pinf = uprv_getInfinity(); 373 double ninf = -uprv_getInfinity(); 374 double nan = uprv_getNaN(); 375 double ten = 10.0; 376 377 if(uprv_isNaN(nan) == FALSE) { 378 errln("FAIL: isNaN() returned FALSE for NaN."); 379 } 380 381 if(uprv_isNaN(pinf) == TRUE) { 382 errln("FAIL: isNaN() returned TRUE for +Infinity."); 383 } 384 385 if(uprv_isNaN(ninf) == TRUE) { 386 errln("FAIL: isNaN() returned TRUE for -Infinity."); 387 } 388 389 if(uprv_isNaN(ten) == TRUE) { 390 errln("FAIL: isNaN() returned TRUE for 10.0."); 391 } 392 } 393 394 //============================== 395 396 void 397 PUtilTest::NaNGT(void) 398 { 399 double pinf = uprv_getInfinity(); 400 double ninf = -uprv_getInfinity(); 401 double nan = uprv_getNaN(); 402 double ten = 10.0; 403 404 if((nan > nan) != FALSE) { 405 logln("WARNING: NaN > NaN returned TRUE, should be FALSE"); 406 } 407 408 if((nan > pinf) != FALSE) { 409 logln("WARNING: NaN > +Infinity returned TRUE, should be FALSE"); 410 } 411 412 if((nan > ninf) != FALSE) { 413 logln("WARNING: NaN > -Infinity returned TRUE, should be FALSE"); 414 } 415 416 if((nan > ten) != FALSE) { 417 logln("WARNING: NaN > 10.0 returned TRUE, should be FALSE"); 418 } 419 } 420 421 //============================== 422 423 void 424 PUtilTest::NaNLT(void) 425 { 426 double pinf = uprv_getInfinity(); 427 double ninf = -uprv_getInfinity(); 428 double nan = uprv_getNaN(); 429 double ten = 10.0; 430 431 if((nan < nan) != FALSE) { 432 logln("WARNING: NaN < NaN returned TRUE, should be FALSE"); 433 } 434 435 if((nan < pinf) != FALSE) { 436 logln("WARNING: NaN < +Infinity returned TRUE, should be FALSE"); 437 } 438 439 if((nan < ninf) != FALSE) { 440 logln("WARNING: NaN < -Infinity returned TRUE, should be FALSE"); 441 } 442 443 if((nan < ten) != FALSE) { 444 logln("WARNING: NaN < 10.0 returned TRUE, should be FALSE"); 445 } 446 } 447 448 //============================== 449 450 void 451 PUtilTest::NaNGTE(void) 452 { 453 double pinf = uprv_getInfinity(); 454 double ninf = -uprv_getInfinity(); 455 double nan = uprv_getNaN(); 456 double ten = 10.0; 457 458 if((nan >= nan) != FALSE) { 459 logln("WARNING: NaN >= NaN returned TRUE, should be FALSE"); 460 } 461 462 if((nan >= pinf) != FALSE) { 463 logln("WARNING: NaN >= +Infinity returned TRUE, should be FALSE"); 464 } 465 466 if((nan >= ninf) != FALSE) { 467 logln("WARNING: NaN >= -Infinity returned TRUE, should be FALSE"); 468 } 469 470 if((nan >= ten) != FALSE) { 471 logln("WARNING: NaN >= 10.0 returned TRUE, should be FALSE"); 472 } 473 } 474 475 //============================== 476 477 void 478 PUtilTest::NaNLTE(void) 479 { 480 double pinf = uprv_getInfinity(); 481 double ninf = -uprv_getInfinity(); 482 double nan = uprv_getNaN(); 483 double ten = 10.0; 484 485 if((nan <= nan) != FALSE) { 486 logln("WARNING: NaN <= NaN returned TRUE, should be FALSE"); 487 } 488 489 if((nan <= pinf) != FALSE) { 490 logln("WARNING: NaN <= +Infinity returned TRUE, should be FALSE"); 491 } 492 493 if((nan <= ninf) != FALSE) { 494 logln("WARNING: NaN <= -Infinity returned TRUE, should be FALSE"); 495 } 496 497 if((nan <= ten) != FALSE) { 498 logln("WARNING: NaN <= 10.0 returned TRUE, should be FALSE"); 499 } 500 } 501 502 //============================== 503 504 void 505 PUtilTest::NaNE(void) 506 { 507 double pinf = uprv_getInfinity(); 508 double ninf = -uprv_getInfinity(); 509 double nan = uprv_getNaN(); 510 double ten = 10.0; 511 512 if((nan == nan) != FALSE) { 513 logln("WARNING: NaN == NaN returned TRUE, should be FALSE"); 514 } 515 516 if((nan == pinf) != FALSE) { 517 logln("WARNING: NaN == +Infinity returned TRUE, should be FALSE"); 518 } 519 520 if((nan == ninf) != FALSE) { 521 logln("WARNING: NaN == -Infinity returned TRUE, should be FALSE"); 522 } 523 524 if((nan == ten) != FALSE) { 525 logln("WARNING: NaN == 10.0 returned TRUE, should be FALSE"); 526 } 527 } 528 529 //============================== 530 531 void 532 PUtilTest::NaNNE(void) 533 { 534 double pinf = uprv_getInfinity(); 535 double ninf = -uprv_getInfinity(); 536 double nan = uprv_getNaN(); 537 double ten = 10.0; 538 539 if((nan != nan) != TRUE) { 540 logln("WARNING: NaN != NaN returned FALSE, should be TRUE"); 541 } 542 543 if((nan != pinf) != TRUE) { 544 logln("WARNING: NaN != +Infinity returned FALSE, should be TRUE"); 545 } 546 547 if((nan != ninf) != TRUE) { 548 logln("WARNING: NaN != -Infinity returned FALSE, should be TRUE"); 549 } 550 551 if((nan != ten) != TRUE) { 552 logln("WARNING: NaN != 10.0 returned FALSE, should be TRUE"); 553 } 554 } 555