blob: 4123451ed5dc75be8b0bd0926f2f748fa907bec2 [file] [log] [blame]
darcy32db4492009-01-26 19:49:26 -08001/*
2 * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23
24/*
25 * @test
26 * @bug 4860891 4826732 4780454 4939441 4826652
27 * @summary Tests for IEEE 754[R] recommended functions and similar methods
28 * @author Joseph D. Darcy
29 * @compile -source 1.5 IeeeRecommendedTests.java
30 * @run main IeeeRecommendedTests
31 */
32
33import sun.misc.FpUtils;
34import sun.misc.DoubleConsts;
35import sun.misc.FloatConsts;
36
37public class IeeeRecommendedTests {
38 private IeeeRecommendedTests(){}
39
40 static final float NaNf = Float.NaN;
41 static final double NaNd = Double.NaN;
42 static final float infinityF = Float.POSITIVE_INFINITY;
43 static final double infinityD = Double.POSITIVE_INFINITY;
44
45 static final float Float_MAX_VALUEmm = 0x1.fffffcP+127f;
46 static final float Float_MAX_SUBNORMAL = 0x0.fffffeP-126f;
47 static final float Float_MAX_SUBNORMALmm = 0x0.fffffcP-126f;
48
49 static final double Double_MAX_VALUEmm = 0x1.ffffffffffffeP+1023;
50 static final double Double_MAX_SUBNORMAL = 0x0.fffffffffffffP-1022;
51 static final double Double_MAX_SUBNORMALmm = 0x0.ffffffffffffeP-1022;
52
53 // Initialize shared random number generator
54 static java.util.Random rand = new java.util.Random();
55
56 /**
57 * Returns a floating-point power of two in the normal range.
58 */
59 static double powerOfTwoD(int n) {
60 return Double.longBitsToDouble((((long)n + (long)DoubleConsts.MAX_EXPONENT) <<
61 (DoubleConsts.SIGNIFICAND_WIDTH-1))
62 & DoubleConsts.EXP_BIT_MASK);
63 }
64
65 /**
66 * Returns a floating-point power of two in the normal range.
67 */
68 static float powerOfTwoF(int n) {
69 return Float.intBitsToFloat(((n + FloatConsts.MAX_EXPONENT) <<
70 (FloatConsts.SIGNIFICAND_WIDTH-1))
71 & FloatConsts.EXP_BIT_MASK);
72 }
73
74 /* ******************** getExponent tests ****************************** */
75
76 /*
77 * The tests for getExponent should test the special values (NaN, +/-
78 * infinity, etc.), test the endpoints of each binade (set of
79 * floating-point values with the same exponent), and for good
80 * measure, test some random values within each binade. Testing
81 * the endpoints of each binade includes testing both positive and
82 * negative numbers. Subnormal values with different normalized
83 * exponents should be tested too. Both Math and StrictMath
84 * methods should return the same results.
85 */
86
87 /*
88 * Test Math.getExponent and StrictMath.getExponent with +d and -d.
89 */
90 static int testGetExponentCase(float f, int expected) {
91 float minus_f = -f;
92 int failures=0;
93
94 failures+=Tests.test("Math.getExponent(float)", f,
95 Math.getExponent(f), expected);
96 failures+=Tests.test("Math.getExponent(float)", minus_f,
97 Math.getExponent(minus_f), expected);
98
99 failures+=Tests.test("StrictMath.getExponent(float)", f,
100 StrictMath.getExponent(f), expected);
101 failures+=Tests.test("StrictMath.getExponent(float)", minus_f,
102 StrictMath.getExponent(minus_f), expected);
103 return failures;
104 }
105
106 /*
107 * Test Math.getExponent and StrictMath.getExponent with +d and -d.
108 */
109 static int testGetExponentCase(double d, int expected) {
110 double minus_d = -d;
111 int failures=0;
112
113 failures+=Tests.test("Math.getExponent(double)", d,
114 Math.getExponent(d), expected);
115 failures+=Tests.test("Math.getExponent(double)", minus_d,
116 Math.getExponent(minus_d), expected);
117
118 failures+=Tests.test("StrictMath.getExponent(double)", d,
119 StrictMath.getExponent(d), expected);
120 failures+=Tests.test("StrictMath.getExponent(double)", minus_d,
121 StrictMath.getExponent(minus_d), expected);
122 return failures;
123 }
124
125 public static int testFloatGetExponent() {
126 int failures = 0;
127 float [] specialValues = {NaNf,
128 Float.POSITIVE_INFINITY,
129 +0.0f,
130 +1.0f,
131 +2.0f,
132 +16.0f,
133 +Float.MIN_VALUE,
134 +Float_MAX_SUBNORMAL,
135 +FloatConsts.MIN_NORMAL,
136 +Float.MAX_VALUE
137 };
138
139 int [] specialResults = {Float.MAX_EXPONENT + 1, // NaN results
140 Float.MAX_EXPONENT + 1, // Infinite results
141 Float.MIN_EXPONENT - 1, // Zero results
142 0,
143 1,
144 4,
145 FloatConsts.MIN_EXPONENT - 1,
146 -FloatConsts.MAX_EXPONENT,
147 FloatConsts.MIN_EXPONENT,
148 FloatConsts.MAX_EXPONENT
149 };
150
151 // Special value tests
152 for(int i = 0; i < specialValues.length; i++) {
153 failures += testGetExponentCase(specialValues[i], specialResults[i]);
154 }
155
156
157 // Normal exponent tests
158 for(int i = FloatConsts.MIN_EXPONENT; i <= FloatConsts.MAX_EXPONENT; i++) {
159 int result;
160
161 // Create power of two
162 float po2 = powerOfTwoF(i);
163
164 failures += testGetExponentCase(po2, i);
165
166 // Generate some random bit patterns for the significand
167 for(int j = 0; j < 10; j++) {
168 int randSignif = rand.nextInt();
169 float randFloat;
170
171 randFloat = Float.intBitsToFloat( // Exponent
172 (Float.floatToIntBits(po2)&
173 (~FloatConsts.SIGNIF_BIT_MASK)) |
174 // Significand
175 (randSignif &
176 FloatConsts.SIGNIF_BIT_MASK) );
177
178 failures += testGetExponentCase(randFloat, i);
179 }
180
181 if (i > FloatConsts.MIN_EXPONENT) {
182 float po2minus = FpUtils.nextAfter(po2,
183 Float.NEGATIVE_INFINITY);
184 failures += testGetExponentCase(po2minus, i-1);
185 }
186 }
187
188 // Subnormal exponent tests
189
190 /*
191 * Start with MIN_VALUE, left shift, test high value, low
192 * values, and random in between.
193 *
194 * Use nextAfter to calculate, high value of previous binade,
195 * loop count i will indicate how many random bits, if any are
196 * needed.
197 */
198
199 float top=Float.MIN_VALUE;
200 for( int i = 1;
201 i < FloatConsts.SIGNIFICAND_WIDTH;
202 i++, top *= 2.0f) {
203
204 failures += testGetExponentCase(top,
205 FloatConsts.MIN_EXPONENT - 1);
206
207 // Test largest value in next smaller binade
208 if (i >= 3) {// (i == 1) would test 0.0;
209 // (i == 2) would just retest MIN_VALUE
210 testGetExponentCase(FpUtils.nextAfter(top, 0.0f),
211 FloatConsts.MIN_EXPONENT - 1);
212
213 if( i >= 10) {
214 // create a bit mask with (i-1) 1's in the low order
215 // bits
216 int mask = ~((~0)<<(i-1));
217 float randFloat = Float.intBitsToFloat( // Exponent
218 Float.floatToIntBits(top) |
219 // Significand
220 (rand.nextInt() & mask ) ) ;
221
222 failures += testGetExponentCase(randFloat,
223 FloatConsts.MIN_EXPONENT - 1);
224 }
225 }
226 }
227
228 return failures;
229 }
230
231
232 public static int testDoubleGetExponent() {
233 int failures = 0;
234 double [] specialValues = {NaNd,
235 infinityD,
236 +0.0,
237 +1.0,
238 +2.0,
239 +16.0,
240 +Double.MIN_VALUE,
241 +Double_MAX_SUBNORMAL,
242 +DoubleConsts.MIN_NORMAL,
243 +Double.MAX_VALUE
244 };
245
246 int [] specialResults = {Double.MAX_EXPONENT + 1, // NaN results
247 Double.MAX_EXPONENT + 1, // Infinite results
248 Double.MIN_EXPONENT - 1, // Zero results
249 0,
250 1,
251 4,
252 DoubleConsts.MIN_EXPONENT - 1,
253 -DoubleConsts.MAX_EXPONENT,
254 DoubleConsts.MIN_EXPONENT,
255 DoubleConsts.MAX_EXPONENT
256 };
257
258 // Special value tests
259 for(int i = 0; i < specialValues.length; i++) {
260 failures += testGetExponentCase(specialValues[i], specialResults[i]);
261 }
262
263
264 // Normal exponent tests
265 for(int i = DoubleConsts.MIN_EXPONENT; i <= DoubleConsts.MAX_EXPONENT; i++) {
266 int result;
267
268 // Create power of two
269 double po2 = powerOfTwoD(i);
270
271 failures += testGetExponentCase(po2, i);
272
273 // Generate some random bit patterns for the significand
274 for(int j = 0; j < 10; j++) {
275 long randSignif = rand.nextLong();
276 double randFloat;
277
278 randFloat = Double.longBitsToDouble( // Exponent
279 (Double.doubleToLongBits(po2)&
280 (~DoubleConsts.SIGNIF_BIT_MASK)) |
281 // Significand
282 (randSignif &
283 DoubleConsts.SIGNIF_BIT_MASK) );
284
285 failures += testGetExponentCase(randFloat, i);
286 }
287
288 if (i > DoubleConsts.MIN_EXPONENT) {
289 double po2minus = FpUtils.nextAfter(po2,
290 Double.NEGATIVE_INFINITY);
291 failures += testGetExponentCase(po2minus, i-1);
292 }
293 }
294
295 // Subnormal exponent tests
296
297 /*
298 * Start with MIN_VALUE, left shift, test high value, low
299 * values, and random in between.
300 *
301 * Use nextAfter to calculate, high value of previous binade;
302 * loop count i will indicate how many random bits, if any are
303 * needed.
304 */
305
306 double top=Double.MIN_VALUE;
307 for( int i = 1;
308 i < DoubleConsts.SIGNIFICAND_WIDTH;
309 i++, top *= 2.0f) {
310
311 failures += testGetExponentCase(top,
312 DoubleConsts.MIN_EXPONENT - 1);
313
314 // Test largest value in next smaller binade
315 if (i >= 3) {// (i == 1) would test 0.0;
316 // (i == 2) would just retest MIN_VALUE
317 testGetExponentCase(FpUtils.nextAfter(top, 0.0),
318 DoubleConsts.MIN_EXPONENT - 1);
319
320 if( i >= 10) {
321 // create a bit mask with (i-1) 1's in the low order
322 // bits
323 long mask = ~((~0L)<<(i-1));
324 double randFloat = Double.longBitsToDouble( // Exponent
325 Double.doubleToLongBits(top) |
326 // Significand
327 (rand.nextLong() & mask ) ) ;
328
329 failures += testGetExponentCase(randFloat,
330 DoubleConsts.MIN_EXPONENT - 1);
331 }
332 }
333 }
334
335 return failures;
336 }
337
338
339 /* ******************** nextAfter tests ****************************** */
340
341 static int testNextAfterCase(float start, double direction, float expected) {
342 int failures=0;
343 float minus_start = -start;
344 double minus_direction = -direction;
345 float minus_expected = -expected;
346
347 failures+=Tests.test("Math.nextAfter(float,double)", start, direction,
348 Math.nextAfter(start, direction), expected);
349 failures+=Tests.test("Math.nextAfter(float,double)", minus_start, minus_direction,
350 Math.nextAfter(minus_start, minus_direction), minus_expected);
351
352 failures+=Tests.test("StrictMath.nextAfter(float,double)", start, direction,
353 StrictMath.nextAfter(start, direction), expected);
354 failures+=Tests.test("StrictMath.nextAfter(float,double)", minus_start, minus_direction,
355 StrictMath.nextAfter(minus_start, minus_direction), minus_expected);
356 return failures;
357 }
358
359 static int testNextAfterCase(double start, double direction, double expected) {
360 int failures=0;
361
362 double minus_start = -start;
363 double minus_direction = -direction;
364 double minus_expected = -expected;
365
366 failures+=Tests.test("Math.nextAfter(double,double)", start, direction,
367 Math.nextAfter(start, direction), expected);
368 failures+=Tests.test("Math.nextAfter(double,double)", minus_start, minus_direction,
369 Math.nextAfter(minus_start, minus_direction), minus_expected);
370
371 failures+=Tests.test("StrictMath.nextAfter(double,double)", start, direction,
372 StrictMath.nextAfter(start, direction), expected);
373 failures+=Tests.test("StrictMath.nextAfter(double,double)", minus_start, minus_direction,
374 StrictMath.nextAfter(minus_start, minus_direction), minus_expected);
375 return failures;
376 }
377
378 public static int testFloatNextAfter() {
379 int failures=0;
380
381 /*
382 * Each row of the testCases matrix represents one test case
383 * for nexAfter; given the input of the first two columns, the
384 * result in the last column is expected.
385 */
386 float [][] testCases = {
387 {NaNf, NaNf, NaNf},
388 {NaNf, 0.0f, NaNf},
389 {0.0f, NaNf, NaNf},
390 {NaNf, infinityF, NaNf},
391 {infinityF, NaNf, NaNf},
392
393 {infinityF, infinityF, infinityF},
394 {infinityF, -infinityF, Float.MAX_VALUE},
395 {infinityF, 0.0f, Float.MAX_VALUE},
396
397 {Float.MAX_VALUE, infinityF, infinityF},
398 {Float.MAX_VALUE, -infinityF, Float_MAX_VALUEmm},
399 {Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE},
400 {Float.MAX_VALUE, 0.0f, Float_MAX_VALUEmm},
401
402 {Float_MAX_VALUEmm, Float.MAX_VALUE, Float.MAX_VALUE},
403 {Float_MAX_VALUEmm, infinityF, Float.MAX_VALUE},
404 {Float_MAX_VALUEmm, Float_MAX_VALUEmm, Float_MAX_VALUEmm},
405
406 {FloatConsts.MIN_NORMAL, infinityF, FloatConsts.MIN_NORMAL+
407 Float.MIN_VALUE},
408 {FloatConsts.MIN_NORMAL, -infinityF, Float_MAX_SUBNORMAL},
409 {FloatConsts.MIN_NORMAL, 1.0f, FloatConsts.MIN_NORMAL+
410 Float.MIN_VALUE},
411 {FloatConsts.MIN_NORMAL, -1.0f, Float_MAX_SUBNORMAL},
412 {FloatConsts.MIN_NORMAL, FloatConsts.MIN_NORMAL, FloatConsts.MIN_NORMAL},
413
414 {Float_MAX_SUBNORMAL, FloatConsts.MIN_NORMAL, FloatConsts.MIN_NORMAL},
415 {Float_MAX_SUBNORMAL, Float_MAX_SUBNORMAL, Float_MAX_SUBNORMAL},
416 {Float_MAX_SUBNORMAL, 0.0f, Float_MAX_SUBNORMALmm},
417
418 {Float_MAX_SUBNORMALmm, Float_MAX_SUBNORMAL, Float_MAX_SUBNORMAL},
419 {Float_MAX_SUBNORMALmm, 0.0f, Float_MAX_SUBNORMALmm-Float.MIN_VALUE},
420 {Float_MAX_SUBNORMALmm, Float_MAX_SUBNORMALmm, Float_MAX_SUBNORMALmm},
421
422 {Float.MIN_VALUE, 0.0f, 0.0f},
423 {-Float.MIN_VALUE, 0.0f, -0.0f},
424 {Float.MIN_VALUE, Float.MIN_VALUE, Float.MIN_VALUE},
425 {Float.MIN_VALUE, 1.0f, 2*Float.MIN_VALUE},
426
427 // Make sure zero behavior is tested
428 {0.0f, 0.0f, 0.0f},
429 {0.0f, -0.0f, -0.0f},
430 {-0.0f, 0.0f, 0.0f},
431 {-0.0f, -0.0f, -0.0f},
432 {0.0f, infinityF, Float.MIN_VALUE},
433 {0.0f, -infinityF, -Float.MIN_VALUE},
434 {-0.0f, infinityF, Float.MIN_VALUE},
435 {-0.0f, -infinityF, -Float.MIN_VALUE},
436 {0.0f, Float.MIN_VALUE, Float.MIN_VALUE},
437 {0.0f, -Float.MIN_VALUE, -Float.MIN_VALUE},
438 {-0.0f, Float.MIN_VALUE, Float.MIN_VALUE},
439 {-0.0f, -Float.MIN_VALUE, -Float.MIN_VALUE}
440 };
441
442 for(int i = 0; i < testCases.length; i++) {
443 failures += testNextAfterCase(testCases[i][0], testCases[i][1],
444 testCases[i][2]);
445 }
446
447 return failures;
448 }
449
450 public static int testDoubleNextAfter() {
451 int failures =0;
452
453 /*
454 * Each row of the testCases matrix represents one test case
455 * for nexAfter; given the input of the first two columns, the
456 * result in the last column is expected.
457 */
458 double [][] testCases = {
459 {NaNd, NaNd, NaNd},
460 {NaNd, 0.0d, NaNd},
461 {0.0d, NaNd, NaNd},
462 {NaNd, infinityD, NaNd},
463 {infinityD, NaNd, NaNd},
464
465 {infinityD, infinityD, infinityD},
466 {infinityD, -infinityD, Double.MAX_VALUE},
467 {infinityD, 0.0d, Double.MAX_VALUE},
468
469 {Double.MAX_VALUE, infinityD, infinityD},
470 {Double.MAX_VALUE, -infinityD, Double_MAX_VALUEmm},
471 {Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE},
472 {Double.MAX_VALUE, 0.0d, Double_MAX_VALUEmm},
473
474 {Double_MAX_VALUEmm, Double.MAX_VALUE, Double.MAX_VALUE},
475 {Double_MAX_VALUEmm, infinityD, Double.MAX_VALUE},
476 {Double_MAX_VALUEmm, Double_MAX_VALUEmm, Double_MAX_VALUEmm},
477
478 {DoubleConsts.MIN_NORMAL, infinityD, DoubleConsts.MIN_NORMAL+
479 Double.MIN_VALUE},
480 {DoubleConsts.MIN_NORMAL, -infinityD, Double_MAX_SUBNORMAL},
481 {DoubleConsts.MIN_NORMAL, 1.0f, DoubleConsts.MIN_NORMAL+
482 Double.MIN_VALUE},
483 {DoubleConsts.MIN_NORMAL, -1.0f, Double_MAX_SUBNORMAL},
484 {DoubleConsts.MIN_NORMAL, DoubleConsts.MIN_NORMAL,DoubleConsts.MIN_NORMAL},
485
486 {Double_MAX_SUBNORMAL, DoubleConsts.MIN_NORMAL,DoubleConsts.MIN_NORMAL},
487 {Double_MAX_SUBNORMAL, Double_MAX_SUBNORMAL, Double_MAX_SUBNORMAL},
488 {Double_MAX_SUBNORMAL, 0.0d, Double_MAX_SUBNORMALmm},
489
490 {Double_MAX_SUBNORMALmm, Double_MAX_SUBNORMAL, Double_MAX_SUBNORMAL},
491 {Double_MAX_SUBNORMALmm, 0.0d, Double_MAX_SUBNORMALmm-Double.MIN_VALUE},
492 {Double_MAX_SUBNORMALmm, Double_MAX_SUBNORMALmm, Double_MAX_SUBNORMALmm},
493
494 {Double.MIN_VALUE, 0.0d, 0.0d},
495 {-Double.MIN_VALUE, 0.0d, -0.0d},
496 {Double.MIN_VALUE, Double.MIN_VALUE, Double.MIN_VALUE},
497 {Double.MIN_VALUE, 1.0f, 2*Double.MIN_VALUE},
498
499 // Make sure zero behavior is tested
500 {0.0d, 0.0d, 0.0d},
501 {0.0d, -0.0d, -0.0d},
502 {-0.0d, 0.0d, 0.0d},
503 {-0.0d, -0.0d, -0.0d},
504 {0.0d, infinityD, Double.MIN_VALUE},
505 {0.0d, -infinityD, -Double.MIN_VALUE},
506 {-0.0d, infinityD, Double.MIN_VALUE},
507 {-0.0d, -infinityD, -Double.MIN_VALUE},
508 {0.0d, Double.MIN_VALUE, Double.MIN_VALUE},
509 {0.0d, -Double.MIN_VALUE, -Double.MIN_VALUE},
510 {-0.0d, Double.MIN_VALUE, Double.MIN_VALUE},
511 {-0.0d, -Double.MIN_VALUE, -Double.MIN_VALUE}
512 };
513
514 for(int i = 0; i < testCases.length; i++) {
515 failures += testNextAfterCase(testCases[i][0], testCases[i][1],
516 testCases[i][2]);
517 }
518 return failures;
519 }
520
521 /* ******************** nextUp tests ********************************* */
522
523 public static int testFloatNextUp() {
524 int failures=0;
525
526 /*
527 * Each row of testCases represents one test case for nextUp;
528 * the first column is the input and the second column is the
529 * expected result.
530 */
531 float testCases [][] = {
532 {NaNf, NaNf},
533 {-infinityF, -Float.MAX_VALUE},
534 {-Float.MAX_VALUE, -Float_MAX_VALUEmm},
535 {-FloatConsts.MIN_NORMAL, -Float_MAX_SUBNORMAL},
536 {-Float_MAX_SUBNORMAL, -Float_MAX_SUBNORMALmm},
537 {-Float.MIN_VALUE, -0.0f},
538 {-0.0f, Float.MIN_VALUE},
539 {+0.0f, Float.MIN_VALUE},
540 {Float.MIN_VALUE, Float.MIN_VALUE*2},
541 {Float_MAX_SUBNORMALmm, Float_MAX_SUBNORMAL},
542 {Float_MAX_SUBNORMAL, FloatConsts.MIN_NORMAL},
543 {FloatConsts.MIN_NORMAL, FloatConsts.MIN_NORMAL+Float.MIN_VALUE},
544 {Float_MAX_VALUEmm, Float.MAX_VALUE},
545 {Float.MAX_VALUE, infinityF},
546 {infinityF, infinityF}
547 };
548
549 for(int i = 0; i < testCases.length; i++) {
550 failures+=Tests.test("Math.nextUp(float)",
551 testCases[i][0], Math.nextUp(testCases[i][0]), testCases[i][1]);
552
553 failures+=Tests.test("StrictMath.nextUp(float)",
554 testCases[i][0], StrictMath.nextUp(testCases[i][0]), testCases[i][1]);
555 }
556
557 return failures;
558 }
559
560
561 public static int testDoubleNextUp() {
562 int failures=0;
563
564 /*
565 * Each row of testCases represents one test case for nextUp;
566 * the first column is the input and the second column is the
567 * expected result.
568 */
569 double testCases [][] = {
570 {NaNd, NaNd},
571 {-infinityD, -Double.MAX_VALUE},
572 {-Double.MAX_VALUE, -Double_MAX_VALUEmm},
573 {-DoubleConsts.MIN_NORMAL, -Double_MAX_SUBNORMAL},
574 {-Double_MAX_SUBNORMAL, -Double_MAX_SUBNORMALmm},
575 {-Double.MIN_VALUE, -0.0d},
576 {-0.0d, Double.MIN_VALUE},
577 {+0.0d, Double.MIN_VALUE},
578 {Double.MIN_VALUE, Double.MIN_VALUE*2},
579 {Double_MAX_SUBNORMALmm, Double_MAX_SUBNORMAL},
580 {Double_MAX_SUBNORMAL, DoubleConsts.MIN_NORMAL},
581 {DoubleConsts.MIN_NORMAL, DoubleConsts.MIN_NORMAL+Double.MIN_VALUE},
582 {Double_MAX_VALUEmm, Double.MAX_VALUE},
583 {Double.MAX_VALUE, infinityD},
584 {infinityD, infinityD}
585 };
586
587 for(int i = 0; i < testCases.length; i++) {
588 failures+=Tests.test("Math.nextUp(double)",
589 testCases[i][0], Math.nextUp(testCases[i][0]), testCases[i][1]);
590
591 failures+=Tests.test("StrictMath.nextUp(double)",
592 testCases[i][0], StrictMath.nextUp(testCases[i][0]), testCases[i][1]);
593 }
594
595 return failures;
596 }
597
598 /* ******************** nextDown tests ********************************* */
599
600 public static int testFloatNextDown() {
601 int failures=0;
602
603 /*
604 * Each row of testCases represents one test case for nextDown;
605 * the first column is the input and the second column is the
606 * expected result.
607 */
608 float testCases [][] = {
609 {NaNf, NaNf},
610 {-infinityF, -infinityF},
611 {-Float.MAX_VALUE, -infinityF},
612 {-Float_MAX_VALUEmm, -Float.MAX_VALUE},
613 {-Float_MAX_SUBNORMAL, -FloatConsts.MIN_NORMAL},
614 {-Float_MAX_SUBNORMALmm, -Float_MAX_SUBNORMAL},
615 {-0.0f, -Float.MIN_VALUE},
616 {+0.0f, -Float.MIN_VALUE},
617 {Float.MIN_VALUE, 0.0f},
618 {Float.MIN_VALUE*2, Float.MIN_VALUE},
619 {Float_MAX_SUBNORMAL, Float_MAX_SUBNORMALmm},
620 {FloatConsts.MIN_NORMAL, Float_MAX_SUBNORMAL},
621 {FloatConsts.MIN_NORMAL+
622 Float.MIN_VALUE, FloatConsts.MIN_NORMAL},
623 {Float.MAX_VALUE, Float_MAX_VALUEmm},
624 {infinityF, Float.MAX_VALUE},
625 };
626
627 for(int i = 0; i < testCases.length; i++) {
628 failures+=Tests.test("FpUtils.nextDown(float)",
629 testCases[i][0], FpUtils.nextDown(testCases[i][0]), testCases[i][1]);
630 }
631
632 return failures;
633 }
634
635
636 public static int testDoubleNextDown() {
637 int failures=0;
638
639 /*
640 * Each row of testCases represents one test case for nextDown;
641 * the first column is the input and the second column is the
642 * expected result.
643 */
644 double testCases [][] = {
645 {NaNd, NaNd},
646 {-infinityD, -infinityD},
647 {-Double.MAX_VALUE, -infinityD},
648 {-Double_MAX_VALUEmm, -Double.MAX_VALUE},
649 {-Double_MAX_SUBNORMAL, -DoubleConsts.MIN_NORMAL},
650 {-Double_MAX_SUBNORMALmm, -Double_MAX_SUBNORMAL},
651 {-0.0d, -Double.MIN_VALUE},
652 {+0.0d, -Double.MIN_VALUE},
653 {Double.MIN_VALUE, 0.0d},
654 {Double.MIN_VALUE*2, Double.MIN_VALUE},
655 {Double_MAX_SUBNORMAL, Double_MAX_SUBNORMALmm},
656 {DoubleConsts.MIN_NORMAL, Double_MAX_SUBNORMAL},
657 {DoubleConsts.MIN_NORMAL+
658 Double.MIN_VALUE, DoubleConsts.MIN_NORMAL},
659 {Double.MAX_VALUE, Double_MAX_VALUEmm},
660 {infinityD, Double.MAX_VALUE},
661 };
662
663 for(int i = 0; i < testCases.length; i++) {
664 failures+=Tests.test("FpUtils.nextDown(double)",
665 testCases[i][0], FpUtils.nextDown(testCases[i][0]), testCases[i][1]);
666 }
667
668 return failures;
669 }
670
671
672 /* ********************** boolean tests ****************************** */
673
674 /*
675 * Combined tests for boolean functions, isFinite, isInfinite,
676 * isNaN, isUnordered.
677 */
678
679 public static int testFloatBooleanMethods() {
680 int failures = 0;
681
682 float testCases [] = {
683 NaNf,
684 -infinityF,
685 infinityF,
686 -Float.MAX_VALUE,
687 -3.0f,
688 -1.0f,
689 -FloatConsts.MIN_NORMAL,
690 -Float_MAX_SUBNORMALmm,
691 -Float_MAX_SUBNORMAL,
692 -Float.MIN_VALUE,
693 -0.0f,
694 +0.0f,
695 Float.MIN_VALUE,
696 Float_MAX_SUBNORMALmm,
697 Float_MAX_SUBNORMAL,
698 FloatConsts.MIN_NORMAL,
699 1.0f,
700 3.0f,
701 Float_MAX_VALUEmm,
702 Float.MAX_VALUE
703 };
704
705 for(int i = 0; i < testCases.length; i++) {
706 // isNaN
707 failures+=Tests.test("FpUtils.isNaN(float)", testCases[i],
708 FpUtils.isNaN(testCases[i]), (i ==0));
709
710 // isFinite
711 failures+=Tests.test("FpUtils.isFinite(float)", testCases[i],
712 FpUtils.isFinite(testCases[i]), (i >= 3));
713
714 // isInfinite
715 failures+=Tests.test("FpUtils.isInfinite(float)", testCases[i],
716 FpUtils.isInfinite(testCases[i]), (i==1 || i==2));
717
718 // isUnorderd
719 for(int j = 0; j < testCases.length; j++) {
720 failures+=Tests.test("FpUtils.isUnordered(float, float)", testCases[i],testCases[j],
721 FpUtils.isUnordered(testCases[i],testCases[j]), (i==0 || j==0));
722 }
723 }
724
725 return failures;
726 }
727
728 public static int testDoubleBooleanMethods() {
729 int failures = 0;
730 boolean result = false;
731
732 double testCases [] = {
733 NaNd,
734 -infinityD,
735 infinityD,
736 -Double.MAX_VALUE,
737 -3.0d,
738 -1.0d,
739 -DoubleConsts.MIN_NORMAL,
740 -Double_MAX_SUBNORMALmm,
741 -Double_MAX_SUBNORMAL,
742 -Double.MIN_VALUE,
743 -0.0d,
744 +0.0d,
745 Double.MIN_VALUE,
746 Double_MAX_SUBNORMALmm,
747 Double_MAX_SUBNORMAL,
748 DoubleConsts.MIN_NORMAL,
749 1.0d,
750 3.0d,
751 Double_MAX_VALUEmm,
752 Double.MAX_VALUE
753 };
754
755 for(int i = 0; i < testCases.length; i++) {
756 // isNaN
757 failures+=Tests.test("FpUtils.isNaN(double)", testCases[i],
758 FpUtils.isNaN(testCases[i]), (i ==0));
759
760 // isFinite
761 failures+=Tests.test("FpUtils.isFinite(double)", testCases[i],
762 FpUtils.isFinite(testCases[i]), (i >= 3));
763
764 // isInfinite
765 failures+=Tests.test("FpUtils.isInfinite(double)", testCases[i],
766 FpUtils.isInfinite(testCases[i]), (i==1 || i==2));
767
768 // isUnorderd
769 for(int j = 0; j < testCases.length; j++) {
770 failures+=Tests.test("FpUtils.isUnordered(double, double)", testCases[i],testCases[j],
771 FpUtils.isUnordered(testCases[i],testCases[j]), (i==0 || j==0));
772 }
773 }
774
775 return failures;
776 }
777
778 /* ******************** copySign tests******************************** */
779
780 public static int testFloatCopySign() {
781 int failures = 0;
782
783 // testCases[0] are logically positive numbers;
784 // testCases[1] are negative numbers.
785 float testCases [][] = {
786 {+0.0f,
787 Float.MIN_VALUE,
788 Float_MAX_SUBNORMALmm,
789 Float_MAX_SUBNORMAL,
790 FloatConsts.MIN_NORMAL,
791 1.0f,
792 3.0f,
793 Float_MAX_VALUEmm,
794 Float.MAX_VALUE,
795 infinityF,
796 },
797 {-infinityF,
798 -Float.MAX_VALUE,
799 -3.0f,
800 -1.0f,
801 -FloatConsts.MIN_NORMAL,
802 -Float_MAX_SUBNORMALmm,
803 -Float_MAX_SUBNORMAL,
804 -Float.MIN_VALUE,
805 -0.0f}
806 };
807
808 float NaNs[] = {Float.intBitsToFloat(0x7fc00000), // "positive" NaN
809 Float.intBitsToFloat(0xFfc00000)}; // "negative" NaN
810
811 // Tests shared between raw and non-raw versions
812 for(int i = 0; i < 2; i++) {
813 for(int j = 0; j < 2; j++) {
814 for(int m = 0; m < testCases[i].length; m++) {
815 for(int n = 0; n < testCases[j].length; n++) {
816 // copySign(magnitude, sign)
817 failures+=Tests.test("Math.copySign(float,float)",
818 testCases[i][m],testCases[j][n],
819 Math.copySign(testCases[i][m], testCases[j][n]),
820 (j==0?1.0f:-1.0f)*Math.abs(testCases[i][m]) );
821
822 failures+=Tests.test("StrictMath.copySign(float,float)",
823 testCases[i][m],testCases[j][n],
824 StrictMath.copySign(testCases[i][m], testCases[j][n]),
825 (j==0?1.0f:-1.0f)*Math.abs(testCases[i][m]) );
826 }
827 }
828 }
829 }
830
831 // For rawCopySign, NaN may effectively have either sign bit
832 // while for copySign NaNs are treated as if they always have
833 // a zero sign bit (i.e. as positive numbers)
834 for(int i = 0; i < 2; i++) {
835 for(int j = 0; j < NaNs.length; j++) {
836 for(int m = 0; m < testCases[i].length; m++) {
837 // copySign(magnitude, sign)
838
839 failures += (Math.abs(Math.copySign(testCases[i][m], NaNs[j])) ==
840 Math.abs(testCases[i][m])) ? 0:1;
841
842
843 failures+=Tests.test("StrictMath.copySign(float,float)",
844 testCases[i][m], NaNs[j],
845 StrictMath.copySign(testCases[i][m], NaNs[j]),
846 Math.abs(testCases[i][m]) );
847 }
848 }
849 }
850
851 return failures;
852 }
853
854 public static int testDoubleCopySign() {
855 int failures = 0;
856
857 // testCases[0] are logically positive numbers;
858 // testCases[1] are negative numbers.
859 double testCases [][] = {
860 {+0.0d,
861 Double.MIN_VALUE,
862 Double_MAX_SUBNORMALmm,
863 Double_MAX_SUBNORMAL,
864 DoubleConsts.MIN_NORMAL,
865 1.0d,
866 3.0d,
867 Double_MAX_VALUEmm,
868 Double.MAX_VALUE,
869 infinityD,
870 },
871 {-infinityD,
872 -Double.MAX_VALUE,
873 -3.0d,
874 -1.0d,
875 -DoubleConsts.MIN_NORMAL,
876 -Double_MAX_SUBNORMALmm,
877 -Double_MAX_SUBNORMAL,
878 -Double.MIN_VALUE,
879 -0.0d}
880 };
881
882 double NaNs[] = {Double.longBitsToDouble(0x7ff8000000000000L), // "positive" NaN
883 Double.longBitsToDouble(0xfff8000000000000L), // "negative" NaN
884 Double.longBitsToDouble(0x7FF0000000000001L),
885 Double.longBitsToDouble(0xFFF0000000000001L),
886 Double.longBitsToDouble(0x7FF8555555555555L),
887 Double.longBitsToDouble(0xFFF8555555555555L),
888 Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL),
889 Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL),
890 Double.longBitsToDouble(0x7FFDeadBeef00000L),
891 Double.longBitsToDouble(0xFFFDeadBeef00000L),
892 Double.longBitsToDouble(0x7FFCafeBabe00000L),
893 Double.longBitsToDouble(0xFFFCafeBabe00000L)};
894
895 // Tests shared between Math and StrictMath versions
896 for(int i = 0; i < 2; i++) {
897 for(int j = 0; j < 2; j++) {
898 for(int m = 0; m < testCases[i].length; m++) {
899 for(int n = 0; n < testCases[j].length; n++) {
900 // copySign(magnitude, sign)
901 failures+=Tests.test("MathcopySign(double,double)",
902 testCases[i][m],testCases[j][n],
903 Math.copySign(testCases[i][m], testCases[j][n]),
904 (j==0?1.0f:-1.0f)*Math.abs(testCases[i][m]) );
905
906 failures+=Tests.test("StrictMath.copySign(double,double)",
907 testCases[i][m],testCases[j][n],
908 StrictMath.copySign(testCases[i][m], testCases[j][n]),
909 (j==0?1.0f:-1.0f)*Math.abs(testCases[i][m]) );
910 }
911 }
912 }
913 }
914
915 // For Math.copySign, NaN may effectively have either sign bit
916 // while for StrictMath.copySign NaNs are treated as if they
917 // always have a zero sign bit (i.e. as positive numbers)
918 for(int i = 0; i < 2; i++) {
919 for(int j = 0; j < NaNs.length; j++) {
920 for(int m = 0; m < testCases[i].length; m++) {
921 // copySign(magnitude, sign)
922
923 failures += (Math.abs(Math.copySign(testCases[i][m], NaNs[j])) ==
924 Math.abs(testCases[i][m])) ? 0:1;
925
926
927 failures+=Tests.test("StrictMath.copySign(double,double)",
928 testCases[i][m], NaNs[j],
929 StrictMath.copySign(testCases[i][m], NaNs[j]),
930 Math.abs(testCases[i][m]) );
931 }
932 }
933 }
934
935
936 return failures;
937 }
938
939 /* ************************ scalb tests ******************************* */
940
941 static int testScalbCase(float value, int scale_factor, float expected) {
942 int failures=0;
943
944 failures+=Tests.test("Math.scalb(float,int)",
945 value, scale_factor,
946 Math.scalb(value, scale_factor), expected);
947
948 failures+=Tests.test("Math.scalb(float,int)",
949 -value, scale_factor,
950 Math.scalb(-value, scale_factor), -expected);
951
952 failures+=Tests.test("StrictMath.scalb(float,int)",
953 value, scale_factor,
954 StrictMath.scalb(value, scale_factor), expected);
955
956 failures+=Tests.test("StrictMath.scalb(float,int)",
957 -value, scale_factor,
958 StrictMath.scalb(-value, scale_factor), -expected);
959 return failures;
960 }
961
962 public static int testFloatScalb() {
963 int failures=0;
964 int MAX_SCALE = FloatConsts.MAX_EXPONENT + -FloatConsts.MIN_EXPONENT +
965 FloatConsts.SIGNIFICAND_WIDTH + 1;
966
967
968 // Arguments x, where scalb(x,n) is x for any n.
969 float [] identityTestCases = {NaNf,
970 -0.0f,
971 +0.0f,
972 infinityF,
973 -infinityF
974 };
975
976 float [] subnormalTestCases = {
977 Float.MIN_VALUE,
978 3.0f*Float.MIN_VALUE,
979 Float_MAX_SUBNORMALmm,
980 Float_MAX_SUBNORMAL
981 };
982
983 float [] someTestCases = {
984 Float.MIN_VALUE,
985 3.0f*Float.MIN_VALUE,
986 Float_MAX_SUBNORMALmm,
987 Float_MAX_SUBNORMAL,
988 FloatConsts.MIN_NORMAL,
989 1.0f,
990 2.0f,
991 3.0f,
992 (float)Math.PI,
993 Float_MAX_VALUEmm,
994 Float.MAX_VALUE
995 };
996
997 int [] oneMultiplyScalingFactors = {
998 FloatConsts.MIN_EXPONENT,
999 FloatConsts.MIN_EXPONENT+1,
1000 -3,
1001 -2,
1002 -1,
1003 0,
1004 1,
1005 2,
1006 3,
1007 FloatConsts.MAX_EXPONENT-1,
1008 FloatConsts.MAX_EXPONENT
1009 };
1010
1011 int [] manyScalingFactors = {
1012 Integer.MIN_VALUE,
1013 Integer.MIN_VALUE+1,
1014 -MAX_SCALE -1,
1015 -MAX_SCALE,
1016 -MAX_SCALE+1,
1017
1018 2*FloatConsts.MIN_EXPONENT-1, // -253
1019 2*FloatConsts.MIN_EXPONENT, // -252
1020 2*FloatConsts.MIN_EXPONENT+1, // -251
1021
1022 FpUtils.ilogb(Float.MIN_VALUE)-1, // -150
1023 FpUtils.ilogb(Float.MIN_VALUE), // -149
1024 -FloatConsts.MAX_EXPONENT, // -127
1025 FloatConsts.MIN_EXPONENT, // -126
1026
1027 -2,
1028 -1,
1029 0,
1030 1,
1031 2,
1032
1033 FloatConsts.MAX_EXPONENT-1, // 126
1034 FloatConsts.MAX_EXPONENT, // 127
1035 FloatConsts.MAX_EXPONENT+1, // 128
1036
1037 2*FloatConsts.MAX_EXPONENT-1, // 253
1038 2*FloatConsts.MAX_EXPONENT, // 254
1039 2*FloatConsts.MAX_EXPONENT+1, // 255
1040
1041 MAX_SCALE-1,
1042 MAX_SCALE,
1043 MAX_SCALE+1,
1044 Integer.MAX_VALUE-1,
1045 Integer.MAX_VALUE
1046 };
1047
1048 // Test cases where scaling is always a no-op
1049 for(int i=0; i < identityTestCases.length; i++) {
1050 for(int j=0; j < manyScalingFactors.length; j++) {
1051 failures += testScalbCase(identityTestCases[i],
1052 manyScalingFactors[j],
1053 identityTestCases[i]);
1054 }
1055 }
1056
1057 // Test cases where result is 0.0 or infinity due to magnitude
1058 // of the scaling factor
1059 for(int i=0; i < someTestCases.length; i++) {
1060 for(int j=0; j < manyScalingFactors.length; j++) {
1061 int scaleFactor = manyScalingFactors[j];
1062 if (Math.abs(scaleFactor) >= MAX_SCALE) {
1063 float value = someTestCases[i];
1064 failures+=testScalbCase(value,
1065 scaleFactor,
1066 FpUtils.copySign( (scaleFactor>0?infinityF:0.0f), value) );
1067 }
1068 }
1069 }
1070
1071 // Test cases that could be done with one floating-point
1072 // multiply.
1073 for(int i=0; i < someTestCases.length; i++) {
1074 for(int j=0; j < oneMultiplyScalingFactors.length; j++) {
1075 int scaleFactor = oneMultiplyScalingFactors[j];
1076 float value = someTestCases[i];
1077
1078 failures+=testScalbCase(value,
1079 scaleFactor,
1080 value*powerOfTwoF(scaleFactor));
1081 }
1082 }
1083
1084 // Create 2^MAX_EXPONENT
1085 float twoToTheMaxExp = 1.0f; // 2^0
1086 for(int i = 0; i < FloatConsts.MAX_EXPONENT; i++)
1087 twoToTheMaxExp *=2.0f;
1088
1089 // Scale-up subnormal values until they all overflow
1090 for(int i=0; i < subnormalTestCases.length; i++) {
1091 float scale = 1.0f; // 2^j
1092 float value = subnormalTestCases[i];
1093
1094 for(int j=FloatConsts.MAX_EXPONENT*2; j < MAX_SCALE; j++) { // MAX_SCALE -1 should cause overflow
1095 int scaleFactor = j;
1096
1097 failures+=testScalbCase(value,
1098 scaleFactor,
1099 (FpUtils.ilogb(value) +j > FloatConsts.MAX_EXPONENT ) ?
1100 FpUtils.copySign(infinityF, value) : // overflow
1101 // calculate right answer
1102 twoToTheMaxExp*(twoToTheMaxExp*(scale*value)) );
1103 scale*=2.0f;
1104 }
1105 }
1106
1107 // Scale down a large number until it underflows. By scaling
1108 // down MAX_NORMALmm, the first subnormal result will be exact
1109 // but the next one will round -- all those results can be
1110 // checked by halving a separate value in the loop. Actually,
1111 // we can keep halving and checking until the product is zero
1112 // since:
1113 //
1114 // 1. If the scalb of MAX_VALUEmm is subnormal and *not* exact
1115 // it will round *up*
1116 //
1117 // 2. When rounding first occurs in the expected product, it
1118 // too rounds up, to 2^-MAX_EXPONENT.
1119 //
1120 // Halving expected after rounding happends to give the same
1121 // result as the scalb operation.
1122 float expected = Float_MAX_VALUEmm *0.5f;
1123 for(int i = -1; i > -MAX_SCALE; i--) {
1124 failures+=testScalbCase(Float_MAX_VALUEmm, i, expected);
1125
1126 expected *= 0.5f;
1127 }
1128
1129 // Tricky rounding tests:
1130 // Scale down a large number into subnormal range such that if
1131 // scalb is being implemented with multiple floating-point
1132 // multiplies, the value would round twice if the multiplies
1133 // were done in the wrong order.
1134
1135 float value = 0x8.0000bP-5f;
1136 expected = 0x1.00001p-129f;
1137
1138 for(int i = 0; i < 129; i++) {
1139 failures+=testScalbCase(value,
1140 -127-i,
1141 expected);
1142 value *=2.0f;
1143 }
1144
1145 return failures;
1146 }
1147
1148 static int testScalbCase(double value, int scale_factor, double expected) {
1149 int failures=0;
1150
1151 failures+=Tests.test("Math.scalb(double,int)",
1152 value, scale_factor,
1153 Math.scalb(value, scale_factor), expected);
1154
1155 failures+=Tests.test("Math.scalb(double,int)",
1156 -value, scale_factor,
1157 Math.scalb(-value, scale_factor), -expected);
1158
1159 failures+=Tests.test("StrictMath.scalb(double,int)",
1160 value, scale_factor,
1161 StrictMath.scalb(value, scale_factor), expected);
1162
1163 failures+=Tests.test("StrictMath.scalb(double,int)",
1164 -value, scale_factor,
1165 StrictMath.scalb(-value, scale_factor), -expected);
1166
1167 return failures;
1168 }
1169
1170 public static int testDoubleScalb() {
1171 int failures=0;
1172 int MAX_SCALE = DoubleConsts.MAX_EXPONENT + -DoubleConsts.MIN_EXPONENT +
1173 DoubleConsts.SIGNIFICAND_WIDTH + 1;
1174
1175
1176 // Arguments x, where scalb(x,n) is x for any n.
1177 double [] identityTestCases = {NaNd,
1178 -0.0,
1179 +0.0,
1180 infinityD,
1181 };
1182
1183 double [] subnormalTestCases = {
1184 Double.MIN_VALUE,
1185 3.0d*Double.MIN_VALUE,
1186 Double_MAX_SUBNORMALmm,
1187 Double_MAX_SUBNORMAL
1188 };
1189
1190 double [] someTestCases = {
1191 Double.MIN_VALUE,
1192 3.0d*Double.MIN_VALUE,
1193 Double_MAX_SUBNORMALmm,
1194 Double_MAX_SUBNORMAL,
1195 DoubleConsts.MIN_NORMAL,
1196 1.0d,
1197 2.0d,
1198 3.0d,
1199 Math.PI,
1200 Double_MAX_VALUEmm,
1201 Double.MAX_VALUE
1202 };
1203
1204 int [] oneMultiplyScalingFactors = {
1205 DoubleConsts.MIN_EXPONENT,
1206 DoubleConsts.MIN_EXPONENT+1,
1207 -3,
1208 -2,
1209 -1,
1210 0,
1211 1,
1212 2,
1213 3,
1214 DoubleConsts.MAX_EXPONENT-1,
1215 DoubleConsts.MAX_EXPONENT
1216 };
1217
1218 int [] manyScalingFactors = {
1219 Integer.MIN_VALUE,
1220 Integer.MIN_VALUE+1,
1221 -MAX_SCALE -1,
1222 -MAX_SCALE,
1223 -MAX_SCALE+1,
1224
1225 2*DoubleConsts.MIN_EXPONENT-1, // -2045
1226 2*DoubleConsts.MIN_EXPONENT, // -2044
1227 2*DoubleConsts.MIN_EXPONENT+1, // -2043
1228
1229 FpUtils.ilogb(Double.MIN_VALUE)-1, // -1076
1230 FpUtils.ilogb(Double.MIN_VALUE), // -1075
1231 -DoubleConsts.MAX_EXPONENT, // -1023
1232 DoubleConsts.MIN_EXPONENT, // -1022
1233
1234 -2,
1235 -1,
1236 0,
1237 1,
1238 2,
1239
1240 DoubleConsts.MAX_EXPONENT-1, // 1022
1241 DoubleConsts.MAX_EXPONENT, // 1023
1242 DoubleConsts.MAX_EXPONENT+1, // 1024
1243
1244 2*DoubleConsts.MAX_EXPONENT-1, // 2045
1245 2*DoubleConsts.MAX_EXPONENT, // 2046
1246 2*DoubleConsts.MAX_EXPONENT+1, // 2047
1247
1248 MAX_SCALE-1,
1249 MAX_SCALE,
1250 MAX_SCALE+1,
1251 Integer.MAX_VALUE-1,
1252 Integer.MAX_VALUE
1253 };
1254
1255 // Test cases where scaling is always a no-op
1256 for(int i=0; i < identityTestCases.length; i++) {
1257 for(int j=0; j < manyScalingFactors.length; j++) {
1258 failures += testScalbCase(identityTestCases[i],
1259 manyScalingFactors[j],
1260 identityTestCases[i]);
1261 }
1262 }
1263
1264 // Test cases where result is 0.0 or infinity due to magnitude
1265 // of the scaling factor
1266 for(int i=0; i < someTestCases.length; i++) {
1267 for(int j=0; j < manyScalingFactors.length; j++) {
1268 int scaleFactor = manyScalingFactors[j];
1269 if (Math.abs(scaleFactor) >= MAX_SCALE) {
1270 double value = someTestCases[i];
1271 failures+=testScalbCase(value,
1272 scaleFactor,
1273 FpUtils.copySign( (scaleFactor>0?infinityD:0.0), value) );
1274 }
1275 }
1276 }
1277
1278 // Test cases that could be done with one floating-point
1279 // multiply.
1280 for(int i=0; i < someTestCases.length; i++) {
1281 for(int j=0; j < oneMultiplyScalingFactors.length; j++) {
1282 int scaleFactor = oneMultiplyScalingFactors[j];
1283 double value = someTestCases[i];
1284
1285 failures+=testScalbCase(value,
1286 scaleFactor,
1287 value*powerOfTwoD(scaleFactor));
1288 }
1289 }
1290
1291 // Create 2^MAX_EXPONENT
1292 double twoToTheMaxExp = 1.0; // 2^0
1293 for(int i = 0; i < DoubleConsts.MAX_EXPONENT; i++)
1294 twoToTheMaxExp *=2.0;
1295
1296 // Scale-up subnormal values until they all overflow
1297 for(int i=0; i < subnormalTestCases.length; i++) {
1298 double scale = 1.0; // 2^j
1299 double value = subnormalTestCases[i];
1300
1301 for(int j=DoubleConsts.MAX_EXPONENT*2; j < MAX_SCALE; j++) { // MAX_SCALE -1 should cause overflow
1302 int scaleFactor = j;
1303
1304 failures+=testScalbCase(value,
1305 scaleFactor,
1306 (FpUtils.ilogb(value) +j > DoubleConsts.MAX_EXPONENT ) ?
1307 FpUtils.copySign(infinityD, value) : // overflow
1308 // calculate right answer
1309 twoToTheMaxExp*(twoToTheMaxExp*(scale*value)) );
1310 scale*=2.0;
1311 }
1312 }
1313
1314 // Scale down a large number until it underflows. By scaling
1315 // down MAX_NORMALmm, the first subnormal result will be exact
1316 // but the next one will round -- all those results can be
1317 // checked by halving a separate value in the loop. Actually,
1318 // we can keep halving and checking until the product is zero
1319 // since:
1320 //
1321 // 1. If the scalb of MAX_VALUEmm is subnormal and *not* exact
1322 // it will round *up*
1323 //
1324 // 2. When rounding first occurs in the expected product, it
1325 // too rounds up, to 2^-MAX_EXPONENT.
1326 //
1327 // Halving expected after rounding happends to give the same
1328 // result as the scalb operation.
1329 double expected = Double_MAX_VALUEmm *0.5f;
1330 for(int i = -1; i > -MAX_SCALE; i--) {
1331 failures+=testScalbCase(Double_MAX_VALUEmm, i, expected);
1332
1333 expected *= 0.5;
1334 }
1335
1336 // Tricky rounding tests:
1337 // Scale down a large number into subnormal range such that if
1338 // scalb is being implemented with multiple floating-point
1339 // multiplies, the value would round twice if the multiplies
1340 // were done in the wrong order.
1341
1342 double value = 0x1.000000000000bP-1;
1343 expected = 0x0.2000000000001P-1022;
1344 for(int i = 0; i < DoubleConsts.MAX_EXPONENT+2; i++) {
1345 failures+=testScalbCase(value,
1346 -1024-i,
1347 expected);
1348 value *=2.0;
1349 }
1350
1351 return failures;
1352 }
1353
1354 /* ************************* ulp tests ******************************* */
1355
1356
1357 /*
1358 * Test Math.ulp and StrictMath.ulp with +d and -d.
1359 */
1360 static int testUlpCase(float f, float expected) {
1361 float minus_f = -f;
1362 int failures=0;
1363
1364 failures+=Tests.test("Math.ulp(float)", f,
1365 Math.ulp(f), expected);
1366 failures+=Tests.test("Math.ulp(float)", minus_f,
1367 Math.ulp(minus_f), expected);
1368 failures+=Tests.test("StrictMath.ulp(float)", f,
1369 StrictMath.ulp(f), expected);
1370 failures+=Tests.test("StrictMath.ulp(float)", minus_f,
1371 StrictMath.ulp(minus_f), expected);
1372 return failures;
1373 }
1374
1375 static int testUlpCase(double d, double expected) {
1376 double minus_d = -d;
1377 int failures=0;
1378
1379 failures+=Tests.test("Math.ulp(double)", d,
1380 Math.ulp(d), expected);
1381 failures+=Tests.test("Math.ulp(double)", minus_d,
1382 Math.ulp(minus_d), expected);
1383 failures+=Tests.test("StrictMath.ulp(double)", d,
1384 StrictMath.ulp(d), expected);
1385 failures+=Tests.test("StrictMath.ulp(double)", minus_d,
1386 StrictMath.ulp(minus_d), expected);
1387 return failures;
1388 }
1389
1390 public static int testFloatUlp() {
1391 int failures = 0;
1392 float [] specialValues = {NaNf,
1393 Float.POSITIVE_INFINITY,
1394 +0.0f,
1395 +1.0f,
1396 +2.0f,
1397 +16.0f,
1398 +Float.MIN_VALUE,
1399 +Float_MAX_SUBNORMAL,
1400 +FloatConsts.MIN_NORMAL,
1401 +Float.MAX_VALUE
1402 };
1403
1404 float [] specialResults = {NaNf,
1405 Float.POSITIVE_INFINITY,
1406 Float.MIN_VALUE,
1407 powerOfTwoF(-23),
1408 powerOfTwoF(-22),
1409 powerOfTwoF(-19),
1410 Float.MIN_VALUE,
1411 Float.MIN_VALUE,
1412 Float.MIN_VALUE,
1413 powerOfTwoF(104)
1414 };
1415
1416 // Special value tests
1417 for(int i = 0; i < specialValues.length; i++) {
1418 failures += testUlpCase(specialValues[i], specialResults[i]);
1419 }
1420
1421
1422 // Normal exponent tests
1423 for(int i = FloatConsts.MIN_EXPONENT; i <= FloatConsts.MAX_EXPONENT; i++) {
1424 float expected;
1425
1426 // Create power of two
1427 float po2 = powerOfTwoF(i);
1428 expected = FpUtils.scalb(1.0f, i - (FloatConsts.SIGNIFICAND_WIDTH-1));
1429
1430 failures += testUlpCase(po2, expected);
1431
1432 // Generate some random bit patterns for the significand
1433 for(int j = 0; j < 10; j++) {
1434 int randSignif = rand.nextInt();
1435 float randFloat;
1436
1437 randFloat = Float.intBitsToFloat( // Exponent
1438 (Float.floatToIntBits(po2)&
1439 (~FloatConsts.SIGNIF_BIT_MASK)) |
1440 // Significand
1441 (randSignif &
1442 FloatConsts.SIGNIF_BIT_MASK) );
1443
1444 failures += testUlpCase(randFloat, expected);
1445 }
1446
1447 if (i > FloatConsts.MIN_EXPONENT) {
1448 float po2minus = FpUtils.nextAfter(po2,
1449 Float.NEGATIVE_INFINITY);
1450 failures += testUlpCase(po2minus, expected/2.0f);
1451 }
1452 }
1453
1454 // Subnormal tests
1455
1456 /*
1457 * Start with MIN_VALUE, left shift, test high value, low
1458 * values, and random in between.
1459 *
1460 * Use nextAfter to calculate, high value of previous binade,
1461 * loop count i will indicate how many random bits, if any are
1462 * needed.
1463 */
1464
1465 float top=Float.MIN_VALUE;
1466 for( int i = 1;
1467 i < FloatConsts.SIGNIFICAND_WIDTH;
1468 i++, top *= 2.0f) {
1469
1470 failures += testUlpCase(top, Float.MIN_VALUE);
1471
1472 // Test largest value in next smaller binade
1473 if (i >= 3) {// (i == 1) would test 0.0;
1474 // (i == 2) would just retest MIN_VALUE
1475 testUlpCase(FpUtils.nextAfter(top, 0.0f),
1476 Float.MIN_VALUE);
1477
1478 if( i >= 10) {
1479 // create a bit mask with (i-1) 1's in the low order
1480 // bits
1481 int mask = ~((~0)<<(i-1));
1482 float randFloat = Float.intBitsToFloat( // Exponent
1483 Float.floatToIntBits(top) |
1484 // Significand
1485 (rand.nextInt() & mask ) ) ;
1486
1487 failures += testUlpCase(randFloat, Float.MIN_VALUE);
1488 }
1489 }
1490 }
1491
1492 return failures;
1493 }
1494
1495 public static int testDoubleUlp() {
1496 int failures = 0;
1497 double [] specialValues = {NaNd,
1498 Double.POSITIVE_INFINITY,
1499 +0.0d,
1500 +1.0d,
1501 +2.0d,
1502 +16.0d,
1503 +Double.MIN_VALUE,
1504 +Double_MAX_SUBNORMAL,
1505 +DoubleConsts.MIN_NORMAL,
1506 +Double.MAX_VALUE
1507 };
1508
1509 double [] specialResults = {NaNf,
1510 Double.POSITIVE_INFINITY,
1511 Double.MIN_VALUE,
1512 powerOfTwoD(-52),
1513 powerOfTwoD(-51),
1514 powerOfTwoD(-48),
1515 Double.MIN_VALUE,
1516 Double.MIN_VALUE,
1517 Double.MIN_VALUE,
1518 powerOfTwoD(971)
1519 };
1520
1521 // Special value tests
1522 for(int i = 0; i < specialValues.length; i++) {
1523 failures += testUlpCase(specialValues[i], specialResults[i]);
1524 }
1525
1526
1527 // Normal exponent tests
1528 for(int i = DoubleConsts.MIN_EXPONENT; i <= DoubleConsts.MAX_EXPONENT; i++) {
1529 double expected;
1530
1531 // Create power of two
1532 double po2 = powerOfTwoD(i);
1533 expected = FpUtils.scalb(1.0, i - (DoubleConsts.SIGNIFICAND_WIDTH-1));
1534
1535 failures += testUlpCase(po2, expected);
1536
1537 // Generate some random bit patterns for the significand
1538 for(int j = 0; j < 10; j++) {
1539 long randSignif = rand.nextLong();
1540 double randDouble;
1541
1542 randDouble = Double.longBitsToDouble( // Exponent
1543 (Double.doubleToLongBits(po2)&
1544 (~DoubleConsts.SIGNIF_BIT_MASK)) |
1545 // Significand
1546 (randSignif &
1547 DoubleConsts.SIGNIF_BIT_MASK) );
1548
1549 failures += testUlpCase(randDouble, expected);
1550 }
1551
1552 if (i > DoubleConsts.MIN_EXPONENT) {
1553 double po2minus = FpUtils.nextAfter(po2,
1554 Double.NEGATIVE_INFINITY);
1555 failures += testUlpCase(po2minus, expected/2.0f);
1556 }
1557 }
1558
1559 // Subnormal tests
1560
1561 /*
1562 * Start with MIN_VALUE, left shift, test high value, low
1563 * values, and random in between.
1564 *
1565 * Use nextAfter to calculate, high value of previous binade,
1566 * loop count i will indicate how many random bits, if any are
1567 * needed.
1568 */
1569
1570 double top=Double.MIN_VALUE;
1571 for( int i = 1;
1572 i < DoubleConsts.SIGNIFICAND_WIDTH;
1573 i++, top *= 2.0f) {
1574
1575 failures += testUlpCase(top, Double.MIN_VALUE);
1576
1577 // Test largest value in next smaller binade
1578 if (i >= 3) {// (i == 1) would test 0.0;
1579 // (i == 2) would just retest MIN_VALUE
1580 testUlpCase(FpUtils.nextAfter(top, 0.0f),
1581 Double.MIN_VALUE);
1582
1583 if( i >= 10) {
1584 // create a bit mask with (i-1) 1's in the low order
1585 // bits
1586 int mask = ~((~0)<<(i-1));
1587 double randDouble = Double.longBitsToDouble( // Exponent
1588 Double.doubleToLongBits(top) |
1589 // Significand
1590 (rand.nextLong() & mask ) ) ;
1591
1592 failures += testUlpCase(randDouble, Double.MIN_VALUE);
1593 }
1594 }
1595 }
1596
1597 return failures;
1598 }
1599
1600 public static int testFloatSignum() {
1601 int failures = 0;
1602 float testCases [][] = {
1603 {NaNf, NaNf},
1604 {-infinityF, -1.0f},
1605 {-Float.MAX_VALUE, -1.0f},
1606 {-FloatConsts.MIN_NORMAL, -1.0f},
1607 {-1.0f, -1.0f},
1608 {-2.0f, -1.0f},
1609 {-Float_MAX_SUBNORMAL, -1.0f},
1610 {-Float.MIN_VALUE, -1.0f},
1611 {-0.0f, -0.0f},
1612 {+0.0f, +0.0f},
1613 {Float.MIN_VALUE, 1.0f},
1614 {Float_MAX_SUBNORMALmm, 1.0f},
1615 {Float_MAX_SUBNORMAL, 1.0f},
1616 {FloatConsts.MIN_NORMAL, 1.0f},
1617 {1.0f, 1.0f},
1618 {2.0f, 1.0f},
1619 {Float_MAX_VALUEmm, 1.0f},
1620 {Float.MAX_VALUE, 1.0f},
1621 {infinityF, 1.0f}
1622 };
1623
1624 for(int i = 0; i < testCases.length; i++) {
1625 failures+=Tests.test("Math.signum(float)",
1626 testCases[i][0], Math.signum(testCases[i][0]), testCases[i][1]);
1627 failures+=Tests.test("StrictMath.signum(float)",
1628 testCases[i][0], StrictMath.signum(testCases[i][0]), testCases[i][1]);
1629 }
1630
1631 return failures;
1632 }
1633
1634 public static int testDoubleSignum() {
1635 int failures = 0;
1636 double testCases [][] = {
1637 {NaNd, NaNd},
1638 {-infinityD, -1.0},
1639 {-Double.MAX_VALUE, -1.0},
1640 {-DoubleConsts.MIN_NORMAL, -1.0},
1641 {-1.0, -1.0},
1642 {-2.0, -1.0},
1643 {-Double_MAX_SUBNORMAL, -1.0},
1644 {-Double.MIN_VALUE, -1.0d},
1645 {-0.0d, -0.0d},
1646 {+0.0d, +0.0d},
1647 {Double.MIN_VALUE, 1.0},
1648 {Double_MAX_SUBNORMALmm, 1.0},
1649 {Double_MAX_SUBNORMAL, 1.0},
1650 {DoubleConsts.MIN_NORMAL, 1.0},
1651 {1.0, 1.0},
1652 {2.0, 1.0},
1653 {Double_MAX_VALUEmm, 1.0},
1654 {Double.MAX_VALUE, 1.0},
1655 {infinityD, 1.0}
1656 };
1657
1658 for(int i = 0; i < testCases.length; i++) {
1659 failures+=Tests.test("Math.signum(double)",
1660 testCases[i][0], Math.signum(testCases[i][0]), testCases[i][1]);
1661 failures+=Tests.test("StrictMath.signum(double)",
1662 testCases[i][0], StrictMath.signum(testCases[i][0]), testCases[i][1]);
1663 }
1664
1665 return failures;
1666 }
1667
1668
1669 public static void main(String argv[]) {
1670 int failures = 0;
1671
1672 failures += testFloatGetExponent();
1673 failures += testDoubleGetExponent();
1674
1675 failures += testFloatNextAfter();
1676 failures += testDoubleNextAfter();
1677
1678 failures += testFloatNextUp();
1679 failures += testDoubleNextUp();
1680
1681 failures += testFloatNextDown();
1682 failures += testDoubleNextDown();
1683
1684 failures += testFloatBooleanMethods();
1685 failures += testDoubleBooleanMethods();
1686
1687 failures += testFloatCopySign();
1688 failures += testDoubleCopySign();
1689
1690 failures += testFloatScalb();
1691 failures += testDoubleScalb();
1692
1693 failures += testFloatUlp();
1694 failures += testDoubleUlp();
1695
1696 failures += testFloatSignum();
1697 failures += testDoubleSignum();
1698
1699 if (failures > 0) {
1700 System.err.println("Testing the recommended functions incurred "
1701 + failures + " failures.");
1702 throw new RuntimeException();
1703 }
1704 }
1705}