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 
14 void
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)15 PUtilTest::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
31 void
32 PUtilTest::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 
79 void
80 PUtilTest::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 
97 void
testMaxMin()98 PUtilTest::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 
181 void
maxMinTest(double a,double b,double exp,UBool max)182 PUtilTest::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
218 void
testNaN(void)219 PUtilTest::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 
238 void
testPositiveInfinity(void)239 PUtilTest::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 
276 void
testNegativeInfinity(void)277 PUtilTest::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?
318 void
testZero(void)319 PUtilTest::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 
367 void
testIsNaN(void)368 PUtilTest::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 
394 void
NaNGT(void)395 PUtilTest::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 
421 void
NaNLT(void)422 PUtilTest::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 
448 void
NaNGTE(void)449 PUtilTest::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 
475 void
NaNLTE(void)476 PUtilTest::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 
502 void
NaNE(void)503 PUtilTest::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 
529 void
NaNNE(void)530 PUtilTest::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