blob: 587b7b2d2509b0f3e49f7d8b9cc1d4cfa96d42f6 [file] [log] [blame]
darcy32db4492009-01-26 19:49:26 -08001/*
2 * Copyright 2003 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 4851638 4939441
27 * @summary Tests for {Math, StrictMath}.hypot
28 * @author Joseph D. Darcy
29 */
30
31import sun.misc.DoubleConsts;
32import sun.misc.FpUtils;
33
34public class HypotTests {
35 private HypotTests(){}
36
37 static final double infinityD = Double.POSITIVE_INFINITY;
38 static final double NaNd = Double.NaN;
39
40 /**
41 * Given integers m and n, assuming m < n, the triple (n^2 - m^2,
42 * 2mn, and n^2 + m^2) is a Pythagorean triple with a^2 + b^2 =
43 * c^2. This methods returns a long array holding the Pythagorean
44 * triple corresponding to the inputs.
45 */
46 static long [] pythagoreanTriple(int m, int n) {
47 long M = m;
48 long N = n;
49 long result[] = new long[3];
50
51
52 result[0] = Math.abs(M*M - N*N);
53 result[1] = Math.abs(2*M*N);
54 result[2] = Math.abs(M*M + N*N);
55
56 return result;
57 }
58
59 static int testHypot() {
60 int failures = 0;
61
62 double [][] testCases = {
63 // Special cases
64 {infinityD, infinityD, infinityD},
65 {infinityD, 0.0, infinityD},
66 {infinityD, 1.0, infinityD},
67 {infinityD, NaNd, infinityD},
68 {NaNd, NaNd, NaNd},
69 {0.0, NaNd, NaNd},
70 {1.0, NaNd, NaNd},
71 {Double.longBitsToDouble(0x7FF0000000000001L), 1.0, NaNd},
72 {Double.longBitsToDouble(0xFFF0000000000001L), 1.0, NaNd},
73 {Double.longBitsToDouble(0x7FF8555555555555L), 1.0, NaNd},
74 {Double.longBitsToDouble(0xFFF8555555555555L), 1.0, NaNd},
75 {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), 1.0, NaNd},
76 {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), 1.0, NaNd},
77 {Double.longBitsToDouble(0x7FFDeadBeef00000L), 1.0, NaNd},
78 {Double.longBitsToDouble(0xFFFDeadBeef00000L), 1.0, NaNd},
79 {Double.longBitsToDouble(0x7FFCafeBabe00000L), 1.0, NaNd},
80 {Double.longBitsToDouble(0xFFFCafeBabe00000L), 1.0, NaNd},
81 };
82
83 for(int i = 0; i < testCases.length; i++) {
84 failures += testHypotCase(testCases[i][0], testCases[i][1],
85 testCases[i][2]);
86 }
87
88 // Verify hypot(x, 0.0) is close to x over the entire exponent
89 // range.
90 for(int i = DoubleConsts.MIN_SUB_EXPONENT;
91 i <= DoubleConsts.MAX_EXPONENT;
92 i++) {
93 double input = FpUtils.scalb(2, i);
94 failures += testHypotCase(input, 0.0, input);
95 }
96
97
98 // Test Pythagorean triples
99
100 // Small ones
101 for(int m = 1; m < 10; m++) {
102 for(int n = m+1; n < 11; n++) {
103 long [] result = pythagoreanTriple(m, n);
104 failures += testHypotCase(result[0], result[1], result[2]);
105 }
106 }
107
108 // Big ones
109 for(int m = 100000; m < 100100; m++) {
110 for(int n = m+100000; n < 200200; n++) {
111 long [] result = pythagoreanTriple(m, n);
112 failures += testHypotCase(result[0], result[1], result[2]);
113 }
114 }
115
116 // Approaching overflow tests
117
118 /*
119 * Create a random value r with an large-ish exponent. The
120 * result of hypot(3*r, 4*r) should be approximately 5*r. (The
121 * computation of 4*r is exact since it just changes the
122 * exponent). While the exponent of r is less than or equal
123 * to (MAX_EXPONENT - 3), the computation should not overflow.
124 */
125 java.util.Random rand = new java.util.Random();
126 for(int i = 0; i < 1000; i++) {
127 double d = rand.nextDouble();
128 // Scale d to have an exponent equal to MAX_EXPONENT -15
129 d = FpUtils.scalb(d, DoubleConsts.MAX_EXPONENT
130 -15 - FpUtils.ilogb(d));
131 for(int j = 0; j <= 13; j += 1) {
132 failures += testHypotCase(3*d, 4*d, 5*d, 2.5);
133 d *= 2.0; // increase exponent by 1
134 }
135 }
136
137 // Test for monotonicity failures. Fix one argument and test
138 // two numbers before and two numbers after each chosen value;
139 // i.e.
140 //
141 // pcNeighbors[] =
142 // {nextDown(nextDown(pc)),
143 // nextDown(pc),
144 // pc,
145 // nextUp(pc),
146 // nextUp(nextUp(pc))}
147 //
148 // and we test that hypot(pcNeighbors[i]) <= hypot(pcNeighbors[i+1])
149 {
150 double pcNeighbors[] = new double[5];
151 double pcNeighborsHypot[] = new double[5];
152 double pcNeighborsStrictHypot[] = new double[5];
153
154
155 for(int i = -18; i <= 18; i++) {
156 double pc = FpUtils.scalb(1.0, i);
157
158 pcNeighbors[2] = pc;
159 pcNeighbors[1] = FpUtils.nextDown(pc);
160 pcNeighbors[0] = FpUtils.nextDown(pcNeighbors[1]);
161 pcNeighbors[3] = FpUtils.nextUp(pc);
162 pcNeighbors[4] = FpUtils.nextUp(pcNeighbors[3]);
163
164 for(int j = 0; j < pcNeighbors.length; j++) {
165 pcNeighborsHypot[j] = Math.hypot(2.0, pcNeighbors[j]);
166 pcNeighborsStrictHypot[j] = StrictMath.hypot(2.0, pcNeighbors[j]);
167 }
168
169 for(int j = 0; j < pcNeighborsHypot.length-1; j++) {
170 if(pcNeighborsHypot[j] > pcNeighborsHypot[j+1] ) {
171 failures++;
172 System.err.println("Monotonicity failure for Math.hypot on " +
173 pcNeighbors[j] + " and " +
174 pcNeighbors[j+1] + "\n\treturned " +
175 pcNeighborsHypot[j] + " and " +
176 pcNeighborsHypot[j+1] );
177 }
178
179 if(pcNeighborsStrictHypot[j] > pcNeighborsStrictHypot[j+1] ) {
180 failures++;
181 System.err.println("Monotonicity failure for StrictMath.hypot on " +
182 pcNeighbors[j] + " and " +
183 pcNeighbors[j+1] + "\n\treturned " +
184 pcNeighborsStrictHypot[j] + " and " +
185 pcNeighborsStrictHypot[j+1] );
186 }
187
188
189 }
190
191 }
192 }
193
194
195 return failures;
196 }
197
198 static int testHypotCase(double input1, double input2, double expected) {
199 return testHypotCase(input1,input2, expected, 1);
200 }
201
202 static int testHypotCase(double input1, double input2, double expected,
203 double ulps) {
204 int failures = 0;
205 if (expected < 0.0) {
206 throw new AssertionError("Result of hypot must be greater than " +
207 "or equal to zero");
208 }
209
210 // Test Math and StrictMath methods with no inputs negated,
211 // each input negated singly, and both inputs negated. Also
212 // test inputs in reversed order.
213
214 for(int i = -1; i <= 1; i+=2) {
215 for(int j = -1; j <= 1; j+=2) {
216 double x = i * input1;
217 double y = j * input2;
218 failures += Tests.testUlpDiff("Math.hypot", x, y,
219 Math.hypot(x, y), expected, ulps);
220 failures += Tests.testUlpDiff("Math.hypot", y, x,
221 Math.hypot(y, x ), expected, ulps);
222
223 failures += Tests.testUlpDiff("StrictMath.hypot", x, y,
224 StrictMath.hypot(x, y), expected, ulps);
225 failures += Tests.testUlpDiff("StrictMath.hypot", y, x,
226 StrictMath.hypot(y, x), expected, ulps);
227 }
228 }
229
230 return failures;
231 }
232
233 public static void main(String argv[]) {
234 int failures = 0;
235
236 failures += testHypot();
237
238 if (failures > 0) {
239 System.err.println("Testing the hypot incurred "
240 + failures + " failures.");
241 throw new RuntimeException();
242 }
243 }
244
245}