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