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
16void
17PUtilTest::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
33void
34PUtilTest::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
81void
82PUtilTest::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
99void
100PUtilTest::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
183void
184PUtilTest::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
220void
221PUtilTest::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
240void
241PUtilTest::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
278void
279PUtilTest::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?
320void
321PUtilTest::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
369void
370PUtilTest::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
396void
397PUtilTest::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
423void
424PUtilTest::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
450void
451PUtilTest::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
477void
478PUtilTest::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
504void
505PUtilTest::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
531void
532PUtilTest::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