1 // © 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
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)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
testMaxMin()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
maxMinTest(double a,double b,double exp,UBool max)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
testNaN(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
testPositiveInfinity(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
testNegativeInfinity(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
testZero(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
testIsNaN(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
NaNGT(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
NaNLT(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
NaNGTE(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
NaNLTE(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
NaNE(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
NaNNE(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