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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /*
25 * Shared static test methods for numerical tests. Sharing these
26 * helper test methods avoids repeated functions in the various test
27 * programs. The test methods return 1 for a test failure and 0 for
28 * success. The order of arguments to the test methods is generally
29 * the test name, followed by the test arguments, the computed result,
30 * and finally the expected result.
31 */
32
33 import sun.misc.FpUtils;
34
35 public class Tests {
36 private Tests(){}; // do not instantiate
37
38 public static String toHexString(float f) {
39 if (!Float.isNaN(f))
40 return Float.toHexString(f);
41 else
42 return "NaN(0x" + Integer.toHexString(Float.floatToRawIntBits(f)) + ")";
43 }
44
45 public static String toHexString(double d) {
46 if (!Double.isNaN(d))
47 return Double.toHexString(d);
48 else
49 return "NaN(0x" + Long.toHexString(Double.doubleToRawLongBits(d)) + ")";
50 }
51
52 /**
53 * Return the floating-point value next larger in magnitude.
54 */
55 public static double nextOut(double d) {
56 if (d > 0.0)
57 return Math.nextUp(d);
58 else
59 return -Math.nextUp(-d);
60 }
61
62 public static int test(String testName, float input,
63 boolean result, boolean expected) {
64 if (expected != result) {
65 System.err.println("Failure for " + testName + ":\n" +
66 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" +
67 "\texpected " + expected + "\n" +
68 "\tgot " + result + ").");
69 return 1;
70 }
71 else
72 return 0;
73 }
74
75 public static int test(String testName, double input,
76 boolean result, boolean expected) {
77 if (expected != result) {
78 System.err.println("Failure for " + testName + ":\n" +
79 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" +
80 "\texpected " + expected + "\n" +
81 "\tgot " + result + ").");
220 return 1;
221 }
222 else
223 return 0;
224 }
225
226 static int testUlpCore(double result, double expected, double ulps) {
227 // We assume we won't be unlucky and have an inexact expected
228 // be nextDown(2^i) when 2^i would be the correctly rounded
229 // answer. This would cause the ulp size to be half as large
230 // as it should be, doubling the measured error).
231
232 if (Double.compare(expected, result) == 0) {
233 return 0; // result and expected are equivalent
234 } else {
235 if( ulps == 0.0) {
236 // Equivalent results required but not found
237 return 1;
238 } else {
239 double difference = expected - result;
240 if (FpUtils.isUnordered(expected, result) ||
241 Double.isNaN(difference) ||
242 // fail if greater than or unordered
243 !(Math.abs( difference/Math.ulp(expected) ) <= Math.abs(ulps)) ) {
244 return 1;
245 }
246 else
247 return 0;
248 }
249 }
250 }
251
252 // One input argument.
253 public static int testUlpDiff(String testName, double input,
254 double result, double expected, double ulps) {
255 int code = testUlpCore(result, expected, ulps);
256 if (code == 1) {
257 System.err.println("Failure for " + testName + ":\n" +
258 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" +
259 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" +
260 "\tgot " + result + "\t(" + toHexString(result) + ");\n" +
315 code = 1;
316 } else
317 code = testUlpCore(result, expected, ulps);
318
319 if (code == 1) {
320 System.err.println("Failure for " + testName +
321 ":\n" +
322 "\tFor input " + input + "\t(" + toHexString(input) + ")" +
323 "\n\texpected " + expected + "\t(" + toHexString(expected) + ")" +
324 "\n\tgot " + result + "\t(" + toHexString(result) + ");" +
325 "\ndifference greater than ulp tolerance " + ulps +
326 " or result not greater than or equal to the bound " + lowerBound);
327 }
328 return code;
329 }
330
331 public static int testTolerance(String testName, double input,
332 double result, double expected, double tolerance) {
333 if (Double.compare(expected, result ) != 0) {
334 double difference = expected - result;
335 if (FpUtils.isUnordered(expected, result) ||
336 Double.isNaN(difference) ||
337 // fail if greater than or unordered
338 !(Math.abs((difference)/expected) <= StrictMath.pow(10, -tolerance)) ) {
339 System.err.println("Failure for " + testName + ":\n" +
340 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" +
341 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" +
342 "\tgot " + result + "\t(" + toHexString(result) + ");\n" +
343 "\tdifference greater than tolerance 10^-" + tolerance);
344 return 1;
345 }
346 return 0;
347 }
348 else
349 return 0;
350 }
351
352 // For a successful test, the result must be within the upper and
353 // lower bounds.
354 public static int testBounds(String testName, double input, double result,
355 double bound1, double bound2) {
|
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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /*
25 * Shared static test methods for numerical tests. Sharing these
26 * helper test methods avoids repeated functions in the various test
27 * programs. The test methods return 1 for a test failure and 0 for
28 * success. The order of arguments to the test methods is generally
29 * the test name, followed by the test arguments, the computed result,
30 * and finally the expected result.
31 */
32
33 import sun.misc.FloatConsts;
34 import sun.misc.DoubleConsts;
35
36 public class Tests {
37 private Tests(){}; // do not instantiate
38
39 public static String toHexString(float f) {
40 if (!Float.isNaN(f))
41 return Float.toHexString(f);
42 else
43 return "NaN(0x" + Integer.toHexString(Float.floatToRawIntBits(f)) + ")";
44 }
45
46 public static String toHexString(double d) {
47 if (!Double.isNaN(d))
48 return Double.toHexString(d);
49 else
50 return "NaN(0x" + Long.toHexString(Double.doubleToRawLongBits(d)) + ")";
51 }
52
53 /**
54 * Return the floating-point value next larger in magnitude.
55 */
56 public static double nextOut(double d) {
57 if (d > 0.0)
58 return Math.nextUp(d);
59 else
60 return -Math.nextUp(-d);
61 }
62
63 /**
64 * Returns unbiased exponent of a {@code float}; for
65 * subnormal values, the number is treated as if it were
66 * normalized. That is for all finite, non-zero, positive numbers
67 * <i>x</i>, <code>scalb(<i>x</i>, -ilogb(<i>x</i>))</code> is
68 * always in the range [1, 2).
69 * <p>
70 * Special cases:
71 * <ul>
72 * <li> If the argument is NaN, then the result is 2<sup>30</sup>.
73 * <li> If the argument is infinite, then the result is 2<sup>28</sup>.
74 * <li> If the argument is zero, then the result is -(2<sup>28</sup>).
75 * </ul>
76 *
77 * @param f floating-point number whose exponent is to be extracted
78 * @return unbiased exponent of the argument.
79 */
80 public static int ilogb(double d) {
81 int exponent = Math.getExponent(d);
82
83 switch (exponent) {
84 case DoubleConsts.MAX_EXPONENT+1: // NaN or infinity
85 if( Double.isNaN(d) )
86 return (1<<30); // 2^30
87 else // infinite value
88 return (1<<28); // 2^28
89
90 case DoubleConsts.MIN_EXPONENT-1: // zero or subnormal
91 if(d == 0.0) {
92 return -(1<<28); // -(2^28)
93 }
94 else {
95 long transducer = Double.doubleToRawLongBits(d);
96
97 /*
98 * To avoid causing slow arithmetic on subnormals,
99 * the scaling to determine when d's significand
100 * is normalized is done in integer arithmetic.
101 * (there must be at least one "1" bit in the
102 * significand since zero has been screened out.
103 */
104
105 // isolate significand bits
106 transducer &= DoubleConsts.SIGNIF_BIT_MASK;
107 assert(transducer != 0L);
108
109 // This loop is simple and functional. We might be
110 // able to do something more clever that was faster;
111 // e.g. number of leading zero detection on
112 // (transducer << (# exponent and sign bits).
113 while (transducer <
114 (1L << (DoubleConsts.SIGNIFICAND_WIDTH - 1))) {
115 transducer *= 2;
116 exponent--;
117 }
118 exponent++;
119 assert( exponent >=
120 DoubleConsts.MIN_EXPONENT - (DoubleConsts.SIGNIFICAND_WIDTH-1) &&
121 exponent < DoubleConsts.MIN_EXPONENT);
122 return exponent;
123 }
124
125 default:
126 assert( exponent >= DoubleConsts.MIN_EXPONENT &&
127 exponent <= DoubleConsts.MAX_EXPONENT);
128 return exponent;
129 }
130 }
131
132 /**
133 * Returns unbiased exponent of a {@code float}; for
134 * subnormal values, the number is treated as if it were
135 * normalized. That is for all finite, non-zero, positive numbers
136 * <i>x</i>, <code>scalb(<i>x</i>, -ilogb(<i>x</i>))</code> is
137 * always in the range [1, 2).
138 * <p>
139 * Special cases:
140 * <ul>
141 * <li> If the argument is NaN, then the result is 2<sup>30</sup>.
142 * <li> If the argument is infinite, then the result is 2<sup>28</sup>.
143 * <li> If the argument is zero, then the result is -(2<sup>28</sup>).
144 * </ul>
145 *
146 * @param f floating-point number whose exponent is to be extracted
147 * @return unbiased exponent of the argument.
148 */
149 public static int ilogb(float f) {
150 int exponent = Math.getExponent(f);
151
152 switch (exponent) {
153 case FloatConsts.MAX_EXPONENT+1: // NaN or infinity
154 if( Float.isNaN(f) )
155 return (1<<30); // 2^30
156 else // infinite value
157 return (1<<28); // 2^28
158
159 case FloatConsts.MIN_EXPONENT-1: // zero or subnormal
160 if(f == 0.0f) {
161 return -(1<<28); // -(2^28)
162 }
163 else {
164 int transducer = Float.floatToRawIntBits(f);
165
166 /*
167 * To avoid causing slow arithmetic on subnormals,
168 * the scaling to determine when f's significand
169 * is normalized is done in integer arithmetic.
170 * (there must be at least one "1" bit in the
171 * significand since zero has been screened out.
172 */
173
174 // isolate significand bits
175 transducer &= FloatConsts.SIGNIF_BIT_MASK;
176 assert(transducer != 0);
177
178 // This loop is simple and functional. We might be
179 // able to do something more clever that was faster;
180 // e.g. number of leading zero detection on
181 // (transducer << (# exponent and sign bits).
182 while (transducer <
183 (1 << (FloatConsts.SIGNIFICAND_WIDTH - 1))) {
184 transducer *= 2;
185 exponent--;
186 }
187 exponent++;
188 assert( exponent >=
189 FloatConsts.MIN_EXPONENT - (FloatConsts.SIGNIFICAND_WIDTH-1) &&
190 exponent < FloatConsts.MIN_EXPONENT);
191 return exponent;
192 }
193
194 default:
195 assert( exponent >= FloatConsts.MIN_EXPONENT &&
196 exponent <= FloatConsts.MAX_EXPONENT);
197 return exponent;
198 }
199 }
200
201 /**
202 * Returns {@code true} if the unordered relation holds
203 * between the two arguments. When two floating-point values are
204 * unordered, one value is neither less than, equal to, nor
205 * greater than the other. For the unordered relation to be true,
206 * at least one argument must be a {@code NaN}.
207 *
208 * @param arg1 the first argument
209 * @param arg2 the second argument
210 * @return {@code true} if at least one argument is a NaN,
211 * {@code false} otherwise.
212 */
213 public static boolean isUnordered(float arg1, float arg2) {
214 return Float.isNaN(arg1) || Float.isNaN(arg2);
215 }
216
217 /**
218 * Returns {@code true} if the unordered relation holds
219 * between the two arguments. When two floating-point values are
220 * unordered, one value is neither less than, equal to, nor
221 * greater than the other. For the unordered relation to be true,
222 * at least one argument must be a {@code NaN}.
223 *
224 * @param arg1 the first argument
225 * @param arg2 the second argument
226 * @return {@code true} if at least one argument is a NaN,
227 * {@code false} otherwise.
228 */
229 public static boolean isUnordered(double arg1, double arg2) {
230 return Double.isNaN(arg1) || Double.isNaN(arg2);
231 }
232
233 public static int test(String testName, float input,
234 boolean result, boolean expected) {
235 if (expected != result) {
236 System.err.println("Failure for " + testName + ":\n" +
237 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" +
238 "\texpected " + expected + "\n" +
239 "\tgot " + result + ").");
240 return 1;
241 }
242 else
243 return 0;
244 }
245
246 public static int test(String testName, double input,
247 boolean result, boolean expected) {
248 if (expected != result) {
249 System.err.println("Failure for " + testName + ":\n" +
250 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" +
251 "\texpected " + expected + "\n" +
252 "\tgot " + result + ").");
391 return 1;
392 }
393 else
394 return 0;
395 }
396
397 static int testUlpCore(double result, double expected, double ulps) {
398 // We assume we won't be unlucky and have an inexact expected
399 // be nextDown(2^i) when 2^i would be the correctly rounded
400 // answer. This would cause the ulp size to be half as large
401 // as it should be, doubling the measured error).
402
403 if (Double.compare(expected, result) == 0) {
404 return 0; // result and expected are equivalent
405 } else {
406 if( ulps == 0.0) {
407 // Equivalent results required but not found
408 return 1;
409 } else {
410 double difference = expected - result;
411 if (isUnordered(expected, result) ||
412 Double.isNaN(difference) ||
413 // fail if greater than or unordered
414 !(Math.abs( difference/Math.ulp(expected) ) <= Math.abs(ulps)) ) {
415 return 1;
416 }
417 else
418 return 0;
419 }
420 }
421 }
422
423 // One input argument.
424 public static int testUlpDiff(String testName, double input,
425 double result, double expected, double ulps) {
426 int code = testUlpCore(result, expected, ulps);
427 if (code == 1) {
428 System.err.println("Failure for " + testName + ":\n" +
429 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" +
430 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" +
431 "\tgot " + result + "\t(" + toHexString(result) + ");\n" +
486 code = 1;
487 } else
488 code = testUlpCore(result, expected, ulps);
489
490 if (code == 1) {
491 System.err.println("Failure for " + testName +
492 ":\n" +
493 "\tFor input " + input + "\t(" + toHexString(input) + ")" +
494 "\n\texpected " + expected + "\t(" + toHexString(expected) + ")" +
495 "\n\tgot " + result + "\t(" + toHexString(result) + ");" +
496 "\ndifference greater than ulp tolerance " + ulps +
497 " or result not greater than or equal to the bound " + lowerBound);
498 }
499 return code;
500 }
501
502 public static int testTolerance(String testName, double input,
503 double result, double expected, double tolerance) {
504 if (Double.compare(expected, result ) != 0) {
505 double difference = expected - result;
506 if (isUnordered(expected, result) ||
507 Double.isNaN(difference) ||
508 // fail if greater than or unordered
509 !(Math.abs((difference)/expected) <= StrictMath.pow(10, -tolerance)) ) {
510 System.err.println("Failure for " + testName + ":\n" +
511 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" +
512 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" +
513 "\tgot " + result + "\t(" + toHexString(result) + ");\n" +
514 "\tdifference greater than tolerance 10^-" + tolerance);
515 return 1;
516 }
517 return 0;
518 }
519 else
520 return 0;
521 }
522
523 // For a successful test, the result must be within the upper and
524 // lower bounds.
525 public static int testBounds(String testName, double input, double result,
526 double bound1, double bound2) {
|