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