1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.hipparchus.util;
23
24 import org.hipparchus.UnitTestUtils;
25 import org.hipparchus.dfp.Dfp;
26 import org.hipparchus.dfp.DfpField;
27 import org.hipparchus.dfp.DfpMath;
28 import org.hipparchus.exception.LocalizedCoreFormats;
29 import org.hipparchus.exception.MathRuntimeException;
30 import org.hipparchus.random.MersenneTwister;
31 import org.hipparchus.random.RandomGenerator;
32 import org.hipparchus.random.Well1024a;
33 import org.hipparchus.random.Well19937a;
34 import org.junit.jupiter.api.BeforeEach;
35 import org.junit.jupiter.api.Test;
36 import org.junit.jupiter.api.Timeout;
37
38 import java.lang.reflect.Method;
39 import java.lang.reflect.Modifier;
40 import java.lang.reflect.Type;
41 import java.math.BigDecimal;
42 import java.math.BigInteger;
43 import java.math.RoundingMode;
44 import java.util.concurrent.TimeUnit;
45
46 import static org.junit.jupiter.api.Assertions.assertEquals;
47 import static org.junit.jupiter.api.Assertions.assertThrows;
48 import static org.junit.jupiter.api.Assertions.assertTrue;
49 import static org.junit.jupiter.api.Assertions.fail;
50
51 class FastMathTest {
52
53 private static final double MAX_ERROR_ULP = 0.51;
54 private static final int NUMBER_OF_TRIALS = 1000;
55
56 private DfpField field;
57 private RandomGenerator generator;
58
59 @BeforeEach
60 void setUp() {
61 field = new DfpField(40);
62 generator = new MersenneTwister(6176597458463500194L);
63 }
64
65 @Test
66 void testMinMaxDouble() {
67 double[][] pairs = {
68 { -50.0, 50.0 },
69 { Double.POSITIVE_INFINITY, 1.0 },
70 { Double.NEGATIVE_INFINITY, 1.0 },
71 { Double.NaN, 1.0 },
72 { Double.POSITIVE_INFINITY, 0.0 },
73 { Double.NEGATIVE_INFINITY, 0.0 },
74 { Double.NaN, 0.0 },
75 { Double.NaN, Double.NEGATIVE_INFINITY },
76 { Double.NaN, Double.POSITIVE_INFINITY },
77 { Precision.SAFE_MIN, Precision.EPSILON }
78 };
79 for (double[] pair : pairs) {
80 assertEquals(Math.min(pair[0], pair[1]),
81 FastMath.min(pair[0], pair[1]),
82 Precision.EPSILON,
83 "min(" + pair[0] + ", " + pair[1] + ")");
84 assertEquals(Math.min(pair[1], pair[0]),
85 FastMath.min(pair[1], pair[0]),
86 Precision.EPSILON,
87 "min(" + pair[1] + ", " + pair[0] + ")");
88 assertEquals(Math.max(pair[0], pair[1]),
89 FastMath.max(pair[0], pair[1]),
90 Precision.EPSILON,
91 "max(" + pair[0] + ", " + pair[1] + ")");
92 assertEquals(Math.max(pair[1], pair[0]),
93 FastMath.max(pair[1], pair[0]),
94 Precision.EPSILON,
95 "max(" + pair[1] + ", " + pair[0] + ")");
96 }
97 }
98
99 @Test
100 void testMinMaxField() {
101 double[][] pairs = {
102 { -50.0, 50.0 },
103 { Double.POSITIVE_INFINITY, 1.0 },
104 { Double.NEGATIVE_INFINITY, 1.0 },
105 { Double.NaN, 1.0 },
106 { Double.POSITIVE_INFINITY, 0.0 },
107 { Double.NEGATIVE_INFINITY, 0.0 },
108 { Double.NaN, 0.0 },
109 { Double.NaN, Double.NEGATIVE_INFINITY },
110 { Double.NaN, Double.POSITIVE_INFINITY },
111 { Precision.SAFE_MIN, Precision.EPSILON }
112 };
113 for (double[] pair : pairs) {
114 assertEquals(Math.min(pair[0], pair[1]),
115 FastMath.min(new Binary64(pair[0]), new Binary64(pair[1])).getReal(),
116 Precision.EPSILON,
117 "min(" + pair[0] + ", " + pair[1] + ")");
118 assertEquals(Math.min(pair[1], pair[0]),
119 FastMath.min(new Binary64(pair[0]), new Binary64(pair[1])).getReal(),
120 Precision.EPSILON,
121 "min(" + pair[1] + ", " + pair[0] + ")");
122 assertEquals(Math.max(pair[0], pair[1]),
123 FastMath.max(new Binary64(pair[0]), new Binary64(pair[1])).getReal(),
124 Precision.EPSILON,
125 "max(" + pair[0] + ", " + pair[1] + ")");
126 assertEquals(Math.max(pair[1], pair[0]),
127 FastMath.max(new Binary64(pair[0]), new Binary64(pair[1])).getReal(),
128 Precision.EPSILON,
129 "max(" + pair[1] + ", " + pair[0] + ")");
130 }
131 }
132
133 @Test
134 void testMinMaxFloat() {
135 float[][] pairs = {
136 { -50.0f, 50.0f },
137 { Float.POSITIVE_INFINITY, 1.0f },
138 { Float.NEGATIVE_INFINITY, 1.0f },
139 { Float.NaN, 1.0f },
140 { Float.POSITIVE_INFINITY, 0.0f },
141 { Float.NEGATIVE_INFINITY, 0.0f },
142 { Float.NaN, 0.0f },
143 { Float.NaN, Float.NEGATIVE_INFINITY },
144 { Float.NaN, Float.POSITIVE_INFINITY }
145 };
146 for (float[] pair : pairs) {
147 assertEquals(Math.min(pair[0], pair[1]),
148 FastMath.min(pair[0], pair[1]),
149 Precision.EPSILON,
150 "min(" + pair[0] + ", " + pair[1] + ")");
151 assertEquals(Math.min(pair[1], pair[0]),
152 FastMath.min(pair[1], pair[0]),
153 Precision.EPSILON,
154 "min(" + pair[1] + ", " + pair[0] + ")");
155 assertEquals(Math.max(pair[0], pair[1]),
156 FastMath.max(pair[0], pair[1]),
157 Precision.EPSILON,
158 "max(" + pair[0] + ", " + pair[1] + ")");
159 assertEquals(Math.max(pair[1], pair[0]),
160 FastMath.max(pair[1], pair[0]),
161 Precision.EPSILON,
162 "max(" + pair[1] + ", " + pair[0] + ")");
163 }
164 }
165
166 @Test
167 void testConstants() {
168 assertEquals(Math.PI, FastMath.PI, 1.0e-20);
169 assertEquals(Math.E, FastMath.E, 1.0e-20);
170 }
171
172 @Test
173 void testAtan2() {
174 double y1 = 1.2713504628280707e10;
175 double x1 = -5.674940885228782e-10;
176 assertEquals(Math.atan2(y1, x1), FastMath.atan2(y1, x1), 2 * Precision.EPSILON);
177 double y2 = 0.0;
178 double x2P = Double.POSITIVE_INFINITY;
179 assertEquals(Math.atan2(y2, x2P), FastMath.atan2(y2, x2P), Precision.SAFE_MIN);
180 double x2M = Double.NEGATIVE_INFINITY;
181 assertEquals(Math.atan2(y2, x2M), FastMath.atan2(y2, x2M), Precision.SAFE_MIN);
182 assertEquals(+0.5 * FastMath.PI, FastMath.atan2(+1e20, +Precision.SAFE_MIN), Precision.SAFE_MIN);
183 assertEquals(+0.5 * FastMath.PI, FastMath.atan2(+1e20, -Precision.SAFE_MIN), Precision.SAFE_MIN);
184 assertEquals(-0.5 * FastMath.PI, FastMath.atan2(-1e20, +Precision.SAFE_MIN), Precision.SAFE_MIN);
185 assertEquals(-0.5 * FastMath.PI, FastMath.atan2(-1e20, -Precision.SAFE_MIN), Precision.SAFE_MIN);
186 assertEquals( 0.0, FastMath.atan2(+Precision.SAFE_MIN, +1e20), Precision.SAFE_MIN);
187 assertEquals(+1.0, FastMath.copySign(1.0, FastMath.atan2(+Precision.SAFE_MIN, +1e20)), Precision.SAFE_MIN);
188 assertEquals( 0.0, FastMath.atan2(-Precision.SAFE_MIN, +1e20), Precision.SAFE_MIN);
189 assertEquals(-1.0, FastMath.copySign(1.0, FastMath.atan2(-Precision.SAFE_MIN, +1e20)), Precision.SAFE_MIN);
190 assertEquals(+FastMath.PI, FastMath.atan2(+Precision.SAFE_MIN, -1e20), Precision.SAFE_MIN);
191 assertEquals(-FastMath.PI, FastMath.atan2(-Precision.SAFE_MIN, -1e20), Precision.SAFE_MIN);
192 }
193
194 @Test
195 void testHyperbolic() {
196 double maxErr = 0;
197 for (double x = -30; x < 30; x += 0.001) {
198 double tst = FastMath.sinh(x);
199 double ref = Math.sinh(x);
200 maxErr = FastMath.max(maxErr, FastMath.abs(ref - tst) / FastMath.ulp(ref));
201 }
202 assertEquals(0, maxErr, 2);
203
204 maxErr = 0;
205 for (double x = -30; x < 30; x += 0.001) {
206 double tst = FastMath.cosh(x);
207 double ref = Math.cosh(x);
208 maxErr = FastMath.max(maxErr, FastMath.abs(ref - tst) / FastMath.ulp(ref));
209 }
210 assertEquals(0, maxErr, 2);
211
212 maxErr = 0;
213 for (double x = -0.5; x < 0.5; x += 0.001) {
214 double tst = FastMath.tanh(x);
215 double ref = Math.tanh(x);
216 maxErr = FastMath.max(maxErr, FastMath.abs(ref - tst) / FastMath.ulp(ref));
217 }
218 assertEquals(0, maxErr, 4);
219
220 }
221
222 @Test
223 void testMath904() {
224 final double x = -1;
225 final double y = (5 + 1e-15) * 1e15;
226 assertEquals(Math.pow(x, y),
227 FastMath.pow(x, y), 0);
228 assertEquals(Math.pow(x, -y),
229 FastMath.pow(x, -y), 0);
230 }
231
232 @Test
233 void testMath905LargePositive() {
234 final double start = StrictMath.log(Double.MAX_VALUE);
235 final double endT = StrictMath.sqrt(2) * StrictMath.sqrt(Double.MAX_VALUE);
236 final double end = 2 * StrictMath.log(endT);
237
238 double maxErr = 0;
239 for (double x = start; x < end; x += 1e-3) {
240 final double tst = FastMath.cosh(x);
241 final double ref = Math.cosh(x);
242 maxErr = FastMath.max(maxErr, FastMath.abs(ref - tst) / FastMath.ulp(ref));
243 }
244 assertEquals(0, maxErr, 3);
245
246 for (double x = start; x < end; x += 1e-3) {
247 final double tst = FastMath.sinh(x);
248 final double ref = Math.sinh(x);
249 maxErr = FastMath.max(maxErr, FastMath.abs(ref - tst) / FastMath.ulp(ref));
250 }
251 assertEquals(0, maxErr, 3);
252 }
253
254 @Test
255 void testMath905LargeNegative() {
256 final double start = -StrictMath.log(Double.MAX_VALUE);
257 final double endT = StrictMath.sqrt(2) * StrictMath.sqrt(Double.MAX_VALUE);
258 final double end = -2 * StrictMath.log(endT);
259
260 double maxErr = 0;
261 for (double x = start; x > end; x -= 1e-3) {
262 final double tst = FastMath.cosh(x);
263 final double ref = Math.cosh(x);
264 maxErr = FastMath.max(maxErr, FastMath.abs(ref - tst) / FastMath.ulp(ref));
265 }
266 assertEquals(0, maxErr, 3);
267
268 for (double x = start; x > end; x -= 1e-3) {
269 final double tst = FastMath.sinh(x);
270 final double ref = Math.sinh(x);
271 maxErr = FastMath.max(maxErr, FastMath.abs(ref - tst) / FastMath.ulp(ref));
272 }
273 assertEquals(0, maxErr, 3);
274 }
275
276 @Test
277 void testMath1269() {
278 final double arg = 709.8125;
279 final double vM = Math.exp(arg);
280 final double vFM = FastMath.exp(arg);
281 assertTrue(Precision.equalsIncludingNaN(vM, vFM),
282 "exp(" + arg + ") is " + vFM + " instead of " + vM);
283 }
284
285 @Test
286 void testHyperbolicInverses() {
287 double maxErr = 0;
288 for (double x = -30; x < 30; x += 0.01) {
289 maxErr = FastMath.max(maxErr, FastMath.abs(x - FastMath.sinh(FastMath.asinh(x))) / (2 * FastMath.ulp(x)));
290 }
291 assertEquals(0, maxErr, 3);
292
293 maxErr = 0;
294 for (double x = 1; x < 30; x += 0.01) {
295 maxErr = FastMath.max(maxErr, FastMath.abs(x - FastMath.cosh(FastMath.acosh(x))) / (2 * FastMath.ulp(x)));
296 }
297 assertEquals(0, maxErr, 2);
298
299 maxErr = 0;
300 for (double x = -1 + Precision.EPSILON; x < 1 - Precision.EPSILON; x += 0.0001) {
301 maxErr = FastMath.max(maxErr, FastMath.abs(x - FastMath.tanh(FastMath.atanh(x))) / (2 * FastMath.ulp(x)));
302 }
303 assertEquals(0, maxErr, 2);
304 }
305
306 @Test
307 void testLogAccuracy() {
308 double maxerrulp = 0.0;
309
310 for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
311 double x = Math.exp(generator.nextDouble() * 1416.0 - 708.0) * generator.nextDouble();
312
313 double tst = FastMath.log(x);
314 double ref = DfpMath.log(field.newDfp(x)).toDouble();
315 double err = (tst - ref) / ref;
316
317 if (err != 0.0) {
318 double ulp = Math.abs(ref -
319 Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
320 double errulp = field.newDfp(tst).subtract(DfpMath.log(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
321
322
323 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
324 }
325 }
326
327 assertTrue(maxerrulp < MAX_ERROR_ULP, "log() had errors in excess of " + MAX_ERROR_ULP + " ULP");
328 }
329
330 @Test
331 void testLog10Accuracy() {
332 double maxerrulp = 0.0;
333
334 for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
335 double x = Math.exp(generator.nextDouble() * 1416.0 - 708.0) * generator.nextDouble();
336
337 double tst = FastMath.log10(x);
338 double ref = DfpMath.log(field.newDfp(x)).divide(DfpMath.log(field.newDfp("10"))).toDouble();
339 double err = (tst - ref) / ref;
340
341 if (err != 0.0) {
342 double ulp = Math.abs(ref -
343 Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
344 double errulp = field.newDfp(tst).subtract(DfpMath.log(field.newDfp(x)).divide(DfpMath.log(field.newDfp("10")))).divide(field.newDfp(ulp)).toDouble();
345
346
347 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
348 }
349 }
350
351 assertTrue(maxerrulp < MAX_ERROR_ULP, "log10() had errors in excess of " + MAX_ERROR_ULP + " ULP");
352 }
353
354 @Test
355 void testLog1pAccuracy() {
356 double maxerrulp = 0.0;
357
358 for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
359 double x = Math.exp(generator.nextDouble() * 10.0 - 5.0) * generator.nextDouble();
360
361 double tst = FastMath.log1p(x);
362 double ref = DfpMath.log(field.newDfp(x).add(field.getOne())).toDouble();
363 double err = (tst - ref) / ref;
364
365 if (err != 0.0) {
366 double ulp = Math.abs(ref -
367 Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
368 double errulp = field.newDfp(tst).subtract(DfpMath.log(field.newDfp(x).add(field.getOne()))).divide(field.newDfp(ulp)).toDouble();
369
370
371 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
372 }
373 }
374
375 assertTrue(maxerrulp < MAX_ERROR_ULP, "log1p() had errors in excess of " + MAX_ERROR_ULP + " ULP");
376 }
377
378 @Test
379 void testLog1pSpecialCases() {
380 assertTrue(Double.isInfinite(FastMath.log1p(-1.0)), "Logp of -1.0 should be -Inf");
381 }
382
383 @Test
384 void testLogSpecialCases() {
385 assertEquals(Double.NEGATIVE_INFINITY, FastMath.log(0.0), 1.0, "Log of zero should be -Inf");
386 assertEquals(Double.NEGATIVE_INFINITY, FastMath.log(-0.0), 1.0, "Log of -zero should be -Inf");
387 assertTrue(Double.isNaN(FastMath.log(Double.NaN)), "Log of NaN should be NaN");
388 assertTrue(Double.isNaN(FastMath.log(-1.0)), "Log of negative number should be NaN");
389 assertEquals(-744.4400719213812, FastMath.log(Double.MIN_VALUE), Precision.EPSILON, "Log of Double.MIN_VALUE should be -744.4400719213812");
390 assertEquals(Double.POSITIVE_INFINITY, FastMath.log(Double.POSITIVE_INFINITY), 1.0, "Log of infinity should be infinity");
391 }
392
393 @Test
394 void testExpSpecialCases() {
395
396 assertEquals(Double.MIN_VALUE, FastMath.exp(-745.1332191019411), Precision.EPSILON);
397 assertEquals(0.0, FastMath.exp(-745.1332191019412), Precision.EPSILON, "exp(-745.1332191019412) should be 0.0");
398 assertTrue(Double.isNaN(FastMath.exp(Double.NaN)), "exp of NaN should be NaN");
399 assertEquals(Double.POSITIVE_INFINITY, FastMath.exp(Double.POSITIVE_INFINITY), 1.0, "exp of infinity should be infinity");
400 assertEquals(0.0, FastMath.exp(Double.NEGATIVE_INFINITY), Precision.EPSILON, "exp of -infinity should be 0.0");
401 assertEquals(Math.E, FastMath.exp(1.0), Precision.EPSILON, "exp(1) should be Math.E");
402 }
403
404 @Test
405 void testPowSpecialCases() {
406 final double EXACT = 1.0;
407
408 assertEquals(1.0, FastMath.pow(-1.0, 0.0), Precision.EPSILON, "pow(-1, 0) should be 1.0");
409 assertEquals(1.0, FastMath.pow(-1.0, -0.0), Precision.EPSILON, "pow(-1, -0) should be 1.0");
410 assertEquals(FastMath.PI, FastMath.pow(FastMath.PI, 1.0), Precision.EPSILON, "pow(PI, 1.0) should be PI");
411 assertEquals(-FastMath.PI, FastMath.pow(-FastMath.PI, 1.0), Precision.EPSILON, "pow(-PI, 1.0) should be -PI");
412 assertTrue(Double.isNaN(FastMath.pow(Math.PI, Double.NaN)), "pow(PI, NaN) should be NaN");
413 assertTrue(Double.isNaN(FastMath.pow(Double.NaN, Math.PI)), "pow(NaN, PI) should be NaN");
414 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(2.0, Double.POSITIVE_INFINITY), 1.0, "pow(2.0, Infinity) should be Infinity");
415 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(0.5, Double.NEGATIVE_INFINITY), 1.0, "pow(0.5, -Infinity) should be Infinity");
416 assertEquals(0.0, FastMath.pow(0.5, Double.POSITIVE_INFINITY), Precision.EPSILON, "pow(0.5, Infinity) should be 0.0");
417 assertEquals(0.0, FastMath.pow(2.0, Double.NEGATIVE_INFINITY), Precision.EPSILON, "pow(2.0, -Infinity) should be 0.0");
418 assertEquals(0.0, FastMath.pow(0.0, 0.5), Precision.EPSILON, "pow(0.0, 0.5) should be 0.0");
419 assertEquals(0.0, FastMath.pow(Double.POSITIVE_INFINITY, -0.5), Precision.EPSILON, "pow(Infinity, -0.5) should be 0.0");
420 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(0.0, -0.5), 1.0, "pow(0.0, -0.5) should be Inf");
421 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(Double.POSITIVE_INFINITY, 0.5), 1.0, "pow(Inf, 0.5) should be Inf");
422 assertEquals(Double.NEGATIVE_INFINITY, FastMath.pow(-0.0, -3.0), 1.0, "pow(-0.0, -3.0) should be -Inf");
423 assertEquals(0.0, FastMath.pow(-0.0, Double.POSITIVE_INFINITY), Precision.EPSILON, "pow(-0.0, Infinity) should be 0.0");
424 assertTrue(Double.isNaN(FastMath.pow(-0.0, Double.NaN)), "pow(-0.0, NaN) should be NaN");
425 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(-0.0, -Double.MIN_VALUE), 1.0, "pow(-0.0, -tiny) should be Infinity");
426 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(-0.0, -Double.MAX_VALUE), 1.0, "pow(-0.0, -huge) should be Infinity");
427 assertEquals(Double.NEGATIVE_INFINITY, FastMath.pow(Double.NEGATIVE_INFINITY, 3.0), 1.0, "pow(-Inf, 3.0) should be -Inf");
428 assertEquals(-0.0, FastMath.pow(Double.NEGATIVE_INFINITY, -3.0), EXACT, "pow(-Inf, -3.0) should be -0.0");
429 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(-0.0, -3.5), 1.0, "pow(-0.0, -3.5) should be Inf");
430 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(Double.POSITIVE_INFINITY, 3.5), 1.0, "pow(Inf, 3.5) should be Inf");
431 assertEquals(-8.0, FastMath.pow(-2.0, 3.0), Precision.EPSILON, "pow(-2.0, 3.0) should be -8.0");
432 assertTrue(Double.isNaN(FastMath.pow(-2.0, 3.5)), "pow(-2.0, 3.5) should be NaN");
433 assertTrue(Double.isNaN(FastMath.pow(Double.NaN, Double.NEGATIVE_INFINITY)), "pow(NaN, -Infinity) should be NaN");
434 assertEquals(1.0, FastMath.pow(Double.NaN, 0.0), Precision.EPSILON, "pow(NaN, 0.0) should be 1.0");
435 assertEquals(0.0, FastMath.pow(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY), Precision.EPSILON, "pow(-Infinity, -Infinity) should be 0.0");
436 assertEquals(0.0, FastMath.pow(-Double.MAX_VALUE, -Double.MAX_VALUE), Precision.EPSILON, "pow(-huge, -huge) should be 0.0");
437 assertTrue(Double.isInfinite(FastMath.pow(-Double.MAX_VALUE, Double.MAX_VALUE)), "pow(-huge, huge) should be +Inf");
438 assertTrue(Double.isNaN(FastMath.pow(Double.NaN, Double.NEGATIVE_INFINITY)), "pow(NaN, -Infinity) should be NaN");
439 assertEquals(1.0, FastMath.pow(Double.NaN, -0.0), Precision.EPSILON, "pow(NaN, -0.0) should be 1.0");
440 assertEquals(0.0, FastMath.pow(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY), Precision.EPSILON, "pow(-Infinity, -Infinity) should be 0.0");
441 assertEquals(0.0, FastMath.pow(-Double.MAX_VALUE, -Double.MAX_VALUE), Precision.EPSILON, "pow(-huge, -huge) should be 0.0");
442 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(-Double.MAX_VALUE, Double.MAX_VALUE), 1.0, "pow(-huge, huge) should be +Inf");
443
444
445
446 assertTrue(Double.isNaN(FastMath.pow(Double.POSITIVE_INFINITY, Double.NaN)), "pow(+Inf, NaN) should be NaN");
447 assertTrue(Double.isNaN(FastMath.pow(1.0, Double.POSITIVE_INFINITY)), "pow(1.0, +Inf) should be NaN");
448 assertTrue(Double.isNaN(FastMath.pow(Double.NEGATIVE_INFINITY, Double.NaN)), "pow(-Inf, NaN) should be NaN");
449 assertEquals(-0.0, FastMath.pow(Double.NEGATIVE_INFINITY, -1.0), EXACT, "pow(-Inf, -1.0) should be -0.0");
450 assertEquals(0.0, FastMath.pow(Double.NEGATIVE_INFINITY, -2.0), EXACT, "pow(-Inf, -2.0) should be 0.0");
451 assertEquals(Double.NEGATIVE_INFINITY, FastMath.pow(Double.NEGATIVE_INFINITY, 1.0), 1.0, "pow(-Inf, 1.0) should be -Inf");
452 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(Double.NEGATIVE_INFINITY, 2.0), 1.0, "pow(-Inf, 2.0) should be +Inf");
453 assertTrue(Double.isNaN(FastMath.pow(1.0, Double.NEGATIVE_INFINITY)), "pow(1.0, -Inf) should be NaN");
454 assertEquals(-0.0, FastMath.pow(-0.0, 1.0), EXACT, "pow(-0.0, 1.0) should be -0.0");
455 assertEquals(0.0, FastMath.pow(0.0, 1.0), EXACT, "pow(0.0, 1.0) should be 0.0");
456 assertEquals(0.0, FastMath.pow(0.0, Double.POSITIVE_INFINITY), EXACT, "pow(0.0, +Inf) should be 0.0");
457 assertEquals(0.0, FastMath.pow(-0.0, 6.0), EXACT, "pow(-0.0, even) should be 0.0");
458 assertEquals(-0.0, FastMath.pow(-0.0, 13.0), EXACT, "pow(-0.0, odd) should be -0.0");
459 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(-0.0, -6.0), EXACT, "pow(-0.0, -even) should be +Inf");
460 assertEquals(Double.NEGATIVE_INFINITY, FastMath.pow(-0.0, -13.0), EXACT, "pow(-0.0, -odd) should be -Inf");
461 assertEquals(16.0, FastMath.pow(-2.0, 4.0), EXACT, "pow(-2.0, 4.0) should be 16.0");
462 assertEquals(Double.NaN, FastMath.pow(-2.0, 4.5), EXACT, "pow(-2.0, 4.5) should be NaN");
463 assertEquals(1.0, FastMath.pow(-0.0, -0.0), EXACT, "pow(-0.0, -0.0) should be 1.0");
464 assertEquals(1.0, FastMath.pow(-0.0, 0.0), EXACT, "pow(-0.0, 0.0) should be 1.0");
465 assertEquals(1.0, FastMath.pow(0.0, -0.0), EXACT, "pow(0.0, -0.0) should be 1.0");
466 assertEquals(1.0, FastMath.pow(0.0, 0.0), EXACT, "pow(0.0, 0.0) should be 1.0");
467 }
468
469 @Test
470 @Timeout(value = 20000L, unit = TimeUnit.MILLISECONDS)
471 void testPowAllSpecialCases() {
472 final double EXACT = 0;
473 final double[] DOUBLES = new double[]
474 {
475 Double.NEGATIVE_INFINITY, -0.0, Double.NaN, 0.0, Double.POSITIVE_INFINITY,
476 Long.MIN_VALUE, Integer.MIN_VALUE, Short.MIN_VALUE, Byte.MIN_VALUE,
477 -(double)Long.MIN_VALUE, -(double)Integer.MIN_VALUE, -(double)Short.MIN_VALUE, -(double)Byte.MIN_VALUE,
478 Byte.MAX_VALUE, Short.MAX_VALUE, Integer.MAX_VALUE, Long.MAX_VALUE,
479 -Byte.MAX_VALUE, -Short.MAX_VALUE, -Integer.MAX_VALUE, -Long.MAX_VALUE,
480 Float.MAX_VALUE, Double.MAX_VALUE, Double.MIN_VALUE, Float.MIN_VALUE,
481 -Float.MAX_VALUE, -Double.MAX_VALUE, -Double.MIN_VALUE, -Float.MIN_VALUE,
482 0.5, 0.1, 0.2, 0.8, 1.1, 1.2, 1.5, 1.8, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 1.3, 2.2, 2.5, 2.8, 33.0, 33.1, 33.5, 33.8, 10.0, 300.0, 400.0, 500.0,
483 -0.5, -0.1, -0.2, -0.8, -1.1, -1.2, -1.5, -1.8, -1.0, -2.0, -3.0, -4.0, -5.0, -6.0, -7.0, -8.0, -9.0, -1.3, -2.2, -2.5, -2.8, -33.0, -33.1, -33.5, -33.8, -10.0, -300.0, -400.0, -500.0
484 };
485
486
487
488 for (double d : DOUBLES) {
489 assertEquals(1.0, FastMath.pow(d, 0.0), EXACT);
490 }
491 for (double d : DOUBLES) {
492 assertEquals(1.0, FastMath.pow(d, -0.0), EXACT);
493 }
494
495 for (double d : DOUBLES) {
496 assertEquals(d, FastMath.pow(d, 1.0), EXACT);
497 }
498
499 for (double d : DOUBLES) {
500 assertEquals(Double.NaN, FastMath.pow(d, Double.NaN), EXACT);
501 }
502
503 for (double i : DOUBLES) {
504 if (i != 0.0) {
505 assertEquals(Double.NaN, FastMath.pow(Double.NaN, i), EXACT);
506 }
507 }
508
509
510 for (double d : DOUBLES) {
511 if (Math.abs(d) > 1.0) {
512 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(d, Double.POSITIVE_INFINITY), EXACT);
513 }
514 }
515 for (double d : DOUBLES) {
516 if (Math.abs(d) < 1.0) {
517 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(d, Double.NEGATIVE_INFINITY), EXACT);
518 }
519 }
520
521
522 for (double d : DOUBLES) {
523 if (Math.abs(d) > 1.0) {
524 assertEquals(0.0, FastMath.pow(d, Double.NEGATIVE_INFINITY), EXACT);
525 }
526 }
527 for (double d : DOUBLES) {
528 if (Math.abs(d) < 1.0) {
529 assertEquals(0.0, FastMath.pow(d, Double.POSITIVE_INFINITY), EXACT);
530 }
531 }
532
533 assertEquals(Double.NaN, FastMath.pow(1.0, Double.POSITIVE_INFINITY), EXACT);
534 assertEquals(Double.NaN, FastMath.pow(1.0, Double.NEGATIVE_INFINITY), EXACT);
535 assertEquals(Double.NaN, FastMath.pow(-1.0, Double.POSITIVE_INFINITY), EXACT);
536 assertEquals(Double.NaN, FastMath.pow(-1.0, Double.NEGATIVE_INFINITY), EXACT);
537
538
539 for (double i : DOUBLES) {
540 if (i > 0.0) {
541 assertEquals(0.0, FastMath.pow(0.0, i), EXACT);
542 }
543 }
544 for (double i : DOUBLES) {
545 if (i < 0.0) {
546 assertEquals(0.0, FastMath.pow(Double.POSITIVE_INFINITY, i), EXACT);
547 }
548 }
549
550
551 for (double i : DOUBLES) {
552 if (i < 0.0) {
553 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(0.0, i), EXACT);
554 }
555 }
556 for (double i : DOUBLES) {
557 if (i > 0.0) {
558 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(Double.POSITIVE_INFINITY, i), EXACT);
559 }
560 }
561
562
563 for (double i : DOUBLES) {
564 if (i > 0.0 && (Double.isInfinite(i) || i % 2.0 == 0.0)) {
565 assertEquals(0.0, FastMath.pow(-0.0, i), EXACT);
566 }
567 }
568 for (double i : DOUBLES) {
569 if (i < 0.0 && (Double.isInfinite(i) || i % 2.0 == 0.0)) {
570 assertEquals(0.0, FastMath.pow(Double.NEGATIVE_INFINITY, i), EXACT);
571 }
572 }
573
574
575 for (double i : DOUBLES) {
576 if (i > 0.0 && i % 2.0 == 1.0) {
577 assertEquals(-0.0, FastMath.pow(-0.0, i), EXACT);
578 }
579 }
580 for (double i : DOUBLES) {
581 if (i < 0.0 && i % 2.0 == -1.0) {
582 assertEquals(-0.0, FastMath.pow(Double.NEGATIVE_INFINITY, i), EXACT);
583 }
584 }
585
586
587 for (double i : DOUBLES) {
588 if (i > 0.0 && (Double.isInfinite(i) || i % 2.0 == 0.0)) {
589 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(Double.NEGATIVE_INFINITY, i), EXACT);
590 }
591 }
592 for (double i : DOUBLES) {
593 if (i < 0.0 && (Double.isInfinite(i) || i % 2.0 == 0.0)) {
594 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(-0.0, i), EXACT);
595 }
596 }
597
598
599 for (double i : DOUBLES) {
600 if (i > 0.0 && i % 2.0 == 1.0) {
601 assertEquals(Double.NEGATIVE_INFINITY, FastMath.pow(Double.NEGATIVE_INFINITY, i), EXACT);
602 }
603 }
604 for (double i : DOUBLES) {
605 if (i < 0.0 && i % 2.0 == -1.0) {
606 assertEquals(Double.NEGATIVE_INFINITY, FastMath.pow(-0.0, i), EXACT);
607 }
608 }
609 for (double d : DOUBLES) {
610
611 if (d < 0.0 && Math.abs(d) <= Double.MAX_VALUE) {
612 for (double i : DOUBLES) {
613 if (Math.abs(i) <= Double.MAX_VALUE) {
614
615 if (i % 2.0 == 0.0) assertEquals(FastMath.pow(-d, i), FastMath.pow(d, i), EXACT);
616
617 else if (Math.abs(i) % 2.0 == 1.0) assertEquals(-FastMath.pow(-d, i), FastMath.pow(d, i), EXACT);
618
619 else assertEquals(Double.NaN, FastMath.pow(d, i), EXACT);
620 }
621 }
622 }
623 }
624
625
626 final int TOO_BIG_TO_CALCULATE = 18;
627 for (double d : DOUBLES) {
628 if (d % 1.0 == 0.0) {
629 boolean dNegative = Double.doubleToRawLongBits( d ) < 0L;
630 for (double i : DOUBLES) {
631 if (i % 1.0 == 0.0) {
632 BigInteger bd = BigDecimal.valueOf(d).toBigInteger().abs();
633 BigInteger bi = BigDecimal.valueOf(i).toBigInteger().abs();
634 double expected;
635 if (bd.bitLength() > 1 && bi.bitLength() > 1 && 32 - Integer.numberOfLeadingZeros(bd.bitLength()) + bi.bitLength() > TOO_BIG_TO_CALCULATE) {
636
637 expected = i < 0.0 ? 0.0 : Double.POSITIVE_INFINITY;
638 } else {
639 BigInteger res = ArithmeticUtils.pow(bd, bi);
640 if (i >= 0.0) {
641 expected = res.doubleValue();
642 } else if (res.signum() == 0) {
643 expected = Double.POSITIVE_INFINITY;
644 } else {
645 expected = BigDecimal.ONE.divide( new BigDecimal( res ), 1024, RoundingMode.HALF_UP ).doubleValue();
646 }
647 }
648 if (dNegative && bi.testBit( 0 )) {
649 expected = -expected;
650 }
651 assertEquals(expected, FastMath.pow(d, i), expected == 0.0 || Double.isInfinite(expected) || Double.isNaN(expected) ? EXACT : 2.0 * Math.ulp(expected), d + "^" + i + "=" + expected + ", Math.pow=" + Math.pow(d, i));
652 }
653 }
654 }
655 }
656 }
657
658 @Test
659 void testPowLargeIntegralDouble() {
660 double y = FastMath.scalb(1.0, 65);
661 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(FastMath.nextUp(1.0), y), 1.0);
662 assertEquals(1.0, FastMath.pow(1.0, y), 1.0);
663 assertEquals(0.0, FastMath.pow(FastMath.nextDown(1.0), y), 1.0);
664 assertEquals(0.0, FastMath.pow(FastMath.nextUp(-1.0), y), 1.0);
665 assertEquals(1.0, FastMath.pow(-1.0, y), 1.0);
666 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(FastMath.nextDown(-1.0), y), 1.0);
667 }
668
669 @Test
670 void testAtan2SpecialCases() {
671
672 assertTrue(Double.isNaN(FastMath.atan2(Double.NaN, 0.0)), "atan2(NaN, 0.0) should be NaN");
673 assertTrue(Double.isNaN(FastMath.atan2(0.0, Double.NaN)), "atan2(0.0, NaN) should be NaN");
674 assertEquals(0.0, FastMath.atan2(0.0, 0.0), Precision.EPSILON, "atan2(0.0, 0.0) should be 0.0");
675 assertEquals(0.0, FastMath.atan2(0.0, 0.001), Precision.EPSILON, "atan2(0.0, 0.001) should be 0.0");
676 assertEquals(0.0, FastMath.atan2(0.1, Double.POSITIVE_INFINITY), Precision.EPSILON, "atan2(0.1, +Inf) should be 0.0");
677 assertEquals(-0.0, FastMath.atan2(-0.0, 0.0), Precision.EPSILON, "atan2(-0.0, 0.0) should be -0.0");
678 assertEquals(-0.0, FastMath.atan2(-0.0, 0.001), Precision.EPSILON, "atan2(-0.0, 0.001) should be -0.0");
679 assertEquals(-0.0, FastMath.atan2(-0.1, Double.POSITIVE_INFINITY), Precision.EPSILON, "atan2(-0.0, +Inf) should be -0.0");
680 assertEquals(FastMath.PI, FastMath.atan2(0.0, -0.0), Precision.EPSILON, "atan2(0.0, -0.0) should be PI");
681 assertEquals(FastMath.PI, FastMath.atan2(0.1, Double.NEGATIVE_INFINITY), Precision.EPSILON, "atan2(0.1, -Inf) should be PI");
682 assertEquals(-FastMath.PI, FastMath.atan2(-0.0, -0.0), Precision.EPSILON, "atan2(-0.0, -0.0) should be -PI");
683 assertEquals(-FastMath.PI, FastMath.atan2(-0.1, Double.NEGATIVE_INFINITY), Precision.EPSILON, "atan2(0.1, -Inf) should be -PI");
684 assertEquals(FastMath.PI / 2.0, FastMath.atan2(0.1, 0.0), Precision.EPSILON, "atan2(0.1, 0.0) should be PI/2");
685 assertEquals(FastMath.PI / 2.0, FastMath.atan2(0.1, -0.0), Precision.EPSILON, "atan2(0.1, -0.0) should be PI/2");
686 assertEquals(FastMath.PI / 2.0, FastMath.atan2(Double.POSITIVE_INFINITY, 0.1), Precision.EPSILON, "atan2(Inf, 0.1) should be PI/2");
687 assertEquals(FastMath.PI / 2.0, FastMath.atan2(Double.POSITIVE_INFINITY, -0.1), Precision.EPSILON, "atan2(Inf, -0.1) should be PI/2");
688 assertEquals(-FastMath.PI / 2.0, FastMath.atan2(-0.1, 0.0), Precision.EPSILON, "atan2(-0.1, 0.0) should be -PI/2");
689 assertEquals(-FastMath.PI / 2.0, FastMath.atan2(-0.1, -0.0), Precision.EPSILON, "atan2(-0.1, -0.0) should be -PI/2");
690 assertEquals(-FastMath.PI / 2.0, FastMath.atan2(Double.NEGATIVE_INFINITY, 0.1), Precision.EPSILON, "atan2(-Inf, 0.1) should be -PI/2");
691 assertEquals(-FastMath.PI / 2.0, FastMath.atan2(Double.NEGATIVE_INFINITY, -0.1), Precision.EPSILON, "atan2(-Inf, -0.1) should be -PI/2");
692 assertEquals(FastMath.PI / 4.0, FastMath.atan2(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY),
693 Precision.EPSILON,
694 "atan2(Inf, Inf) should be PI/4");
695 assertEquals(FastMath.PI * 3.0 / 4.0,
696 FastMath.atan2(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY), Precision.EPSILON, "atan2(Inf, -Inf) should be PI * 3/4");
697 assertEquals(-FastMath.PI / 4.0, FastMath.atan2(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY),
698 Precision.EPSILON,
699 "atan2(-Inf, Inf) should be -PI/4");
700 assertEquals(- FastMath.PI * 3.0 / 4.0,
701 FastMath.atan2(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY), Precision.EPSILON, "atan2(-Inf, -Inf) should be -PI * 3/4");
702 }
703
704 @Test
705 void testPowAccuracy() {
706 double maxerrulp = 0.0;
707
708 for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
709 double x = (generator.nextDouble() * 2.0 + 0.25);
710 double y = (generator.nextDouble() * 1200.0 - 600.0) * generator.nextDouble();
711
712
713
714
715
716
717
718
719 double tst = FastMath.pow(x, y);
720 double ref = DfpMath.pow(field.newDfp(x), field.newDfp(y)).toDouble();
721 double err = (tst - ref) / ref;
722
723 if (err != 0) {
724 double ulp = Math.abs(ref -
725 Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
726 double errulp = field.newDfp(tst).subtract(DfpMath.pow(field.newDfp(x), field.newDfp(y))).divide(field.newDfp(ulp)).toDouble();
727
728
729 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
730 }
731 }
732
733 assertTrue(maxerrulp < MAX_ERROR_ULP, "pow() had errors in excess of " + MAX_ERROR_ULP + " ULP");
734 }
735
736 @Test
737 void testExpAccuracy() {
738 double maxerrulp = 0.0;
739
740 for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
741
742 double x = ((generator.nextDouble() * 1416.0) - 708.0) * generator.nextDouble();
743
744
745
746 double tst = FastMath.exp(x);
747 double ref = DfpMath.exp(field.newDfp(x)).toDouble();
748 double err = (tst - ref) / ref;
749
750 if (err != 0) {
751 double ulp = Math.abs(ref -
752 Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
753 double errulp = field.newDfp(tst).subtract(DfpMath.exp(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
754
755
756 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
757 }
758 }
759
760 assertTrue(maxerrulp < MAX_ERROR_ULP, "exp() had errors in excess of " + MAX_ERROR_ULP + " ULP");
761 }
762
763 @Test
764 void testSinCosSpecialCases() {
765 for (double x : new double[] {
766 -0.0, +0.0, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY,
767 Double.NaN, Precision.EPSILON, -Precision.EPSILON,
768 Precision.SAFE_MIN, -Precision.SAFE_MIN,
769 FastMath.PI, MathUtils.TWO_PI
770 }) {
771 doTestSinCos(x);
772 }
773 }
774
775 @Test
776 void testSinCosRandom() {
777 final RandomGenerator random = new Well19937a(0xf67ff538323a55eaL);
778 for (int i = 0; i < 1000000; ++i) {
779 doTestSinCos(1000000.0 * (2.0 * random.nextDouble() - 1.0));
780 }
781 }
782
783 private void doTestSinCos(final double x) {
784 final SinCos sinCos = FastMath.sinCos(x);
785 UnitTestUtils.customAssertSame(FastMath.sin(x), sinCos.sin());
786 UnitTestUtils.customAssertSame(FastMath.cos(x), sinCos.cos());
787 }
788
789 @Test
790 void testSinCosSum() {
791 final RandomGenerator random = new Well19937a(0x4aab62a42c9eb940L);
792 for (int i = 0; i < 1000000; ++i) {
793 final double alpha = 10.0 * (2.0 * random.nextDouble() - 1.0);
794 final double beta = 10.0 * (2.0 * random.nextDouble() - 1.0);
795 final SinCos scAlpha = FastMath.sinCos(alpha);
796 final SinCos scBeta = FastMath.sinCos(beta);
797 final SinCos scAlphaPlusBeta = FastMath.sinCos(alpha + beta);
798 final SinCos scSum = SinCos.sum(scAlpha, scBeta);
799 assertEquals(scAlphaPlusBeta.sin(), scSum.sin(), 2.0e-15);
800 assertEquals(scAlphaPlusBeta.cos(), scSum.cos(), 2.0e-15);
801 }
802 }
803
804 @Test
805 void testSinCosdifference() {
806 final RandomGenerator random = new Well19937a(0x589aaf49471b03d5L);
807 for (int i = 0; i < 1000000; ++i) {
808 final double alpha = 10.0 * (2.0 * random.nextDouble() - 1.0);
809 final double beta = 10.0 * (2.0 * random.nextDouble() - 1.0);
810 final SinCos scAlpha = FastMath.sinCos(alpha);
811 final SinCos scBeta = FastMath.sinCos(beta);
812 final SinCos scAlphaMinusBeta = FastMath.sinCos(alpha - beta);
813 final SinCos scdifference = SinCos.difference(scAlpha, scBeta);
814 assertEquals(scAlphaMinusBeta.sin(), scdifference.sin(), 2.0e-15);
815 assertEquals(scAlphaMinusBeta.cos(), scdifference.cos(), 2.0e-15);
816 }
817 }
818
819 @Test
820 void testSinAccuracy() {
821 double maxerrulp = 0.0;
822
823 for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
824
825
826 double x = ((generator.nextDouble() * Math.PI) - Math.PI / 2.0) *
827 Math.pow(2, 21) * generator.nextDouble();
828
829
830
831 double tst = FastMath.sin(x);
832 double ref = DfpMath.sin(field.newDfp(x)).toDouble();
833 double err = (tst - ref) / ref;
834
835 if (err != 0) {
836 double ulp = Math.abs(ref -
837 Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
838 double errulp = field.newDfp(tst).subtract(DfpMath.sin(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
839
840
841 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
842 }
843 }
844
845 assertTrue(maxerrulp < MAX_ERROR_ULP, "sin() had errors in excess of " + MAX_ERROR_ULP + " ULP");
846 }
847
848 @Test
849 void testCosAccuracy() {
850 double maxerrulp = 0.0;
851
852 for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
853
854
855 double x = ((generator.nextDouble() * Math.PI) - Math.PI / 2.0) *
856 Math.pow(2, 21) * generator.nextDouble();
857
858
859
860 double tst = FastMath.cos(x);
861 double ref = DfpMath.cos(field.newDfp(x)).toDouble();
862 double err = (tst - ref) / ref;
863
864 if (err != 0) {
865 double ulp = Math.abs(ref -
866 Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
867 double errulp = field.newDfp(tst).subtract(DfpMath.cos(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
868
869
870 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
871 }
872 }
873
874 assertTrue(maxerrulp < MAX_ERROR_ULP, "cos() had errors in excess of " + MAX_ERROR_ULP + " ULP");
875 }
876
877 @Test
878 void testTanAccuracy() {
879 double maxerrulp = 0.0;
880
881 for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
882
883
884 double x = ((generator.nextDouble() * Math.PI) - Math.PI / 2.0) *
885 Math.pow(2, 12) * generator.nextDouble();
886
887
888
889 double tst = FastMath.tan(x);
890 double ref = DfpMath.tan(field.newDfp(x)).toDouble();
891 double err = (tst - ref) / ref;
892
893 if (err != 0) {
894 double ulp = Math.abs(ref -
895 Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
896 double errulp = field.newDfp(tst).subtract(DfpMath.tan(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
897
898
899 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
900 }
901 }
902
903 assertTrue(maxerrulp < MAX_ERROR_ULP, "tan() had errors in excess of " + MAX_ERROR_ULP + " ULP");
904 }
905
906 @Test
907 void testAtanAccuracy() {
908 double maxerrulp = 0.0;
909
910 for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
911
912
913
914
915 double x = ((generator.nextDouble() * 16.0) - 8.0) * generator.nextDouble();
916
917
918
919
920 double tst = FastMath.atan(x);
921 double ref = DfpMath.atan(field.newDfp(x)).toDouble();
922 double err = (tst - ref) / ref;
923
924 if (err != 0) {
925 double ulp = Math.abs(ref -
926 Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
927 double errulp = field.newDfp(tst).subtract(DfpMath.atan(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
928
929
930 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
931 }
932 }
933
934 assertTrue(maxerrulp < MAX_ERROR_ULP, "atan() had errors in excess of " + MAX_ERROR_ULP + " ULP");
935 }
936
937 @Test
938 void testAtan2Accuracy() {
939 double maxerrulp = 0.0;
940
941 for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
942
943
944 double x = generator.nextDouble() - 0.5;
945 double y = generator.nextDouble() - 0.5;
946
947
948
949 double tst = FastMath.atan2(y, x);
950 Dfp refdfp = DfpMath.atan(field.newDfp(y).divide(field.newDfp(x)));
951
952 if (x < 0.0) {
953 if (y > 0.0)
954 refdfp = field.getPi().add(refdfp);
955 else
956 refdfp = refdfp.subtract(field.getPi());
957 }
958
959 double ref = refdfp.toDouble();
960 double err = (tst - ref) / ref;
961
962 if (err != 0) {
963 double ulp = Math.abs(ref -
964 Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
965 double errulp = field.newDfp(tst).subtract(refdfp).divide(field.newDfp(ulp)).toDouble();
966
967
968 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
969 }
970 }
971
972 assertTrue(maxerrulp < MAX_ERROR_ULP, "atan2() had errors in excess of " + MAX_ERROR_ULP + " ULP");
973 }
974
975 @Test
976 void testExpm1Huge() {
977 assertTrue(Double.isInfinite(FastMath.expm1(709.85)));
978 }
979
980 @Test
981 void testExpm1Accuracy() {
982 double maxerrulp = 0.0;
983
984 for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
985
986
987 double x = ((generator.nextDouble() * 16.0) - 8.0) * generator.nextDouble();
988
989 double tst = FastMath.expm1(x);
990 double ref = DfpMath.exp(field.newDfp(x)).subtract(field.getOne()).toDouble();
991 double err = (tst - ref) / ref;
992
993 if (err != 0) {
994 double ulp = Math.abs(ref -
995 Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
996 double errulp = field.newDfp(tst).subtract(DfpMath.exp(field.newDfp(x)).subtract(field.getOne())).divide(field.newDfp(ulp)).toDouble();
997
998
999 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
1000 }
1001 }
1002
1003 assertTrue(maxerrulp < MAX_ERROR_ULP, "expm1() had errors in excess of " + MAX_ERROR_ULP + " ULP");
1004 }
1005
1006 @Test
1007 void testAsinAccuracy() {
1008 double maxerrulp = 0.0;
1009
1010 for (int i=0; i<10000; i++) {
1011 double x = ((generator.nextDouble() * 2.0) - 1.0) * generator.nextDouble();
1012
1013 double tst = FastMath.asin(x);
1014 double ref = DfpMath.asin(field.newDfp(x)).toDouble();
1015 double err = (tst - ref) / ref;
1016
1017 if (err != 0) {
1018 double ulp = Math.abs(ref - Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
1019 double errulp = field.newDfp(tst).subtract(DfpMath.asin(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
1020
1021
1022 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
1023 }
1024 }
1025
1026 assertTrue(maxerrulp < MAX_ERROR_ULP, "asin() had errors in excess of " + MAX_ERROR_ULP + " ULP");
1027 }
1028
1029 @Test
1030 void testAcosAccuracy() {
1031 double maxerrulp = 0.0;
1032
1033 for (int i=0; i<10000; i++) {
1034 double x = ((generator.nextDouble() * 2.0) - 1.0) * generator.nextDouble();
1035
1036 double tst = FastMath.acos(x);
1037 double ref = DfpMath.acos(field.newDfp(x)).toDouble();
1038 double err = (tst - ref) / ref;
1039
1040 if (err != 0) {
1041 double ulp = Math.abs(ref - Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
1042 double errulp = field.newDfp(tst).subtract(DfpMath.acos(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
1043
1044
1045 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
1046 }
1047 }
1048
1049 assertTrue(maxerrulp < MAX_ERROR_ULP, "acos() had errors in excess of " + MAX_ERROR_ULP + " ULP");
1050 }
1051
1052
1053
1054
1055 @Test
1056 void testAcosSpecialCases() {
1057
1058 assertTrue(Double.isNaN(FastMath.acos(Double.NaN)), "acos(NaN) should be NaN");
1059 assertTrue(Double.isNaN(FastMath.acos(-1.1)), "acos(-1.1) should be NaN");
1060 assertTrue(Double.isNaN(FastMath.acos(1.1)), "acos(-1.1) should be NaN");
1061 assertEquals(FastMath.PI, FastMath.acos(-1.0), Precision.EPSILON, "acos(-1.0) should be PI");
1062 assertEquals(0.0, FastMath.acos(1.0), Precision.EPSILON, "acos(1.0) should be 0.0");
1063 assertEquals(FastMath.acos(0.0), FastMath.PI / 2.0, Precision.EPSILON, "acos(0.0) should be PI/2");
1064 }
1065
1066
1067
1068
1069 @Test
1070 void testAsinSpecialCases() {
1071
1072 assertTrue(Double.isNaN(FastMath.asin(Double.NaN)), "asin(NaN) should be NaN");
1073 assertTrue(Double.isNaN(FastMath.asin(1.1)), "asin(1.1) should be NaN");
1074 assertTrue(Double.isNaN(FastMath.asin(-1.1)), "asin(-1.1) should be NaN");
1075 assertEquals(FastMath.asin(1.0), FastMath.PI / 2.0, Precision.EPSILON, "asin(1.0) should be PI/2");
1076 assertEquals(FastMath.asin(-1.0), -FastMath.PI / 2.0, Precision.EPSILON, "asin(-1.0) should be -PI/2");
1077 assertEquals(0.0, FastMath.asin(0.0), Precision.EPSILON, "asin(0.0) should be 0.0");
1078 }
1079
1080 private Dfp cosh(Dfp x) {
1081 return DfpMath.exp(x).add(DfpMath.exp(x.negate())).divide(2);
1082 }
1083
1084 private Dfp sinh(Dfp x) {
1085 return DfpMath.exp(x).subtract(DfpMath.exp(x.negate())).divide(2);
1086 }
1087
1088 private Dfp tanh(Dfp x) {
1089 return sinh(x).divide(cosh(x));
1090 }
1091
1092 @Test
1093 void testSinhCoshSpecialCases() {
1094 for (double x : new double[] {
1095 -0.0, +0.0, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY,
1096 Double.NaN, Precision.EPSILON, -Precision.EPSILON,
1097 Precision.SAFE_MIN, -Precision.SAFE_MIN,
1098 FastMath.PI, MathUtils.TWO_PI
1099 }) {
1100 doTestSinhCosh(x);
1101 }
1102 }
1103
1104 @Test
1105 void testSinhCoshRandom() {
1106 final RandomGenerator random = new Well19937a(0xa7babe18705d756fL);
1107 for (int i = 0; i < 1000000; ++i) {
1108 doTestSinhCosh(1000.0 * (2.0 * random.nextDouble() - 1.0));
1109 }
1110 }
1111
1112 private void doTestSinhCosh(final double x) {
1113 final SinhCosh sinhCosh = FastMath.sinhCosh(x);
1114 UnitTestUtils.customAssertSame(FastMath.sinh(x), sinhCosh.sinh());
1115 UnitTestUtils.customAssertSame(FastMath.cosh(x), sinhCosh.cosh());
1116 }
1117
1118 @Test
1119 void testSinhCoshSum() {
1120 final RandomGenerator random = new Well19937a(0x11cf5123446bc9ffL);
1121 for (int i = 0; i < 1000000; ++i) {
1122 final double alpha = 2.0 * (2.0 * random.nextDouble() - 1.0);
1123 final double beta = 2.0 * (2.0 * random.nextDouble() - 1.0);
1124 final SinhCosh schAlpha = FastMath.sinhCosh(alpha);
1125 final SinhCosh schBeta = FastMath.sinhCosh(beta);
1126 final SinhCosh schAlphaPlusBeta = FastMath.sinhCosh(alpha + beta);
1127 final SinhCosh schSum = SinhCosh.sum(schAlpha, schBeta);
1128 final double tol = 8 * FastMath.max(FastMath.max(FastMath.ulp(schAlpha.sinh()), FastMath.ulp(schAlpha.cosh())),
1129 FastMath.max(FastMath.ulp(schBeta.sinh()), FastMath.ulp(schBeta.cosh())));
1130 assertEquals(schAlphaPlusBeta.sinh(), schSum.sinh(), tol);
1131 assertEquals(schAlphaPlusBeta.cosh(), schSum.cosh(), tol);
1132 }
1133 }
1134
1135 @Test
1136 void testSinhCoshdifference() {
1137 final RandomGenerator random = new Well19937a(0x219fd680c53974bbL);
1138 for (int i = 0; i < 1000000; ++i) {
1139 final double alpha = 2.0 * (2.0 * random.nextDouble() - 1.0);
1140 final double beta = 2.0 * (2.0 * random.nextDouble() - 1.0);
1141 final SinhCosh schAlpha = FastMath.sinhCosh(alpha);
1142 final SinhCosh schBeta = FastMath.sinhCosh(beta);
1143 final SinhCosh schAlphaMinusBeta = FastMath.sinhCosh(alpha - beta);
1144 final SinhCosh schDifference = SinhCosh.difference(schAlpha, schBeta);
1145 final double tol = 8 * FastMath.max(FastMath.max(FastMath.ulp(schAlpha.sinh()), FastMath.ulp(schAlpha.cosh())),
1146 FastMath.max(FastMath.ulp(schBeta.sinh()), FastMath.ulp(schBeta.cosh())));
1147 assertEquals(schAlphaMinusBeta.sinh(), schDifference.sinh(), tol);
1148 assertEquals(schAlphaMinusBeta.cosh(), schDifference.cosh(), tol);
1149 }
1150 }
1151
1152 @Test
1153 void testSinhAccuracy() {
1154 double maxerrulp = 0.0;
1155
1156 for (int i=0; i<10000; i++) {
1157 double x = ((generator.nextDouble() * 16.0) - 8.0) * generator.nextDouble();
1158
1159 double tst = FastMath.sinh(x);
1160 double ref = sinh(field.newDfp(x)).toDouble();
1161 double err = (tst - ref) / ref;
1162
1163 if (err != 0) {
1164 double ulp = Math.abs(ref - Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
1165 double errulp = field.newDfp(tst).subtract(sinh(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
1166
1167 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
1168 }
1169 }
1170
1171 assertTrue(maxerrulp < MAX_ERROR_ULP, "sinh() had errors in excess of " + MAX_ERROR_ULP + " ULP");
1172 }
1173
1174 @Test
1175 void testCoshAccuracy() {
1176 double maxerrulp = 0.0;
1177
1178 for (int i=0; i<10000; i++) {
1179 double x = ((generator.nextDouble() * 16.0) - 8.0) * generator.nextDouble();
1180
1181 double tst = FastMath.cosh(x);
1182 double ref = cosh(field.newDfp(x)).toDouble();
1183 double err = (tst - ref) / ref;
1184
1185 if (err != 0) {
1186 double ulp = Math.abs(ref - Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
1187 double errulp = field.newDfp(tst).subtract(cosh(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
1188
1189 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
1190 }
1191 }
1192
1193 assertTrue(maxerrulp < MAX_ERROR_ULP, "cosh() had errors in excess of " + MAX_ERROR_ULP + " ULP");
1194 }
1195
1196 @Test
1197 void testTanhAccuracy() {
1198 double maxerrulp = 0.0;
1199
1200 for (int i=0; i<10000; i++) {
1201 double x = ((generator.nextDouble() * 16.0) - 8.0) * generator.nextDouble();
1202
1203 double tst = FastMath.tanh(x);
1204 double ref = tanh(field.newDfp(x)).toDouble();
1205 double err = (tst - ref) / ref;
1206
1207 if (err != 0) {
1208 double ulp = Math.abs(ref - Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
1209 double errulp = field.newDfp(tst).subtract(tanh(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
1210
1211 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
1212 }
1213 }
1214
1215 assertTrue(maxerrulp < MAX_ERROR_ULP, "tanh() had errors in excess of " + MAX_ERROR_ULP + " ULP");
1216 }
1217
1218 @Test
1219 void testCbrtAccuracy() {
1220 double maxerrulp = 0.0;
1221
1222 for (int i=0; i<10000; i++) {
1223 double x = ((generator.nextDouble() * 200.0) - 100.0) * generator.nextDouble();
1224
1225 double tst = FastMath.cbrt(x);
1226 double ref = cbrt(field.newDfp(x)).toDouble();
1227 double err = (tst - ref) / ref;
1228
1229 if (err != 0) {
1230 double ulp = Math.abs(ref - Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
1231 double errulp = field.newDfp(tst).subtract(cbrt(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
1232
1233 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
1234 }
1235 }
1236
1237 assertTrue(maxerrulp < MAX_ERROR_ULP, "cbrt() had errors in excess of " + MAX_ERROR_ULP + " ULP");
1238 }
1239
1240 private Dfp cbrt(Dfp x) {
1241 boolean negative=false;
1242
1243 if (x.lessThan(field.getZero())) {
1244 negative = true;
1245 x = x.negate();
1246 }
1247
1248 Dfp y = DfpMath.pow(x, field.getOne().divide(3));
1249
1250 if (negative) {
1251 y = y.negate();
1252 }
1253
1254 return y;
1255 }
1256
1257 @Test
1258 void testToDegrees() {
1259 double maxerrulp = 0.0;
1260 for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
1261 double x = generator.nextDouble();
1262 double tst = field.newDfp(x).multiply(180).divide(field.getPi()).toDouble();
1263 double ref = FastMath.toDegrees(x);
1264 double err = (tst - ref) / ref;
1265
1266 if (err != 0) {
1267 double ulp = Math.abs(ref -
1268 Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
1269 double errulp = field.newDfp(tst).subtract(DfpMath.exp(field.newDfp(x)).subtract(field.getOne())).divide(field.newDfp(ulp)).toDouble();
1270
1271
1272 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
1273 }
1274 }
1275 assertTrue(maxerrulp < MAX_ERROR_ULP, "toDegrees() had errors in excess of " + MAX_ERROR_ULP + " ULP");
1276 }
1277
1278 @Test
1279 void testToRadians() {
1280 double maxerrulp = 0.0;
1281 for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
1282 double x = generator.nextDouble();
1283 double tst = field.newDfp(x).multiply(field.getPi()).divide(180).toDouble();
1284 double ref = FastMath.toRadians(x);
1285 double err = (tst - ref) / ref;
1286
1287 if (err != 0) {
1288 double ulp = Math.abs(ref -
1289 Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
1290 double errulp = field.newDfp(tst).subtract(DfpMath.exp(field.newDfp(x)).subtract(field.getOne())).divide(field.newDfp(ulp)).toDouble();
1291
1292
1293 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
1294 }
1295 }
1296
1297 assertTrue(maxerrulp < MAX_ERROR_ULP, "toRadians() had errors in excess of " + MAX_ERROR_ULP + " ULP");
1298 }
1299
1300 @Test
1301 void testNextAfter() {
1302
1303 assertEquals(16.0, FastMath.nextUp(15.999999999999998), 0.0);
1304
1305
1306 assertEquals(-15.999999999999996, FastMath.nextAfter(-15.999999999999998, 34.27555555555555), 0.0);
1307
1308
1309 assertEquals(15.999999999999996, FastMath.nextDown(15.999999999999998), 0.0);
1310
1311
1312 assertEquals(-15.999999999999996, FastMath.nextAfter(-15.999999999999998, 2.142222222222222), 0.0);
1313
1314
1315 assertEquals(8.000000000000002, FastMath.nextAfter(8.0, 34.27555555555555), 0.0);
1316
1317
1318 assertEquals(-7.999999999999999, FastMath.nextAfter(-8.0, 34.27555555555555), 0.0);
1319
1320
1321 assertEquals(7.999999999999999, FastMath.nextAfter(8.0, 2.142222222222222), 0.0);
1322
1323
1324 assertEquals(-7.999999999999999, FastMath.nextAfter(-8.0, 2.142222222222222), 0.0);
1325
1326
1327 assertEquals(2.308922399667661E-4, FastMath.nextAfter(2.3089223996676606E-4, 2.308922399667661E-4), 0.0);
1328
1329
1330 assertEquals(2.3089223996676606E-4, FastMath.nextAfter(2.3089223996676606E-4, 2.3089223996676606E-4), 0.0);
1331
1332
1333 assertEquals(2.3089223996676603E-4, FastMath.nextAfter(2.3089223996676606E-4, 2.3089223996676603E-4), 0.0);
1334
1335
1336 assertEquals(2.3089223996676603E-4, FastMath.nextAfter(2.3089223996676606E-4, -2.308922399667661E-4), 0.0);
1337
1338
1339 assertEquals(2.3089223996676603E-4, FastMath.nextAfter(2.3089223996676606E-4, -2.3089223996676606E-4), 0.0);
1340
1341
1342 assertEquals(2.3089223996676603E-4, FastMath.nextAfter(2.3089223996676606E-4, -2.3089223996676603E-4), 0.0);
1343
1344
1345 assertEquals(-2.3089223996676603E-4, FastMath.nextAfter(-2.3089223996676606E-4, 2.308922399667661E-4), 0.0);
1346
1347
1348 assertEquals(-2.3089223996676603E-4, FastMath.nextAfter(-2.3089223996676606E-4, 2.3089223996676606E-4), 0.0);
1349
1350
1351 assertEquals(-2.3089223996676603E-4, FastMath.nextAfter(-2.3089223996676606E-4, 2.3089223996676603E-4), 0.0);
1352
1353
1354 assertEquals(-2.308922399667661E-4, FastMath.nextAfter(-2.3089223996676606E-4, -2.308922399667661E-4), 0.0);
1355
1356
1357 assertEquals(-2.3089223996676606E-4, FastMath.nextAfter(-2.3089223996676606E-4, -2.3089223996676606E-4), 0.0);
1358
1359
1360 assertEquals(-2.3089223996676603E-4, FastMath.nextAfter(-2.3089223996676606E-4, -2.3089223996676603E-4), 0.0);
1361
1362 }
1363
1364 @Test
1365 void testDoubleNextAfterSpecialCases() {
1366 assertEquals(-Double.MAX_VALUE,FastMath.nextAfter(Double.NEGATIVE_INFINITY, 0D), 0D);
1367 assertEquals(Double.MAX_VALUE,FastMath.nextAfter(Double.POSITIVE_INFINITY, 0D), 0D);
1368 assertEquals(Double.NaN,FastMath.nextAfter(Double.NaN, 0D), 0D);
1369 assertEquals(Double.POSITIVE_INFINITY,FastMath.nextAfter(Double.MAX_VALUE, Double.POSITIVE_INFINITY), 0D);
1370 assertEquals(Double.NEGATIVE_INFINITY,FastMath.nextAfter(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY), 0D);
1371 assertEquals(Double.MIN_VALUE, FastMath.nextAfter(0D, 1D), 0D);
1372 assertEquals(-Double.MIN_VALUE, FastMath.nextAfter(0D, -1D), 0D);
1373 assertEquals(0D, FastMath.nextAfter(Double.MIN_VALUE, -1), 0D);
1374 assertEquals(0D, FastMath.nextAfter(-Double.MIN_VALUE, 1), 0D);
1375 }
1376
1377 @Test
1378 void testFloatNextAfterSpecialCases() {
1379 assertEquals(-Float.MAX_VALUE,FastMath.nextAfter(Float.NEGATIVE_INFINITY, 0F), 0F);
1380 assertEquals(Float.MAX_VALUE,FastMath.nextAfter(Float.POSITIVE_INFINITY, 0F), 0F);
1381 assertEquals(Float.NaN,FastMath.nextAfter(Float.NaN, 0F), 0F);
1382 assertEquals(Float.POSITIVE_INFINITY,FastMath.nextUp(Float.MAX_VALUE), 0F);
1383 assertEquals(Float.NEGATIVE_INFINITY,FastMath.nextDown(-Float.MAX_VALUE), 0F);
1384 assertEquals(Float.MIN_VALUE, FastMath.nextAfter(0F, 1F), 0F);
1385 assertEquals(-Float.MIN_VALUE, FastMath.nextAfter(0F, -1F), 0F);
1386 assertEquals(0F, FastMath.nextAfter(Float.MIN_VALUE, -1F), 0F);
1387 assertEquals(0F, FastMath.nextAfter(-Float.MIN_VALUE, 1F), 0F);
1388 }
1389
1390 @Test
1391 void testClampInt() {
1392 assertEquals( 3, FastMath.clamp(-17, 3, 4));
1393 assertEquals( 4, FastMath.clamp(+17, 3, 4));
1394 assertEquals( 0, FastMath.clamp(-17, 0, 4));
1395 assertEquals( 0, FastMath.clamp(+17, -3, 0));
1396 }
1397
1398 @Test
1399 void testClampLong() {
1400 assertEquals(3L, FastMath.clamp(-17L, 3L, 4L));
1401 assertEquals(4L, FastMath.clamp(+17L, 3L, 4L));
1402 assertEquals(0L, FastMath.clamp(-17L, 0L, 4L));
1403 assertEquals(0L, FastMath.clamp(+17L, -3L, 0L));
1404 }
1405
1406 @Test
1407 void testClampLongInt() {
1408 assertEquals( 3, FastMath.clamp(-17L, 3, 4));
1409 assertEquals( 4, FastMath.clamp(+17L, 3, 4));
1410 assertEquals( 0, FastMath.clamp(-17L, 0, 4));
1411 assertEquals( 0, FastMath.clamp(+17L, -3, 0));
1412 }
1413
1414 @Test
1415 void testClampFloat() {
1416 assertEquals( 3.0f, FastMath.clamp(-17.0f, 3.0f, 4.0f), 1.0e-15f);
1417 assertEquals( 4.0f, FastMath.clamp(+17.0f, 3.0f, 4.0f), 1.0e-15f);
1418 assertEquals( 0.0f, FastMath.clamp(-17.0f, -0.0f, 4.0f), 1.0e-15f);
1419 assertEquals(-1.0f, FastMath.copySign(1.0f, FastMath.clamp(-17.0f, -0.0f, 4.0f)), 1.0e-15f);
1420 assertEquals( 0.0f, FastMath.clamp(-17.0f, +0.0f, 4.0f), 1.0e-15f);
1421 assertEquals(+1.0f, FastMath.copySign(1.0f, FastMath.clamp(-17.0f, +0.0f, 4.0f)), 1.0e-15f);
1422 assertEquals( 0.0f, FastMath.clamp(+17.0f, -3.0f, -0.0f), 1.0e-15f);
1423 assertEquals(-1.0f, FastMath.copySign(1.0f, FastMath.clamp(+17.0f, -3.0f, -0.0f)), 1.0e-15f);
1424 assertEquals( 0.0f, FastMath.clamp(+17.0f, -3.0f, +0.0f), 1.0e-15f);
1425 assertEquals(+1.0f, FastMath.copySign(1.0f, FastMath.clamp(+17.0f, -3.0f, +0.0f)), 1.0e-15f);
1426 }
1427
1428 @Test
1429 void testClampDouble() {
1430 assertEquals( 3.0, FastMath.clamp(-17.0, 3.0, 4.0), 1.0e-15);
1431 assertEquals( 4.0, FastMath.clamp(+17.0, 3.0, 4.0), 1.0e-15);
1432 assertEquals( 0.0, FastMath.clamp(-17.0, -0.0, 4.0), 1.0e-15);
1433 assertEquals(-1.0, FastMath.copySign(1.0, FastMath.clamp(-17.0, -0.0, 4.0)), 1.0e-15);
1434 assertEquals( 0.0, FastMath.clamp(-17.0, +0.0, 4.0), 1.0e-15);
1435 assertEquals(+1.0, FastMath.copySign(1.0, FastMath.clamp(-17.0, +0.0, 4.0)), 1.0e-15);
1436 assertEquals( 0.0, FastMath.clamp(+17.0, -3.0, -0.0), 1.0e-15);
1437 assertEquals(-1.0, FastMath.copySign(1.0, FastMath.clamp(+17.0, -3.0, -0.0)), 1.0e-15);
1438 assertEquals( 0.0, FastMath.clamp(+17.0, -3.0, +0.0), 1.0e-15);
1439 assertEquals(+1.0, FastMath.copySign(1.0, FastMath.clamp(+17.0, -3.0, +0.0)), 1.0e-15);
1440 }
1441
1442 @Test
1443 void testDoubleScalbSpecialCases() {
1444 assertEquals(0d, FastMath.scalb(0d, 1100), 0d);
1445 assertEquals(Double.POSITIVE_INFINITY, FastMath.scalb(Double.POSITIVE_INFINITY, 1100), 0);
1446 assertEquals(Double.NEGATIVE_INFINITY, FastMath.scalb(Double.NEGATIVE_INFINITY, 1100), 0);
1447 assertTrue(Double.isNaN(FastMath.scalb(Double.NaN, 1100)));
1448 assertEquals(2.5269841324701218E-175, FastMath.scalb(2.2250738585072014E-308, 442), 0D);
1449 assertEquals(1.307993905256674E297, FastMath.scalb(1.1102230246251565E-16, 1040), 0D);
1450 assertEquals(7.2520887996488946E-217, FastMath.scalb(Double.MIN_VALUE, 356), 0D);
1451 assertEquals(8.98846567431158E307, FastMath.scalb(Double.MIN_VALUE, 2097), 0D);
1452 assertEquals(Double.POSITIVE_INFINITY, FastMath.scalb(Double.MIN_VALUE, 2098), 0D);
1453 assertEquals(1.1125369292536007E-308, FastMath.scalb(2.225073858507201E-308, -1), 0D);
1454 assertEquals(1.0E-323, FastMath.scalb(Double.MAX_VALUE, -2097), 0D);
1455 assertEquals(Double.MIN_VALUE, FastMath.scalb(Double.MAX_VALUE, -2098), 0D);
1456 assertEquals(0, FastMath.scalb(Double.MAX_VALUE, -2099), 0D);
1457 assertEquals(Double.POSITIVE_INFINITY, FastMath.scalb(Double.POSITIVE_INFINITY, -1000000), 0D);
1458 assertEquals(Double.POSITIVE_INFINITY, FastMath.scalb( 1.1102230246251565E-16, 1078), 0D);
1459 assertEquals(Double.NEGATIVE_INFINITY, FastMath.scalb(-1.1102230246251565E-16, 1078), 0D);
1460 assertEquals(Double.NEGATIVE_INFINITY, FastMath.scalb(-1.1102230246251565E-16, 1079), 0D);
1461 assertEquals(Double.NEGATIVE_INFINITY, FastMath.scalb(-2.2250738585072014E-308, 2047), 0D);
1462 assertEquals(Double.NEGATIVE_INFINITY, FastMath.scalb(-2.2250738585072014E-308, 2048), 0D);
1463 assertEquals(Double.NEGATIVE_INFINITY, FastMath.scalb(-1.7976931348623157E308, 2147483647), 0D);
1464 assertEquals(Double.POSITIVE_INFINITY, FastMath.scalb( 1.7976931348623157E308, 2147483647), 0D);
1465 assertEquals(Double.NEGATIVE_INFINITY, FastMath.scalb(-1.1102230246251565E-16, 2147483647), 0D);
1466 assertEquals(Double.POSITIVE_INFINITY, FastMath.scalb( 1.1102230246251565E-16, 2147483647), 0D);
1467 assertEquals(Double.NEGATIVE_INFINITY, FastMath.scalb(-2.2250738585072014E-308, 2147483647), 0D);
1468 assertEquals(Double.POSITIVE_INFINITY, FastMath.scalb( 2.2250738585072014E-308, 2147483647), 0D);
1469 assertEquals(0L, Double.doubleToRawLongBits(FastMath.scalb(4.0, -2099)));
1470 assertEquals(1L << 63, Double.doubleToRawLongBits(FastMath.scalb(-4.0, -2099)));
1471 assertEquals(0L, Double.doubleToRawLongBits(FastMath.scalb(0.0, 12)));
1472 assertEquals(1L << 63, Double.doubleToRawLongBits(FastMath.scalb(-0.0, 12)));
1473 assertTrue(Double.isNaN(FastMath.scalb(Double.NaN, 12)));
1474 assertEquals(Double.POSITIVE_INFINITY, FastMath.scalb(Double.POSITIVE_INFINITY, 12), 1.0);
1475 assertEquals(Double.NEGATIVE_INFINITY, FastMath.scalb(Double.NEGATIVE_INFINITY, 12), 1.0);
1476 assertEquals(0x1.2345p-1022, FastMath.scalb(0x1.2345p28, -1050), 0x1.0p-1070);
1477 assertEquals(0L, Double.doubleToRawLongBits(FastMath.scalb(0x1.2345p28, -1104)));
1478 assertEquals(1L << 63, Double.doubleToRawLongBits(FastMath.scalb(-0x1.2345p28, -1104)));
1479 assertEquals(0x1.2345p27, FastMath.scalb(0x1.2345p-1023, 1050), 0x1.0p-25);
1480 assertEquals(Double.POSITIVE_INFINITY, FastMath.scalb( 0x1.2345p-1023, 2047), 1.0);
1481 assertEquals(Double.NEGATIVE_INFINITY, FastMath.scalb(-0x1.2345p-1023, 2047), 1.0);
1482 assertEquals(0x1p-1057, FastMath.scalb(0x1.0p23, -1080), 0x1.0p-1073);
1483 }
1484
1485 @Test
1486 void testFloatScalbSpecialCases() {
1487 assertEquals(0f, FastMath.scalb(0f, 130), 0F);
1488 assertEquals(Float.POSITIVE_INFINITY, FastMath.scalb(Float.POSITIVE_INFINITY, 130), 0F);
1489 assertEquals(Float.NEGATIVE_INFINITY, FastMath.scalb(Float.NEGATIVE_INFINITY, 130), 0F);
1490 assertTrue(Float.isNaN(FastMath.scalb(Float.NaN, 130)));
1491 assertEquals(0f, FastMath.scalb(Float.MIN_VALUE, -30), 0F);
1492 assertEquals(2 * Float.MIN_VALUE, FastMath.scalb(Float.MIN_VALUE, 1), 0F);
1493 assertEquals(7.555786e22f, FastMath.scalb(Float.MAX_VALUE, -52), 0F);
1494 assertEquals(1.7014118e38f, FastMath.scalb(Float.MIN_VALUE, 276), 0F);
1495 assertEquals(Float.POSITIVE_INFINITY, FastMath.scalb(Float.MIN_VALUE, 277), 0F);
1496 assertEquals(5.8774718e-39f, FastMath.scalb(1.1754944e-38f, -1), 0F);
1497 assertEquals(2 * Float.MIN_VALUE, FastMath.scalb(Float.MAX_VALUE, -276), 0F);
1498 assertEquals(Float.MIN_VALUE, FastMath.scalb(Float.MAX_VALUE, -277), 0F);
1499 assertEquals(0, FastMath.scalb(Float.MAX_VALUE, -278), 0F);
1500 assertEquals(Float.POSITIVE_INFINITY, FastMath.scalb(Float.POSITIVE_INFINITY, -1000000), 0F);
1501 assertEquals(-3.13994498e38f, FastMath.scalb(-1.1e-7f, 151), 0F);
1502 assertEquals(Float.NEGATIVE_INFINITY, FastMath.scalb(-1.1e-7f, 152), 0F);
1503 assertEquals(Float.POSITIVE_INFINITY, FastMath.scalb(3.4028235E38f, 2147483647), 0F);
1504 assertEquals(Float.NEGATIVE_INFINITY, FastMath.scalb(-3.4028235E38f, 2147483647), 0F);
1505 assertEquals(0, Float.floatToRawIntBits(FastMath.scalb(4.0f, -278)));
1506 assertEquals(1 << 31, Float.floatToRawIntBits(FastMath.scalb(-4.0f, -278)));
1507 assertEquals(0, Float.floatToRawIntBits(FastMath.scalb(0.0f, 12)));
1508 assertEquals(1 << 31, Float.floatToRawIntBits(FastMath.scalb(-0.0f, 12)));
1509 assertTrue(Float.isNaN(FastMath.scalb(Float.NaN, 12)));
1510 assertEquals(Float.POSITIVE_INFINITY, FastMath.scalb(Float.POSITIVE_INFINITY, 12), 1.0);
1511 assertEquals(Float.NEGATIVE_INFINITY, FastMath.scalb(Float.NEGATIVE_INFINITY, 12), 1.0);
1512 assertEquals(0x1.2345p-106f, FastMath.scalb(0x1.2345p28f, -134), 0x1.0p-130f);
1513 assertEquals(0, Float.floatToRawIntBits(FastMath.scalb( 0x1.2345p28f, -179)));
1514 assertEquals(1 << 31, Float.floatToRawIntBits(FastMath.scalb(-0x1.2345p28f, -179)));
1515 assertEquals(0x1.2345p127f, FastMath.scalb(0x1.2345p-123f, 250), 0x1.0p3f);
1516 assertEquals(Float.POSITIVE_INFINITY, FastMath.scalb( 0x1.2345p-127f, 255), 1.0f);
1517 assertEquals(Float.NEGATIVE_INFINITY, FastMath.scalb(-0x1.2345p-127f, 255), 1.0f);
1518 assertEquals(Float.POSITIVE_INFINITY, FastMath.scalb( 0x1.2345p-123f, 252), 1.0f);
1519 assertEquals(Float.NEGATIVE_INFINITY, FastMath.scalb(-0x1.2345p-123f, 252), 1.0f);
1520 assertEquals(0x1p-130f, FastMath.scalb(0x1.0p23f, -153), 0x1.0p-148f);
1521 }
1522
1523 private boolean compareClassMethods(Class<?> class1, Class<?> class2){
1524 boolean allfound = true;
1525 for(Method method1 : class1.getDeclaredMethods()){
1526 if (Modifier.isPublic(method1.getModifiers())){
1527 Type []params = method1.getGenericParameterTypes();
1528 try {
1529 class2.getDeclaredMethod(method1.getName(), (Class[]) params);
1530 } catch (NoSuchMethodException e) {
1531 allfound = false;
1532 System.out.println(class2.getSimpleName()+" does not implement: "+method1);
1533 }
1534 }
1535 }
1536 return allfound;
1537 }
1538
1539 @Test
1540 void checkMissingFastMathClasses() {
1541 boolean ok = compareClassMethods(StrictMath.class, FastMath.class);
1542 assertTrue(ok, "FastMath should implement all StrictMath methods");
1543 }
1544
1545 @Test
1546 void testUlpDouble() {
1547 assertTrue(Double.isNaN(FastMath.ulp(Double.NaN)));
1548 assertEquals(Double.POSITIVE_INFINITY, FastMath.ulp(Double.POSITIVE_INFINITY), 1.0);
1549 assertEquals(Double.POSITIVE_INFINITY, FastMath.ulp(Double.NEGATIVE_INFINITY), 1.0);
1550 assertEquals(0.0, FastMath.ulp(+0.0), Precision.SAFE_MIN);
1551 assertEquals(0.0, FastMath.ulp(-0.0), Precision.SAFE_MIN);
1552 assertEquals(0x1.0p-53, FastMath.ulp(0x1.fffffffffffffp-1), 0x1.0p-100);
1553 assertEquals(0x1.0p-52, FastMath.ulp(+1.0), 0x1.0p-100);
1554 assertEquals(0x1.0p-52, FastMath.ulp(-1.0), 0x1.0p-100);
1555 }
1556
1557 @Test
1558 void testUlpFloat() {
1559 assertTrue(Float.isNaN(FastMath.ulp(Float.NaN)));
1560 assertEquals(Float.POSITIVE_INFINITY, FastMath.ulp(Float.POSITIVE_INFINITY), 1.0f);
1561 assertEquals(Float.POSITIVE_INFINITY, FastMath.ulp(Float.NEGATIVE_INFINITY), 1.0f);
1562 assertEquals(0.0f, FastMath.ulp(+0.0f), 1.0e-8f);
1563 assertEquals(0.0f, FastMath.ulp(-0.0f), 1.0e-8f);
1564 assertEquals(0x1.0p-24f, FastMath.ulp(0x1.fffffcp-1f), 0x1.0p-50f);
1565 assertEquals(0x1.0p-23f, FastMath.ulp(+1.0f), 0x1.0p-50f);
1566 assertEquals(0x1.0p-23f, FastMath.ulp(-1.0f), 0x1.0p-50f);
1567 }
1568
1569 @Test
1570 void testCopySignDouble() {
1571
1572 assertEquals(-2.0, FastMath.copySign(-2.0, -5.0), 1.0e-10);
1573 assertEquals(-2.0, FastMath.copySign(+2.0, -5.0), 1.0e-10);
1574 assertEquals(+2.0, FastMath.copySign(-2.0, +5.0), 1.0e-10);
1575 assertEquals(+2.0, FastMath.copySign(+2.0, +5.0), 1.0e-10);
1576 assertEquals(-2.0, FastMath.copySign(-2.0, Double.NEGATIVE_INFINITY), 1.0e-10);
1577 assertEquals(-2.0, FastMath.copySign(+2.0, Double.NEGATIVE_INFINITY), 1.0e-10);
1578 assertEquals(+2.0, FastMath.copySign(-2.0, Double.POSITIVE_INFINITY), 1.0e-10);
1579 assertEquals(+2.0, FastMath.copySign(+2.0, Double.POSITIVE_INFINITY), 1.0e-10);
1580 assertEquals(+2.0, FastMath.copySign(-2.0, Double.NaN), 1.0e-10);
1581 assertEquals(+2.0, FastMath.copySign(-2.0, Double.NaN), 1.0e-10);
1582 assertEquals(+2.0, FastMath.copySign(-2.0, -Double.NaN), 1.0e-10);
1583 assertEquals(+2.0, FastMath.copySign(-2.0, -Double.NaN), 1.0e-10);
1584 assertEquals(-2.0, FastMath.copySign(-2.0, -0.0), 1.0e-10);
1585 assertEquals(-2.0, FastMath.copySign(+2.0, -0.0), 1.0e-10);
1586 assertEquals(+2.0, FastMath.copySign(-2.0, +0.0), 1.0e-10);
1587 assertEquals(+2.0, FastMath.copySign(+2.0, +0.0), 1.0e-10);
1588
1589 assertEquals(-3.0, FastMath.copySign(+3.0, FastMath.copySign(-0.0, -5.0)), 1.0e-10);
1590 assertEquals(-3.0, FastMath.copySign(+3.0, FastMath.copySign(+0.0, -5.0)), 1.0e-10);
1591 assertEquals(+3.0, FastMath.copySign(+3.0, FastMath.copySign(-0.0, +5.0)), 1.0e-10);
1592 assertEquals(+3.0, FastMath.copySign(+3.0, FastMath.copySign(+0.0, +5.0)), 1.0e-10);
1593 assertEquals(-3.0, FastMath.copySign(+3.0, FastMath.copySign(-0.0, Double.NEGATIVE_INFINITY)), 1.0e-10);
1594 assertEquals(-3.0, FastMath.copySign(+3.0, FastMath.copySign(+0.0, Double.NEGATIVE_INFINITY)), 1.0e-10);
1595 assertEquals(+3.0, FastMath.copySign(+3.0, FastMath.copySign(-0.0, Double.POSITIVE_INFINITY)), 1.0e-10);
1596 assertEquals(+3.0, FastMath.copySign(+3.0, FastMath.copySign(+0.0, Double.POSITIVE_INFINITY)), 1.0e-10);
1597 assertEquals(+3.0, FastMath.copySign(+3.0, FastMath.copySign(-0.0, Double.NaN)), 1.0e-10);
1598 assertEquals(+3.0, FastMath.copySign(+3.0, FastMath.copySign(-0.0, Double.NaN)), 1.0e-10);
1599 assertEquals(+3.0, FastMath.copySign(+3.0, FastMath.copySign(-0.0, -Double.NaN)), 1.0e-10);
1600 assertEquals(+3.0, FastMath.copySign(+3.0, FastMath.copySign(-0.0, -Double.NaN)), 1.0e-10);
1601 assertEquals(-3.0, FastMath.copySign(+3.0, FastMath.copySign(-0.0, -0.0)), 1.0e-10);
1602 assertEquals(-3.0, FastMath.copySign(+3.0, FastMath.copySign(+0.0, -0.0)), 1.0e-10);
1603 assertEquals(+3.0, FastMath.copySign(+3.0, FastMath.copySign(-0.0, +0.0)), 1.0e-10);
1604 assertEquals(+3.0, FastMath.copySign(+3.0, FastMath.copySign(+0.0, +0.0)), 1.0e-10);
1605
1606 }
1607
1608 @Test
1609 void testCopySignFloat() {
1610
1611 assertEquals(-2.0f, FastMath.copySign(-2.0f, -5.0f), 1.0e-10f);
1612 assertEquals(-2.0f, FastMath.copySign(+2.0f, -5.0f), 1.0e-10f);
1613 assertEquals(+2.0f, FastMath.copySign(-2.0f, +5.0f), 1.0e-10f);
1614 assertEquals(+2.0f, FastMath.copySign(+2.0f, +5.0f), 1.0e-10f);
1615 assertEquals(-2.0f, FastMath.copySign(-2.0f, Float.NEGATIVE_INFINITY), 1.0e-10f);
1616 assertEquals(-2.0f, FastMath.copySign(+2.0f, Float.NEGATIVE_INFINITY), 1.0e-10f);
1617 assertEquals(+2.0f, FastMath.copySign(-2.0f, Float.POSITIVE_INFINITY), 1.0e-10f);
1618 assertEquals(+2.0f, FastMath.copySign(+2.0f, Float.POSITIVE_INFINITY), 1.0e-10f);
1619 assertEquals(+2.0f, FastMath.copySign(-2.0f, Float.NaN), 1.0e-10f);
1620 assertEquals(+2.0f, FastMath.copySign(-2.0f, Float.NaN), 1.0e-10f);
1621 assertEquals(+2.0f, FastMath.copySign(-2.0f, -Float.NaN), 1.0e-10f);
1622 assertEquals(+2.0f, FastMath.copySign(-2.0f, -Float.NaN), 1.0e-10f);
1623 assertEquals(-2.0f, FastMath.copySign(-2.0f, -0.0f), 1.0e-10f);
1624 assertEquals(-2.0f, FastMath.copySign(+2.0f, -0.0f), 1.0e-10f);
1625 assertEquals(+2.0f, FastMath.copySign(-2.0f, +0.0f), 1.0e-10f);
1626 assertEquals(+2.0f, FastMath.copySign(+2.0f, +0.0f), 1.0e-10f);
1627
1628 assertEquals(-3.0f, FastMath.copySign(+3.0f, FastMath.copySign(-0.0f, -5.0f)), 1.0e-10f);
1629 assertEquals(-3.0f, FastMath.copySign(+3.0f, FastMath.copySign(+0.0f, -5.0f)), 1.0e-10f);
1630 assertEquals(+3.0f, FastMath.copySign(+3.0f, FastMath.copySign(-0.0f, +5.0f)), 1.0e-10f);
1631 assertEquals(+3.0f, FastMath.copySign(+3.0f, FastMath.copySign(+0.0f, +5.0f)), 1.0e-10f);
1632 assertEquals(-3.0f, FastMath.copySign(+3.0f, FastMath.copySign(-0.0f, Float.NEGATIVE_INFINITY)), 1.0e-10f);
1633 assertEquals(-3.0f, FastMath.copySign(+3.0f, FastMath.copySign(+0.0f, Float.NEGATIVE_INFINITY)), 1.0e-10f);
1634 assertEquals(+3.0f, FastMath.copySign(+3.0f, FastMath.copySign(-0.0f, Float.POSITIVE_INFINITY)), 1.0e-10f);
1635 assertEquals(+3.0f, FastMath.copySign(+3.0f, FastMath.copySign(+0.0f, Float.POSITIVE_INFINITY)), 1.0e-10f);
1636 assertEquals(+3.0f, FastMath.copySign(+3.0f, FastMath.copySign(-0.0f, Float.NaN)), 1.0e-10f);
1637 assertEquals(+3.0f, FastMath.copySign(+3.0f, FastMath.copySign(-0.0f, Float.NaN)), 1.0e-10f);
1638 assertEquals(+3.0f, FastMath.copySign(+3.0f, FastMath.copySign(-0.0f, -Float.NaN)), 1.0e-10f);
1639 assertEquals(+3.0f, FastMath.copySign(+3.0f, FastMath.copySign(-0.0f, -Float.NaN)), 1.0e-10f);
1640 assertEquals(-3.0f, FastMath.copySign(+3.0f, FastMath.copySign(-0.0f, -0.0f)), 1.0e-10f);
1641 assertEquals(-3.0f, FastMath.copySign(+3.0f, FastMath.copySign(+0.0f, -0.0f)), 1.0e-10f);
1642 assertEquals(+3.0f, FastMath.copySign(+3.0f, FastMath.copySign(-0.0f, +0.0f)), 1.0e-10f);
1643 assertEquals(+3.0f, FastMath.copySign(+3.0f, FastMath.copySign(+0.0f, +0.0f)), 1.0e-10f);
1644
1645 }
1646
1647 @Test
1648 void testSignumDouble() {
1649 final double delta = 0.0;
1650 assertEquals(1.0, FastMath.signum(2.0), delta);
1651 assertEquals(0.0, FastMath.signum(0.0), delta);
1652 assertEquals(-1.0, FastMath.signum(-2.0), delta);
1653 UnitTestUtils.customAssertSame(-0. / 0., FastMath.signum(Double.NaN));
1654 }
1655
1656 @Test
1657 void testSignumFloat() {
1658 final float delta = 0.0F;
1659 assertEquals(1.0F, FastMath.signum(2.0F), delta);
1660 assertEquals(0.0F, FastMath.signum(0.0F), delta);
1661 assertEquals(-1.0F, FastMath.signum(-2.0F), delta);
1662 UnitTestUtils.customAssertSame(Float.NaN, FastMath.signum(Float.NaN));
1663 }
1664
1665 @Test
1666 void testLogWithBase() {
1667 assertEquals(2.0, FastMath.log(2, 4), 0);
1668 assertEquals(3.0, FastMath.log(2, 8), 0);
1669 assertTrue(Double.isNaN(FastMath.log(-1, 1)));
1670 assertTrue(Double.isNaN(FastMath.log(1, -1)));
1671 assertTrue(Double.isNaN(FastMath.log(0, 0)));
1672 assertEquals(0, FastMath.log(0, 10), 0);
1673 assertEquals(Double.NEGATIVE_INFINITY, FastMath.log(10, 0), 0);
1674 }
1675
1676 @Test
1677 void testIndicatorDouble() {
1678 double delta = 0.0;
1679 assertEquals(1.0, FastMath.copySign(1d, 2.0), delta);
1680 assertEquals(1.0, FastMath.copySign(1d, 0.0), delta);
1681 assertEquals(-1.0, FastMath.copySign(1d, -0.0), delta);
1682 assertEquals(1.0, FastMath.copySign(1d, Double.POSITIVE_INFINITY), delta);
1683 assertEquals(-1.0, FastMath.copySign(1d, Double.NEGATIVE_INFINITY), delta);
1684 assertEquals(1.0, FastMath.copySign(1d, Double.NaN), delta);
1685 assertEquals(-1.0, FastMath.copySign(1d, -2.0), delta);
1686 }
1687
1688 @Test
1689 void testIndicatorFloat() {
1690 float delta = 0.0F;
1691 assertEquals(1.0F, FastMath.copySign(1d, 2.0F), delta);
1692 assertEquals(1.0F, FastMath.copySign(1d, 0.0F), delta);
1693 assertEquals(-1.0F, FastMath.copySign(1d, -0.0F), delta);
1694 assertEquals(1.0F, FastMath.copySign(1d, Float.POSITIVE_INFINITY), delta);
1695 assertEquals(-1.0F, FastMath.copySign(1d, Float.NEGATIVE_INFINITY), delta);
1696 assertEquals(1.0F, FastMath.copySign(1d, Float.NaN), delta);
1697 assertEquals(-1.0F, FastMath.copySign(1d, -2.0F), delta);
1698 }
1699
1700 @Test
1701 void testIntPow() {
1702 final int maxExp = 300;
1703 DfpField field = new DfpField(40);
1704 final double base = 1.23456789;
1705 Dfp baseDfp = field.newDfp(base);
1706 Dfp dfpPower = field.getOne();
1707 for (int i = 0; i < maxExp; i++) {
1708 assertEquals(dfpPower.toDouble(), FastMath.pow(base, i),
1709 0.6 * FastMath.ulp(dfpPower.toDouble()),
1710 "exp=" + i);
1711 dfpPower = dfpPower.multiply(baseDfp);
1712 }
1713 }
1714
1715 @Test
1716 void testIntPowHuge() {
1717 assertTrue(Double.isInfinite(FastMath.pow(FastMath.scalb(1.0, 500), 4)));
1718 }
1719
1720
1721 @Test
1722 @Timeout(value = 5000L, unit = TimeUnit.MILLISECONDS)
1723 void testIntPowLongMinValue() {
1724 assertEquals(1.0, FastMath.pow(1.0, Long.MIN_VALUE), 1.0);
1725 }
1726
1727 @Test
1728 @Timeout(value = 5000L, unit = TimeUnit.MILLISECONDS)
1729 void testIntPowSpecialCases() {
1730 final double EXACT = 1.0;
1731 final double[] DOUBLES = new double[]
1732 {
1733 Double.NEGATIVE_INFINITY, -0.0, Double.NaN, 0.0, Double.POSITIVE_INFINITY,
1734 Long.MIN_VALUE, Integer.MIN_VALUE, Short.MIN_VALUE, Byte.MIN_VALUE,
1735 -(double)Long.MIN_VALUE, -(double)Integer.MIN_VALUE, -(double)Short.MIN_VALUE, -(double)Byte.MIN_VALUE,
1736 Byte.MAX_VALUE, Short.MAX_VALUE, Integer.MAX_VALUE, Long.MAX_VALUE,
1737 -Byte.MAX_VALUE, -Short.MAX_VALUE, -Integer.MAX_VALUE, -Long.MAX_VALUE,
1738 Float.MAX_VALUE, Double.MAX_VALUE, Double.MIN_VALUE, Float.MIN_VALUE,
1739 -Float.MAX_VALUE, -Double.MAX_VALUE, -Double.MIN_VALUE, -Float.MIN_VALUE,
1740 0.5, 0.1, 0.2, 0.8, 1.1, 1.2, 1.5, 1.8, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 1.3, 2.2, 2.5, 2.8, 33.0, 33.1, 33.5, 33.8, 10.0, 300.0, 400.0, 500.0,
1741 -0.5, -0.1, -0.2, -0.8, -1.1, -1.2, -1.5, -1.8, -1.0, -2.0, -3.0, -4.0, -5.0, -6.0, -7.0, -8.0, -9.0, -1.3, -2.2, -2.5, -2.8, -33.0, -33.1, -33.5, -33.8, -10.0, -300.0, -400.0, -500.0
1742 };
1743
1744 final long[]
1745 INTS = new long[]{Long.MAX_VALUE, Long.MAX_VALUE - 1, Long.MIN_VALUE, Long.MIN_VALUE + 1, Long.MIN_VALUE + 2, Integer.MAX_VALUE, Integer.MAX_VALUE - 1, Integer.MIN_VALUE, Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2, 0, 1, 2, 3, 5, 8, 10, 20, 100, 300, 500, -1, -2, -3, -5, -8, -10, -20, -100, -300, -500};
1746
1747
1748 for (double d : DOUBLES) {
1749 assertEquals(1.0, FastMath.pow(d, 0L), EXACT);
1750 }
1751
1752 for (double d : DOUBLES) {
1753 assertEquals(d, FastMath.pow(d, 1L), EXACT);
1754 }
1755
1756
1757 for (long i : INTS) {
1758 if (i != 0L) {
1759 assertEquals(Double.NaN, FastMath.pow(Double.NaN, i), EXACT);
1760 }
1761 }
1762
1763
1764 for (double d : DOUBLES) {
1765 if (Math.abs(d) > 1.0) {
1766 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(d, Long.MAX_VALUE - 1L), EXACT);
1767 }
1768 }
1769 for (double d : DOUBLES) {
1770 if (Math.abs(d) < 1.0) {
1771 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(d, Long.MIN_VALUE), EXACT);
1772 }
1773 }
1774
1775 for (double d : DOUBLES) {
1776 if (Math.abs(d) > 1.0) {
1777 assertTrue(Double.isInfinite(FastMath.pow(d, Long.MAX_VALUE)));
1778 }
1779 }
1780 for (double d : DOUBLES) {
1781 if (Math.abs(d) < 1.0) {
1782 assertTrue(Double.isInfinite(FastMath.pow(d, Long.MIN_VALUE + 1L)));
1783 }
1784 }
1785
1786
1787 for (double d : DOUBLES) {
1788 if (Math.abs(d) > 1.0) {
1789 assertEquals(0.0, FastMath.pow(d, Long.MIN_VALUE), EXACT);
1790 }
1791 }
1792 for (double d : DOUBLES) {
1793 if (Math.abs(d) < 1.0) {
1794 assertEquals(0.0, FastMath.pow(d, Long.MAX_VALUE - 1L), EXACT);
1795 }
1796 }
1797
1798 for (double d : DOUBLES) {
1799 if (Math.abs(d) > 1.0) {
1800 assertEquals(0.0, FastMath.pow(d, Long.MIN_VALUE + 1L), 0.0);
1801 }
1802 }
1803 for (double d : DOUBLES) {
1804 if (Math.abs(d) < 1.0) {
1805 assertEquals(0.0, FastMath.pow(d, Long.MAX_VALUE), 0.0);
1806 }
1807 }
1808
1809
1810
1811 for (long i : INTS) {
1812 if (i > 0L) {
1813 assertEquals(0.0, FastMath.pow(0.0, i), EXACT);
1814 }
1815 }
1816 for (long i : INTS) {
1817 if (i < 0L) {
1818 assertEquals(0.0, FastMath.pow(Double.POSITIVE_INFINITY, i), EXACT);
1819 }
1820 }
1821
1822
1823 for (long i : INTS) {
1824 if (i < 0L) {
1825 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(0.0, i), EXACT);
1826 }
1827 }
1828 for (long i : INTS) {
1829 if (i > 0L) {
1830 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(Double.POSITIVE_INFINITY, i), EXACT);
1831 }
1832 }
1833
1834
1835 for (long i : INTS) {
1836 if (i > 0L && (i & 1L) == 0L) {
1837 assertEquals(0.0, FastMath.pow(-0.0, i), EXACT);
1838 }
1839 }
1840 for (long i : INTS) {
1841 if (i < 0L && (i & 1L) == 0L) {
1842 assertEquals(0.0, FastMath.pow(Double.NEGATIVE_INFINITY, i), EXACT);
1843 }
1844 }
1845
1846
1847 for (long i : INTS) {
1848 if (i > 0L && (i & 1L) == 1L) {
1849 assertEquals(-0.0, FastMath.pow(-0.0, i), EXACT);
1850 }
1851 }
1852 for (long i : INTS) {
1853 if (i < 0L && (i & 1L) == 1L) {
1854 assertEquals(-0.0, FastMath.pow(Double.NEGATIVE_INFINITY, i), EXACT);
1855 }
1856 }
1857
1858
1859 for (long i : INTS) {
1860 if (i > 0L && (i & 1L) == 0L) {
1861 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(Double.NEGATIVE_INFINITY, i), EXACT);
1862 }
1863 }
1864 for (long i : INTS) {
1865 if (i < 0L && (i & 1L) == 0L) {
1866 assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(-0.0, i), EXACT);
1867 }
1868 }
1869
1870
1871 for (long i : INTS) {
1872 if (i > 0L && (i & 1L) == 1L) {
1873 assertEquals(Double.NEGATIVE_INFINITY, FastMath.pow(Double.NEGATIVE_INFINITY, i), EXACT);
1874 }
1875 }
1876 for (long i : INTS) {
1877 if (i < 0L && (i & 1L) == 1L) {
1878 assertEquals(Double.NEGATIVE_INFINITY, FastMath.pow(-0.0, i), EXACT);
1879 }
1880 }
1881 for (double d : DOUBLES) {
1882
1883 if (d < 0.0 && Math.abs(d) <= Double.MAX_VALUE) {
1884 for (long i : INTS) {
1885
1886 if ((i & 1L) == 0L) assertEquals(FastMath.pow(-d, i), FastMath.pow(d, i), EXACT);
1887
1888 else assertEquals(-FastMath.pow(-d, i), FastMath.pow(d, i), EXACT);
1889
1890 }
1891 }
1892 }
1893
1894
1895 }
1896
1897 @Test
1898 void testIncrementExactInt() {
1899 int[] specialValues = new int[] {
1900 Integer.MIN_VALUE, Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2,
1901 Integer.MAX_VALUE, Integer.MAX_VALUE - 1, Integer.MAX_VALUE - 2,
1902 -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1903 -1 - (Integer.MIN_VALUE / 2), -(Integer.MIN_VALUE / 2), 1 - (Integer.MIN_VALUE / 2),
1904 -1 + (Integer.MAX_VALUE / 2), (Integer.MAX_VALUE / 2), 1 + (Integer.MAX_VALUE / 2),
1905 };
1906 for (int a : specialValues) {
1907 BigInteger bdA = BigInteger.valueOf(a);
1908 BigInteger bdSum = bdA.add(BigInteger.ONE);
1909 if (bdSum.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0 ||
1910 bdSum.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) {
1911 try {
1912 FastMath.incrementExact(a);
1913 fail("an exception should have been thrown");
1914 } catch (MathRuntimeException mae) {
1915
1916 }
1917 } else {
1918 assertEquals(bdSum, BigInteger.valueOf(FastMath.incrementExact(a)));
1919 }
1920 }
1921 }
1922
1923 @Test
1924 void testIncrementExactLong() {
1925 long[] specialValues = new long[] {
1926 Long.MIN_VALUE, Long.MIN_VALUE + 1, Long.MIN_VALUE + 2,
1927 Long.MAX_VALUE, Long.MAX_VALUE - 1, Long.MAX_VALUE - 2,
1928 -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1929 -1 - (Long.MIN_VALUE / 2), -(Long.MIN_VALUE / 2), 1 - (Long.MIN_VALUE / 2),
1930 -1 + (Long.MAX_VALUE / 2), (Long.MAX_VALUE / 2), 1 + (Long.MAX_VALUE / 2),
1931 };
1932 for (long a : specialValues) {
1933 BigInteger bdA = BigInteger.valueOf(a);
1934 BigInteger bdSum = bdA.add(BigInteger.ONE);
1935 if (bdSum.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 0 ||
1936 bdSum.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) {
1937 try {
1938 FastMath.incrementExact(a);
1939 fail("an exception should have been thrown");
1940 } catch (MathRuntimeException mae) {
1941
1942 }
1943 } else {
1944 assertEquals(bdSum, BigInteger.valueOf(FastMath.incrementExact(a)));
1945 }
1946 }
1947 }
1948
1949 @Test
1950 void testDecrementExactInt() {
1951 int[] specialValues = new int[] {
1952 Integer.MIN_VALUE, Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2,
1953 Integer.MAX_VALUE, Integer.MAX_VALUE - 1, Integer.MAX_VALUE - 2,
1954 -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1955 -1 - (Integer.MIN_VALUE / 2), -(Integer.MIN_VALUE / 2), 1 - (Integer.MIN_VALUE / 2),
1956 -1 + (Integer.MAX_VALUE / 2), (Integer.MAX_VALUE / 2), 1 + (Integer.MAX_VALUE / 2),
1957 };
1958 for (int a : specialValues) {
1959 BigInteger bdA = BigInteger.valueOf(a);
1960 BigInteger bdSub = bdA.subtract(BigInteger.ONE);
1961 if (bdSub.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0 ||
1962 bdSub.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) {
1963 try {
1964 FastMath.decrementExact(a);
1965 fail("an exception should have been thrown");
1966 } catch (MathRuntimeException mae) {
1967
1968 }
1969 } else {
1970 assertEquals(bdSub, BigInteger.valueOf(FastMath.decrementExact(a)));
1971 }
1972 }
1973 }
1974
1975 @Test
1976 void testDecrementExactLong() {
1977 long[] specialValues = new long[] {
1978 Long.MIN_VALUE, Long.MIN_VALUE + 1, Long.MIN_VALUE + 2,
1979 Long.MAX_VALUE, Long.MAX_VALUE - 1, Long.MAX_VALUE - 2,
1980 -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1981 -1 - (Long.MIN_VALUE / 2), -(Long.MIN_VALUE / 2), 1 - (Long.MIN_VALUE / 2),
1982 -1 + (Long.MAX_VALUE / 2), (Long.MAX_VALUE / 2), 1 + (Long.MAX_VALUE / 2),
1983 };
1984 for (long a : specialValues) {
1985 BigInteger bdA = BigInteger.valueOf(a);
1986 BigInteger bdSub = bdA.subtract(BigInteger.ONE);
1987 if (bdSub.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 0 ||
1988 bdSub.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) {
1989 try {
1990 FastMath.decrementExact(a);
1991 fail("an exception should have been thrown");
1992 } catch (MathRuntimeException mae) {
1993
1994 }
1995 } else {
1996 assertEquals(bdSub, BigInteger.valueOf(FastMath.decrementExact(a)));
1997 }
1998 }
1999 }
2000
2001 @Test
2002 void testAddExactInt() {
2003 int[] specialValues = new int[] {
2004 Integer.MIN_VALUE, Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2,
2005 Integer.MAX_VALUE, Integer.MAX_VALUE - 1, Integer.MAX_VALUE - 2,
2006 -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
2007 -1 - (Integer.MIN_VALUE / 2), -(Integer.MIN_VALUE / 2), 1 - (Integer.MIN_VALUE / 2),
2008 -1 + (Integer.MAX_VALUE / 2), (Integer.MAX_VALUE / 2), 1 + (Integer.MAX_VALUE / 2),
2009 };
2010 for (int a : specialValues) {
2011 for (int b : specialValues) {
2012 BigInteger bdA = BigInteger.valueOf(a);
2013 BigInteger bdB = BigInteger.valueOf(b);
2014 BigInteger bdSum = bdA.add(bdB);
2015 if (bdSum.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0 ||
2016 bdSum.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) {
2017 try {
2018 FastMath.addExact(a, b);
2019 fail("an exception should have been thrown");
2020 } catch (MathRuntimeException mae) {
2021
2022 }
2023 } else {
2024 assertEquals(bdSum, BigInteger.valueOf(FastMath.addExact(a, b)));
2025 }
2026 }
2027 }
2028 }
2029
2030 @Test
2031 void testAddExactLong() {
2032 long[] specialValues = new long[] {
2033 Long.MIN_VALUE, Long.MIN_VALUE + 1, Long.MIN_VALUE + 2,
2034 Long.MAX_VALUE, Long.MAX_VALUE - 1, Long.MAX_VALUE - 2,
2035 -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
2036 -1 - (Long.MIN_VALUE / 2), -(Long.MIN_VALUE / 2), 1 - (Long.MIN_VALUE / 2),
2037 -1 + (Long.MAX_VALUE / 2), (Long.MAX_VALUE / 2), 1 + (Long.MAX_VALUE / 2),
2038 };
2039 for (long a : specialValues) {
2040 for (long b : specialValues) {
2041 BigInteger bdA = BigInteger.valueOf(a);
2042 BigInteger bdB = BigInteger.valueOf(b);
2043 BigInteger bdSum = bdA.add(bdB);
2044 if (bdSum.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 0 ||
2045 bdSum.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) {
2046 try {
2047 FastMath.addExact(a, b);
2048 fail("an exception should have been thrown");
2049 } catch (MathRuntimeException mae) {
2050
2051 }
2052 } else {
2053 assertEquals(bdSum, BigInteger.valueOf(FastMath.addExact(a, b)));
2054 }
2055 }
2056 }
2057 }
2058
2059 @Test
2060 void testSubtractExactInt() {
2061 int[] specialValues = new int[] {
2062 Integer.MIN_VALUE, Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2,
2063 Integer.MAX_VALUE, Integer.MAX_VALUE - 1, Integer.MAX_VALUE - 2,
2064 -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
2065 -1 - (Integer.MIN_VALUE / 2), -(Integer.MIN_VALUE / 2), 1 - (Integer.MIN_VALUE / 2),
2066 -1 + (Integer.MAX_VALUE / 2), (Integer.MAX_VALUE / 2), 1 + (Integer.MAX_VALUE / 2),
2067 };
2068 for (int a : specialValues) {
2069 for (int b : specialValues) {
2070 BigInteger bdA = BigInteger.valueOf(a);
2071 BigInteger bdB = BigInteger.valueOf(b);
2072 BigInteger bdSub = bdA.subtract(bdB);
2073 if (bdSub.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0 ||
2074 bdSub.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) {
2075 try {
2076 FastMath.subtractExact(a, b);
2077 fail("an exception should have been thrown");
2078 } catch (MathRuntimeException mae) {
2079
2080 }
2081 } else {
2082 assertEquals(bdSub, BigInteger.valueOf(FastMath.subtractExact(a, b)));
2083 }
2084 }
2085 }
2086 }
2087
2088 @Test
2089 void testSubtractExactLong() {
2090 long[] specialValues = new long[] {
2091 Long.MIN_VALUE, Long.MIN_VALUE + 1, Long.MIN_VALUE + 2,
2092 Long.MAX_VALUE, Long.MAX_VALUE - 1, Long.MAX_VALUE - 2,
2093 -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
2094 -1 - (Long.MIN_VALUE / 2), -(Long.MIN_VALUE / 2), 1 - (Long.MIN_VALUE / 2),
2095 -1 + (Long.MAX_VALUE / 2), (Long.MAX_VALUE / 2), 1 + (Long.MAX_VALUE / 2),
2096 };
2097 for (long a : specialValues) {
2098 for (long b : specialValues) {
2099 BigInteger bdA = BigInteger.valueOf(a);
2100 BigInteger bdB = BigInteger.valueOf(b);
2101 BigInteger bdSub = bdA.subtract(bdB);
2102 if (bdSub.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 0 ||
2103 bdSub.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) {
2104 try {
2105 FastMath.subtractExact(a, b);
2106 fail("an exception should have been thrown");
2107 } catch (MathRuntimeException mae) {
2108
2109 }
2110 } else {
2111 assertEquals(bdSub, BigInteger.valueOf(FastMath.subtractExact(a, b)));
2112 }
2113 }
2114 }
2115 }
2116
2117 @Test
2118 void testMultiplyExactInt() {
2119 int[] specialValues = new int[] {
2120 Integer.MIN_VALUE, Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2,
2121 Integer.MAX_VALUE, Integer.MAX_VALUE - 1, Integer.MAX_VALUE - 2,
2122 -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
2123 -1 - (Integer.MIN_VALUE / 2), -(Integer.MIN_VALUE / 2), 1 - (Integer.MIN_VALUE / 2),
2124 -1 + (Integer.MAX_VALUE / 2), (Integer.MAX_VALUE / 2), 1 + (Integer.MAX_VALUE / 2),
2125 };
2126 for (int a : specialValues) {
2127 for (int b : specialValues) {
2128 BigInteger bdA = BigInteger.valueOf(a);
2129 BigInteger bdB = BigInteger.valueOf(b);
2130 BigInteger bdMul = bdA.multiply(bdB);
2131 if (bdMul.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0 ||
2132 bdMul.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) {
2133 try {
2134 FastMath.multiplyExact(a, b);
2135 fail("an exception should have been thrown " + a + b);
2136 } catch (MathRuntimeException mae) {
2137
2138 }
2139 } else {
2140 assertEquals(bdMul, BigInteger.valueOf(FastMath.multiplyExact(a, b)));
2141 }
2142 assertEquals(bdMul.longValue(), FastMath.multiplyFull(a, b));
2143 }
2144 }
2145 }
2146
2147 @Test
2148 void testMultiplyExactLongInt() {
2149 long[] specialValuesL = new long[] {
2150 Long.MIN_VALUE, Long.MIN_VALUE + 1, Long.MIN_VALUE + 2,
2151 Long.MAX_VALUE, Long.MAX_VALUE - 1, Long.MAX_VALUE - 2,
2152 -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
2153 -1 - (Long.MIN_VALUE / 2), -(Long.MIN_VALUE / 2), 1 - (Long.MIN_VALUE / 2),
2154 -1 + (Long.MAX_VALUE / 2), (Long.MAX_VALUE / 2), 1 + (Long.MAX_VALUE / 2),
2155 };
2156 int[] specialValuesI = new int[] {
2157 Integer.MIN_VALUE, Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2,
2158 Integer.MAX_VALUE, Integer.MAX_VALUE - 1, Integer.MAX_VALUE - 2,
2159 -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
2160 -1 - (Integer.MIN_VALUE / 2), -(Integer.MIN_VALUE / 2), 1 - (Integer.MIN_VALUE / 2),
2161 -1 + (Integer.MAX_VALUE / 2), (Integer.MAX_VALUE / 2), 1 + (Integer.MAX_VALUE / 2),
2162 };
2163 for (long a : specialValuesL) {
2164 for (int b : specialValuesI) {
2165 BigInteger bdA = BigInteger.valueOf(a);
2166 BigInteger bdB = BigInteger.valueOf(b);
2167 BigInteger bdMul = bdA.multiply(bdB);
2168 if (bdMul.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 0 ||
2169 bdMul.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) {
2170 try {
2171 FastMath.multiplyExact(a, b);
2172 fail("an exception should have been thrown " + a + b);
2173 } catch (MathRuntimeException mae) {
2174
2175 }
2176 } else {
2177 assertEquals(bdMul, BigInteger.valueOf(FastMath.multiplyExact(a, b)));
2178 }
2179 }
2180 }
2181 }
2182
2183 @Test
2184 void testMultiplyExactLong() {
2185 long[] specialValues = new long[] {
2186 Long.MIN_VALUE, Long.MIN_VALUE + 1, Long.MIN_VALUE + 2,
2187 Long.MAX_VALUE, Long.MAX_VALUE - 1, Long.MAX_VALUE - 2,
2188 -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
2189 -1 - (Long.MIN_VALUE / 2), -(Long.MIN_VALUE / 2), 1 - (Long.MIN_VALUE / 2),
2190 -1 + (Long.MAX_VALUE / 2), (Long.MAX_VALUE / 2), 1 + (Long.MAX_VALUE / 2),
2191 };
2192 for (long a : specialValues) {
2193 for (long b : specialValues) {
2194 BigInteger bdA = BigInteger.valueOf(a);
2195 BigInteger bdB = BigInteger.valueOf(b);
2196 BigInteger bdMul = bdA.multiply(bdB);
2197 if (bdMul.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 0 ||
2198 bdMul.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) {
2199 try {
2200 FastMath.multiplyExact(a, b);
2201 fail("an exception should have been thrown " + a + b);
2202 } catch (MathRuntimeException mae) {
2203
2204 }
2205 } else {
2206 assertEquals(bdMul, BigInteger.valueOf(FastMath.multiplyExact(a, b)));
2207 }
2208 }
2209 }
2210 }
2211
2212 @Test
2213 void testDivideExactInt() {
2214 int[] specialValues = new int[] {
2215 Integer.MIN_VALUE, Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2,
2216 Integer.MAX_VALUE, Integer.MAX_VALUE - 1, Integer.MAX_VALUE - 2,
2217 -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
2218 -1 - (Integer.MIN_VALUE / 2), -(Integer.MIN_VALUE / 2), 1 - (Integer.MIN_VALUE / 2),
2219 -1 + (Integer.MAX_VALUE / 2), (Integer.MAX_VALUE / 2), 1 + (Integer.MAX_VALUE / 2),
2220 };
2221 for (int a : specialValues) {
2222 for (int b : specialValues) {
2223 if (b == 0) {
2224 try {
2225 FastMath.divideExact(a, b);
2226 fail("an exception should have been thrown " + a + b);
2227 } catch (MathRuntimeException mae) {
2228 assertEquals(LocalizedCoreFormats.ZERO_DENOMINATOR, mae.getSpecifier());
2229 }
2230 } else {
2231 BigInteger bdA = BigInteger.valueOf(a);
2232 BigInteger bdB = BigInteger.valueOf(b);
2233 BigInteger bdDiv = bdA.divide(bdB);
2234 if (bdDiv.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0 ||
2235 bdDiv.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) {
2236 try {
2237 FastMath.divideExact(a, b);
2238 fail("an exception should have been thrown " + a + b);
2239 } catch (MathRuntimeException mae) {
2240
2241 }
2242 } else {
2243 assertEquals(bdDiv, BigInteger.valueOf(FastMath.divideExact(a, b)));
2244 }
2245 }
2246 }
2247 }
2248 }
2249
2250 @Test
2251 void testDivideExactLong() {
2252 long[] specialValues = new long[] {
2253 Long.MIN_VALUE, Long.MIN_VALUE + 1, Long.MIN_VALUE + 2,
2254 Long.MAX_VALUE, Long.MAX_VALUE - 1, Long.MAX_VALUE - 2,
2255 -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
2256 -1 - (Long.MIN_VALUE / 2), -(Long.MIN_VALUE / 2), 1 - (Long.MIN_VALUE / 2),
2257 -1 + (Long.MAX_VALUE / 2), (Long.MAX_VALUE / 2), 1 + (Long.MAX_VALUE / 2),
2258 };
2259 for (long a : specialValues) {
2260 for (long b : specialValues) {
2261 if (b == 0L) {
2262 try {
2263 FastMath.divideExact(a, b);
2264 fail("an exception should have been thrown " + a + b);
2265 } catch (MathRuntimeException mae) {
2266 assertEquals(LocalizedCoreFormats.ZERO_DENOMINATOR, mae.getSpecifier());
2267 }
2268 } else {
2269 BigInteger bdA = BigInteger.valueOf(a);
2270 BigInteger bdB = BigInteger.valueOf(b);
2271 BigInteger bdDiv = bdA.divide(bdB);
2272 if (bdDiv.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 0 ||
2273 bdDiv.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) {
2274 try {
2275 FastMath.divideExact(a, b);
2276 fail("an exception should have been thrown " + a + b);
2277 } catch (MathRuntimeException mae) {
2278
2279 }
2280 } else {
2281 assertEquals(bdDiv, BigInteger.valueOf(FastMath.divideExact(a, b)));
2282 }
2283 }
2284 }
2285 }
2286 }
2287
2288 @Test
2289 void testToIntExactTooLow() {
2290 assertThrows(MathRuntimeException.class, () -> {
2291 FastMath.toIntExact(-1L + Integer.MIN_VALUE);
2292 });
2293 }
2294
2295 @Test
2296 void testToIntExactTooHigh() {
2297 assertThrows(MathRuntimeException.class, () -> {
2298 FastMath.toIntExact(+1L + Integer.MAX_VALUE);
2299 });
2300 }
2301
2302 @Test
2303 void testAbsExactInt() {
2304 assertEquals(12, FastMath.absExact(+12));
2305 assertEquals(12, FastMath.absExact(-12));
2306 assertEquals(Integer.MAX_VALUE, FastMath.absExact(Integer.MAX_VALUE));
2307 assertEquals(Integer.MAX_VALUE, FastMath.absExact(-Integer.MAX_VALUE));
2308 try {
2309 FastMath.absExact(Integer.MIN_VALUE);
2310 fail("an exception should have been thrown");
2311 } catch (ArithmeticException ae) {
2312
2313 }
2314 }
2315
2316 @Test
2317 void testAbsExactLong() {
2318 assertEquals(12L, FastMath.absExact(+12L));
2319 assertEquals(12L, FastMath.absExact(-12L));
2320 assertEquals(Long.MAX_VALUE, FastMath.absExact(Long.MAX_VALUE));
2321 assertEquals(Long.MAX_VALUE, FastMath.absExact(-Long.MAX_VALUE));
2322 try {
2323 FastMath.absExact(Long.MIN_VALUE);
2324 fail("an exception should have been thrown");
2325 } catch (ArithmeticException ae) {
2326
2327 }
2328 }
2329
2330 @Test
2331 void testNegateExactInt() {
2332 assertEquals(-12, FastMath.negateExact(+12));
2333 assertEquals(12, FastMath.negateExact(-12));
2334 assertEquals(-Integer.MAX_VALUE, FastMath.negateExact(Integer.MAX_VALUE));
2335 assertEquals(Integer.MAX_VALUE, FastMath.negateExact(-Integer.MAX_VALUE));
2336 try {
2337 FastMath.negateExact(Integer.MIN_VALUE);
2338 fail("an exception should have been thrown");
2339 } catch (ArithmeticException ae) {
2340
2341 }
2342 }
2343
2344 @Test
2345 void testNegateExactLong() {
2346 assertEquals(-12L, FastMath.negateExact(+12L));
2347 assertEquals(12L, FastMath.negateExact(-12L));
2348 assertEquals(-Long.MAX_VALUE, FastMath.negateExact(Long.MAX_VALUE));
2349 assertEquals(Long.MAX_VALUE, FastMath.negateExact(-Long.MAX_VALUE));
2350 try {
2351 FastMath.negateExact(Long.MIN_VALUE);
2352 fail("an exception should have been thrown");
2353 } catch (ArithmeticException ae) {
2354
2355 }
2356 }
2357
2358 @Test
2359 void testToIntExact() {
2360 for (int n = -1000; n < 1000; ++n) {
2361 assertEquals(n, FastMath.toIntExact((long) n));
2362 }
2363 assertEquals(Integer.MIN_VALUE, FastMath.toIntExact(
2364 (long) Integer.MIN_VALUE));
2365 assertEquals(Integer.MAX_VALUE, FastMath.toIntExact(
2366 (long) Integer.MAX_VALUE));
2367 }
2368
2369 @Test
2370 void testCeilDivInt() {
2371 assertEquals(+2, FastMath.ceilDiv(+4, +3));
2372 assertEquals(-1, FastMath.ceilDiv(-4, +3));
2373 assertEquals(-1, FastMath.ceilDiv(+4, -3));
2374 assertEquals(+2, FastMath.ceilDiv(-4, -3));
2375 try {
2376 FastMath.ceilDiv(1, 0);
2377 fail("an exception should have been thrown");
2378 } catch (MathRuntimeException mae) {
2379
2380 }
2381 for (int a = -100; a <= 100; ++a) {
2382 for (int b = -100; b <= 100; ++b) {
2383 if (b != 0) {
2384 assertEquals(poorManCeilDiv(a, b), FastMath.ceilDiv(a, b));
2385 assertEquals(poorManCeilDiv(a, b), FastMath.ceilDivExact(a, b));
2386 }
2387 }
2388 }
2389 assertEquals(Integer.MIN_VALUE, FastMath.ceilDiv(Integer.MIN_VALUE, -1));
2390 try {
2391 FastMath.ceilDivExact(Integer.MIN_VALUE, -1);
2392 fail("an exception should have been thrown");
2393 } catch (MathRuntimeException mre) {
2394 assertEquals(LocalizedCoreFormats.OVERFLOW_IN_FRACTION, mre.getSpecifier());
2395 }
2396 }
2397
2398 @Test
2399 void testCeilDivLong() {
2400 assertEquals(+2L, FastMath.ceilDiv(+4L, +3L));
2401 assertEquals(-1L, FastMath.ceilDiv(-4L, +3L));
2402 assertEquals(-1L, FastMath.ceilDiv(+4L, -3L));
2403 assertEquals(+2L, FastMath.ceilDiv(-4L, -3L));
2404 try {
2405 FastMath.ceilDiv(1L, 0L);
2406 fail("an exception should have been thrown");
2407 } catch (MathRuntimeException mae) {
2408
2409 }
2410 for (long a = -100L; a <= 100L; ++a) {
2411 for (long b = -100L; b <= 100L; ++b) {
2412 if (b != 0L) {
2413 assertEquals(poorManCeilDiv(a, b), FastMath.ceilDiv(a, b));
2414 assertEquals(poorManCeilDiv(a, b), FastMath.ceilDivExact(a, b));
2415 }
2416 }
2417 }
2418 assertEquals(Long.MIN_VALUE, FastMath.ceilDiv(Long.MIN_VALUE, -1L));
2419 try {
2420 FastMath.ceilDivExact(Long.MIN_VALUE, -1L);
2421 fail("an exception should have been thrown");
2422 } catch (MathRuntimeException mre) {
2423 assertEquals(LocalizedCoreFormats.OVERFLOW_IN_FRACTION, mre.getSpecifier());
2424 }
2425 }
2426
2427 @Test
2428 void testCeilDivLongInt() {
2429 assertEquals(+2L, FastMath.ceilDiv(+4L, +3));
2430 assertEquals(-1L, FastMath.ceilDiv(-4L, +3));
2431 assertEquals(-1L, FastMath.ceilDiv(+4L, -3));
2432 assertEquals(+2L, FastMath.ceilDiv(-4L, -3));
2433 try {
2434 FastMath.ceilDiv(1L, 0);
2435 fail("an exception should have been thrown");
2436 } catch (MathRuntimeException mae) {
2437
2438 }
2439 for (long a = -100L; a <= 100L; ++a) {
2440 for (int b = -100; b <= 100; ++b) {
2441 if (b != 0) {
2442 assertEquals(poorManCeilDiv(a, b), FastMath.ceilDiv(a, b));
2443 assertEquals(poorManCeilDiv(a, b), FastMath.ceilDivExact(a, b));
2444 }
2445 }
2446 }
2447 assertEquals(Long.MIN_VALUE, FastMath.ceilDiv(Long.MIN_VALUE, -1));
2448 try {
2449 FastMath.ceilDivExact(Long.MIN_VALUE, -1);
2450 fail("an exception should have been thrown");
2451 } catch (MathRuntimeException mre) {
2452 assertEquals(LocalizedCoreFormats.OVERFLOW_IN_FRACTION, mre.getSpecifier());
2453 }
2454 }
2455
2456 @Test
2457 void testCeilDivModInt() {
2458 RandomGenerator generator = new Well1024a(0x66c371cc6f7ebea9L);
2459 for (int i = 0; i < 10000; ++i) {
2460 int a = generator.nextInt();
2461 int b = generator.nextInt();
2462 if (b == 0) {
2463 try {
2464 FastMath.floorMod(a, b);
2465 fail("an exception should have been thrown");
2466 } catch (MathRuntimeException mae) {
2467
2468 }
2469 } else {
2470 int d = FastMath.ceilDiv(a, b);
2471 int m = FastMath.ceilMod(a, b);
2472 assertEquals(poorManCeilDiv(a, b), d);
2473 assertEquals(poorManCeilMod(a, b), m);
2474 assertEquals(a, (long) d * b + m);
2475 if (b < 0) {
2476 assertTrue(m >= 0);
2477 assertTrue(-m > b);
2478 } else {
2479 assertTrue(m <= 0);
2480 assertTrue(m < b);
2481 }
2482 }
2483 }
2484 }
2485
2486 @Test
2487 void testCeilDivModLong() {
2488 RandomGenerator generator = new Well1024a(0x769c9ab4e4a9129eL);
2489 for (int i = 0; i < 10000; ++i) {
2490 long a = generator.nextLong();
2491 long b = generator.nextLong();
2492 if (b == 0L) {
2493 try {
2494 FastMath.floorMod(a, b);
2495 fail("an exception should have been thrown");
2496 } catch (MathRuntimeException mae) {
2497
2498 }
2499 } else {
2500 long d = FastMath.ceilDiv(a, b);
2501 long m = FastMath.ceilMod(a, b);
2502 assertEquals(poorManCeilDiv(a, b), d);
2503 assertEquals(poorManCeilMod(a, b), m);
2504 assertEquals(a, d * b + m);
2505 if (b < 0L) {
2506 assertTrue(m >= 0L);
2507 assertTrue(-m > b);
2508 } else {
2509 assertTrue(m <= 0L);
2510 assertTrue(m < b);
2511 }
2512 }
2513 }
2514 }
2515
2516 @Test
2517 void testCeilDivModLongInt() {
2518 RandomGenerator generator = new Well1024a(0xd4c67ab9cd4af669L);
2519 for (int i = 0; i < 10000; ++i) {
2520 long a = generator.nextLong();
2521 int b = generator.nextInt();
2522 if (b == 0) {
2523 try {
2524 FastMath.floorMod(a, b);
2525 fail("an exception should have been thrown");
2526 } catch (MathRuntimeException mae) {
2527
2528 }
2529 } else {
2530 long d = FastMath.ceilDiv(a, b);
2531 int m = FastMath.ceilMod(a, b);
2532 assertEquals(poorManCeilDiv(a, b), d);
2533 assertEquals(poorManCeilMod(a, b), m);
2534 assertEquals(a, d * b + m);
2535 if (b < 0) {
2536 assertTrue(m >= 0);
2537 assertTrue(-m > b);
2538 } else {
2539 assertTrue(m <= 0);
2540 assertTrue(m < b);
2541 }
2542 }
2543 }
2544 }
2545
2546 @Test
2547 void testFloorDivInt() {
2548 assertEquals(+1, FastMath.floorDiv(+4, +3));
2549 assertEquals(-2, FastMath.floorDiv(-4, +3));
2550 assertEquals(-2, FastMath.floorDiv(+4, -3));
2551 assertEquals(+1, FastMath.floorDiv(-4, -3));
2552 try {
2553 FastMath.floorDiv(1, 0);
2554 fail("an exception should have been thrown");
2555 } catch (MathRuntimeException mae) {
2556
2557 }
2558 for (int a = -100; a <= 100; ++a) {
2559 for (int b = -100; b <= 100; ++b) {
2560 if (b != 0) {
2561 assertEquals(poorManFloorDiv(a, b), FastMath.floorDiv(a, b));
2562 assertEquals(poorManFloorDiv(a, b), FastMath.floorDivExact(a, b));
2563 }
2564 }
2565 }
2566 assertEquals(Integer.MIN_VALUE, FastMath.floorDiv(Integer.MIN_VALUE, -1));
2567 try {
2568 FastMath.floorDivExact(Integer.MIN_VALUE, -1);
2569 fail("an exception should have been thrown");
2570 } catch (MathRuntimeException mre) {
2571 assertEquals(LocalizedCoreFormats.OVERFLOW_IN_FRACTION, mre.getSpecifier());
2572 }
2573 }
2574
2575 @Test
2576 void testFloorModInt() {
2577 assertEquals(+1, FastMath.floorMod(+4, +3));
2578 assertEquals(+2, FastMath.floorMod(-4, +3));
2579 assertEquals(-2, FastMath.floorMod(+4, -3));
2580 assertEquals(-1, FastMath.floorMod(-4, -3));
2581 try {
2582 FastMath.floorMod(1, 0);
2583 fail("an exception should have been thrown");
2584 } catch (MathRuntimeException mae) {
2585
2586 }
2587 for (int a = -100; a <= 100; ++a) {
2588 for (int b = -100; b <= 100; ++b) {
2589 if (b != 0) {
2590 assertEquals(poorManFloorMod(a, b), FastMath.floorMod(a, b));
2591 }
2592 }
2593 }
2594 }
2595
2596 @Test
2597 void testFloorDivModInt() {
2598 RandomGenerator generator = new Well1024a(0x7ccab45edeaab90aL);
2599 for (int i = 0; i < 10000; ++i) {
2600 int a = generator.nextInt();
2601 int b = generator.nextInt();
2602 if (b == 0) {
2603 try {
2604 FastMath.floorDiv(a, b);
2605 fail("an exception should have been thrown");
2606 } catch (MathRuntimeException mae) {
2607
2608 }
2609 } else {
2610 int d = FastMath.floorDiv(a, b);
2611 int m = FastMath.floorMod(a, b);
2612 assertEquals(poorManFloorDiv(a, b), d);
2613 assertEquals(poorManFloorMod(a, b), m);
2614 assertEquals(a, (long) d * b + m);
2615 if (b < 0) {
2616 assertTrue(m <= 0);
2617 assertTrue(-m < -b);
2618 } else {
2619 assertTrue(m >= 0);
2620 assertTrue(m < b);
2621 }
2622 }
2623 }
2624 }
2625
2626 @Test
2627 void testFloorDivLong() {
2628 assertEquals(+1L, FastMath.floorDiv(+4L, +3L));
2629 assertEquals(-2L, FastMath.floorDiv(-4L, +3L));
2630 assertEquals(-2L, FastMath.floorDiv(+4L, -3L));
2631 assertEquals(+1L, FastMath.floorDiv(-4L, -3L));
2632 try {
2633 FastMath.floorDiv(1L, 0L);
2634 fail("an exception should have been thrown");
2635 } catch (MathRuntimeException mae) {
2636
2637 }
2638 for (long a = -100L; a <= 100L; ++a) {
2639 for (long b = -100L; b <= 100L; ++b) {
2640 if (b != 0) {
2641 assertEquals(poorManFloorDiv(a, b), FastMath.floorDiv(a, b));
2642 assertEquals(poorManFloorDiv(a, b), FastMath.floorDivExact(a, b));
2643 }
2644 }
2645 }
2646 assertEquals(Long.MIN_VALUE, FastMath.floorDiv(Long.MIN_VALUE, -1L));
2647 try {
2648 FastMath.floorDivExact(Long.MIN_VALUE, -1L);
2649 fail("an exception should have been thrown");
2650 } catch (MathRuntimeException mre) {
2651 assertEquals(LocalizedCoreFormats.OVERFLOW_IN_FRACTION, mre.getSpecifier());
2652 }
2653 }
2654
2655 @Test
2656 void testFloorModLong() {
2657 assertEquals(+1L, FastMath.floorMod(+4L, +3L));
2658 assertEquals(+2L, FastMath.floorMod(-4L, +3L));
2659 assertEquals(-2L, FastMath.floorMod(+4L, -3L));
2660 assertEquals(-1L, FastMath.floorMod(-4L, -3L));
2661 try {
2662 FastMath.floorMod(1L, 0L);
2663 fail("an exception should have been thrown");
2664 } catch (MathRuntimeException mae) {
2665
2666 }
2667 for (long a = -100L; a <= 100L; ++a) {
2668 for (long b = -100L; b <= 100L; ++b) {
2669 if (b != 0) {
2670 assertEquals(poorManFloorMod(a, b), FastMath.floorMod(a, b));
2671 }
2672 }
2673 }
2674 }
2675
2676 @Test
2677 void testFloorDivModLong() {
2678 RandomGenerator generator = new Well1024a(0xb87b9bc14c96ccd5L);
2679 for (int i = 0; i < 10000; ++i) {
2680 long a = generator.nextLong();
2681 long b = generator.nextLong();
2682 if (b == 0) {
2683 try {
2684 FastMath.floorDiv(a, b);
2685 fail("an exception should have been thrown");
2686 } catch (MathRuntimeException mae) {
2687
2688 }
2689 } else {
2690 long d = FastMath.floorDiv(a, b);
2691 long m = FastMath.floorMod(a, b);
2692 assertEquals(poorManFloorDiv(a, b), d);
2693 assertEquals(poorManFloorMod(a, b), m);
2694 assertEquals(a, d * b + m);
2695 if (b < 0) {
2696 assertTrue(m <= 0);
2697 assertTrue(-m < -b);
2698 } else {
2699 assertTrue(m >= 0);
2700 assertTrue(m < b);
2701 }
2702 }
2703 }
2704 }
2705
2706 @Test
2707 void testFloorDivModLongInt() {
2708 RandomGenerator generator = new Well1024a(0xe03b6a1800d92fa7L);
2709 for (int i = 0; i < 10000; ++i) {
2710 long a = generator.nextInt();
2711 int b = generator.nextInt();
2712 if (b == 0) {
2713 try {
2714 FastMath.floorDiv(a, b);
2715 fail("an exception should have been thrown");
2716 } catch (MathRuntimeException mae) {
2717
2718 }
2719 } else {
2720 long d = FastMath.floorDiv(a, b);
2721 long m = FastMath.floorMod(a, b);
2722 assertEquals(poorManFloorDiv(a, b), d);
2723 assertEquals(poorManFloorMod(a, b), m);
2724 assertEquals(a, d * b + m);
2725 if (b < 0) {
2726 assertTrue(m <= 0);
2727 assertTrue(-m < -b);
2728 } else {
2729 assertTrue(m >= 0);
2730 assertTrue(m < b);
2731 }
2732 }
2733 }
2734 }
2735
2736 private int poorManCeilDiv(int a, int b) {
2737
2738
2739 BigInteger q0 = BigInteger.valueOf(a / b);
2740 BigInteger r0 = BigInteger.valueOf(a % b);
2741 BigInteger fd = BigInteger.valueOf(Integer.MIN_VALUE);
2742 BigInteger bigB = BigInteger.valueOf(b);
2743
2744 for (int k = -2; k < 2; ++k) {
2745
2746 BigInteger bigK = BigInteger.valueOf(k);
2747 BigInteger q = q0.subtract(bigK);
2748 BigInteger r = r0.add(bigK.multiply(bigB));
2749 if (r.abs().compareTo(bigB.abs()) < 0 &&
2750 (r.intValue() == 0 || ((r.intValue() ^ b) & 0x80000000) != 0)) {
2751 if (fd.compareTo(q) < 0) {
2752 fd = q;
2753 }
2754 }
2755 }
2756
2757 return fd.intValue();
2758
2759 }
2760
2761 private long poorManCeilDiv(long a, long b) {
2762
2763
2764 BigInteger q0 = BigInteger.valueOf(a / b);
2765 BigInteger r0 = BigInteger.valueOf(a % b);
2766 BigInteger fd = BigInteger.valueOf(Long.MIN_VALUE);
2767 BigInteger bigB = BigInteger.valueOf(b);
2768
2769 for (int k = -2; k < 2; ++k) {
2770
2771 BigInteger bigK = BigInteger.valueOf(k);
2772 BigInteger q = q0.subtract(bigK);
2773 BigInteger r = r0.add(bigK.multiply(bigB));
2774 if (r.abs().compareTo(bigB.abs()) < 0 &&
2775 (r.longValue() == 0L || ((r.longValue() ^ b) & 0x8000000000000000L) != 0)) {
2776 if (fd.compareTo(q) < 0) {
2777 fd = q;
2778 }
2779 }
2780 }
2781
2782 return fd.longValue();
2783
2784 }
2785
2786 private long poorManCeilMod(long a, long b) {
2787 return a - b * poorManCeilDiv(a, b);
2788 }
2789
2790 private int poorManFloorDiv(int a, int b) {
2791
2792
2793 BigInteger q0 = BigInteger.valueOf(a / b);
2794 BigInteger r0 = BigInteger.valueOf(a % b);
2795 BigInteger fd = BigInteger.valueOf(Integer.MIN_VALUE);
2796 BigInteger bigB = BigInteger.valueOf(b);
2797
2798 for (int k = -2; k < 2; ++k) {
2799
2800 BigInteger bigK = BigInteger.valueOf(k);
2801 BigInteger q = q0.subtract(bigK);
2802 BigInteger r = r0.add(bigK.multiply(bigB));
2803 if (r.abs().compareTo(bigB.abs()) < 0 &&
2804 (r.intValue() == 0 || ((r.intValue() ^ b) & 0x80000000) == 0)) {
2805 if (fd.compareTo(q) < 0) {
2806 fd = q;
2807 }
2808 }
2809 }
2810
2811 return fd.intValue();
2812
2813 }
2814
2815 private int poorManFloorMod(int a, int b) {
2816 return a - b * poorManFloorDiv(a, b);
2817 }
2818
2819 private long poorManFloorDiv(long a, long b) {
2820
2821
2822 BigInteger q0 = BigInteger.valueOf(a / b);
2823 BigInteger r0 = BigInteger.valueOf(a % b);
2824 BigInteger fd = BigInteger.valueOf(Long.MIN_VALUE);
2825 BigInteger bigB = BigInteger.valueOf(b);
2826
2827 for (int k = -2; k < 2; ++k) {
2828
2829 BigInteger bigK = BigInteger.valueOf(k);
2830 BigInteger q = q0.subtract(bigK);
2831 BigInteger r = r0.add(bigK.multiply(bigB));
2832 if (r.abs().compareTo(bigB.abs()) < 0 &&
2833 (r.longValue() == 0L || ((r.longValue() ^ b) & 0x8000000000000000L) == 0)) {
2834 if (fd.compareTo(q) < 0) {
2835 fd = q;
2836 }
2837 }
2838 }
2839
2840 return fd.longValue();
2841
2842 }
2843
2844 private long poorManFloorMod(long a, long b) {
2845 return a - b * poorManFloorDiv(a, b);
2846 }
2847
2848
2849
2850
2851 @Test
2852 void testRoundDown() {
2853 double x = 0x1.fffffffffffffp-2;
2854 assertTrue(x < 0.5d);
2855 assertEquals(0, FastMath.round(x));
2856
2857 x = 4503599627370497.0;
2858 assertEquals("4503599627370497", new BigDecimal(x).toString());
2859 assertEquals(x, Math.rint(x), 0.0);
2860 assertEquals(x, FastMath.round(x), 0.0);
2861 assertEquals(x, Math.round(x), 0.0);
2862 }
2863
2864 @Test
2865 void testHypot() {
2866 for (double x = -20; x < 20; x += 0.01) {
2867 for (double y = -20; y < 20; y += 0.01) {
2868 assertEquals(FastMath.sqrt(x * x + y * y), FastMath.hypot(x, y), 1.0e-15);
2869 }
2870 }
2871 }
2872
2873 @Test
2874 void testHypotNoOverflow() {
2875 final double x = +3.0e250;
2876 final double y = -4.0e250;
2877 final double h = +5.0e250;
2878 assertEquals(h, FastMath.hypot(x, y), 1.0e-15 * h);
2879 assertTrue(Double.isInfinite(FastMath.sqrt(x * x + y * y)));
2880 }
2881
2882 @Test
2883 void testHypotSpecialCases() {
2884 assertTrue(Double.isNaN(FastMath.hypot(Double.NaN, 0)));
2885 assertTrue(Double.isNaN(FastMath.hypot(0, Double.NaN)));
2886 assertEquals(Double.POSITIVE_INFINITY, FastMath.hypot(Double.POSITIVE_INFINITY, 0), 1.0);
2887 assertEquals(Double.POSITIVE_INFINITY, FastMath.hypot(Double.NEGATIVE_INFINITY, 0), 1.0);
2888 assertEquals(Double.POSITIVE_INFINITY, FastMath.hypot(Double.POSITIVE_INFINITY, Double.NaN), 1.0);
2889 assertEquals(Double.POSITIVE_INFINITY, FastMath.hypot(Double.NEGATIVE_INFINITY, Double.NaN), 1.0);
2890 assertEquals(Double.POSITIVE_INFINITY, FastMath.hypot(0, Double.POSITIVE_INFINITY), 1.0);
2891 assertEquals(Double.POSITIVE_INFINITY, FastMath.hypot(0, Double.NEGATIVE_INFINITY), 1.0);
2892 assertEquals(Double.POSITIVE_INFINITY, FastMath.hypot(Double.NaN, Double.POSITIVE_INFINITY), 1.0);
2893 assertEquals(Double.POSITIVE_INFINITY, FastMath.hypot(Double.NaN, Double.NEGATIVE_INFINITY), 1.0);
2894 }
2895
2896 @Test
2897 void testFMADouble() {
2898
2899 assertEquals(Double.doubleToRawLongBits(+0.0),
2900 Double.doubleToRawLongBits(FastMath.fma(-0.0, +0.0, +0.0)));
2901 assertEquals(Double.doubleToRawLongBits(-0.0),
2902 Double.doubleToRawLongBits(-0.0 * +0.0));
2903
2904
2905 double a = 0x1.123456789abcdp-04;
2906 double b = 0x1.dcba987654321p+01;
2907 double c = -0x1.fea12e1ce4000p-03;
2908 double fma = 0x1.fb864494872dap-44;
2909 assertEquals(fma, FastMath.fma(a, b, c), 1.0e-50);
2910 assertTrue(FastMath.fma(a, b, c) - (a * b + c) > 5.0e-18);
2911
2912 }
2913
2914 @Test
2915 void testFMAFloat() {
2916
2917 assertEquals(Float.floatToRawIntBits(+0.0f),
2918 Float.floatToRawIntBits(FastMath.fma(-0.0f, +0.0f, +0.0f)));
2919 assertEquals(Float.floatToRawIntBits(-0.0f),
2920 Float.floatToRawIntBits(-0.0f * +0.0f));
2921
2922
2923 float a = 0x1.123456p-04f;
2924 float b = 0x1.654322p+01f;
2925 float c = -0x1.7eaa00p-03f;
2926 float fma = 0x1.c816eap-20f;
2927 assertEquals(fma, FastMath.fma(a, b, c), 1.0e-20f);
2928 assertTrue(FastMath.fma(a, b, c) - (a * b + c) > 3.0e-10f);
2929
2930 }
2931
2932 @Test
2933 void testMultiplyHigh() {
2934
2935
2936 final long a = 153092023L;
2937 final long b = 60247241209L;
2938 assertEquals(Long.MAX_VALUE, a * b);
2939 assertEquals(0, FastMath.multiplyHigh(a, b));
2940
2941
2942
2943 final long c1 = 1L << 31;
2944 final long c2 = 1L << 32;
2945 assertEquals(0, FastMath.multiplyHigh(c1, c2));
2946 assertEquals(Long.MIN_VALUE, c1 * c2);
2947
2948
2949 final long[] values = new long[] {
2950 -1L, 0L, 1L, 10L, 0x100000000L, 0x200000000L, 0x400000000L, -0x100000000L, -0x200000000L, -0x400000000L,
2951 ((long) Integer.MIN_VALUE) -1, ((long) Integer.MIN_VALUE), ((long) Integer.MIN_VALUE) +1,
2952 ((long) Integer.MAX_VALUE) -1, ((long) Integer.MAX_VALUE), ((long) Integer.MAX_VALUE) +1,
2953 Long.MIN_VALUE, Long.MAX_VALUE
2954 };
2955 for (final long p : values) {
2956 for (long q : values) {
2957 assertEquals(poorManMultiplyHigh(p, q), FastMath.multiplyHigh(p, q));
2958 }
2959 }
2960
2961
2962 RandomGenerator random = new Well1024a(0x082a2316178e5e9eL);
2963 for (int i = 0; i < 10000000; ++i) {
2964 long m = random.nextLong();
2965 long n = random.nextLong();
2966 assertEquals(poorManMultiplyHigh(m, n), FastMath.multiplyHigh(m, n));
2967 }
2968 }
2969
2970 @Test
2971 void testUnsignedMultiplyHigh() {
2972
2973
2974 final long a = 153092023L;
2975 final long b = 60247241209L;
2976 assertEquals(Long.MAX_VALUE, a * b);
2977 assertEquals(0, FastMath.unsignedMultiplyHigh(a, b));
2978
2979
2980
2981 final long c1 = 1L << 31;
2982 final long c2 = 1L << 32;
2983 assertEquals(0, FastMath.unsignedMultiplyHigh(c1, c2));
2984 assertEquals(Long.MIN_VALUE, c1 * c2);
2985
2986
2987 final long[] values = new long[] {
2988 -1L, 0L, 1L, 10L, 0x100000000L, 0x200000000L, 0x400000000L, -0x100000000L, -0x200000000L, -0x400000000L,
2989 ((long) Integer.MIN_VALUE) -1, ((long) Integer.MIN_VALUE), ((long) Integer.MIN_VALUE) +1,
2990 ((long) Integer.MAX_VALUE) -1, ((long) Integer.MAX_VALUE), ((long) Integer.MAX_VALUE) +1,
2991 Long.MIN_VALUE, Long.MAX_VALUE
2992 };
2993 for (final long p : values) {
2994 for (long q : values) {
2995 assertEquals(poorManUnsignedMultiplyHigh(p, q), FastMath.unsignedMultiplyHigh(p, q));
2996 }
2997 }
2998
2999
3000 RandomGenerator random = new Well1024a(0xcf5736c8f8adf962L);
3001 for (int i = 0; i < 10000000; ++i) {
3002 long m = random.nextLong();
3003 long n = random.nextLong();
3004 assertEquals(poorManUnsignedMultiplyHigh(m, n), FastMath.unsignedMultiplyHigh(m, n));
3005 }
3006 }
3007
3008 @Test
3009 void testGetExponentDouble() {
3010 assertEquals( 1024, FastMath.getExponent(Double.NaN));
3011 assertEquals( 1024, FastMath.getExponent(Double.POSITIVE_INFINITY));
3012 assertEquals( 1024, FastMath.getExponent(Double.NEGATIVE_INFINITY));
3013 assertEquals(-1023, FastMath.getExponent(+0.0));
3014 assertEquals(-1023, FastMath.getExponent(-0.0));
3015 assertEquals( 1, FastMath.getExponent(+2.0));
3016 assertEquals( 1, FastMath.getExponent(-2.0));
3017 for (int i = -1022; i < 1024; ++i) {
3018 assertEquals(i, FastMath.getExponent(FastMath.scalb(1.0, i)));
3019 assertEquals(i, FastMath.getExponent(FastMath.scalb(1.2, i)));
3020 assertEquals(i, FastMath.getExponent(FastMath.scalb(1.5, i)));
3021 assertEquals(i, FastMath.getExponent(FastMath.scalb(1.999, i)));
3022 }
3023 }
3024
3025 @Test
3026 void testGetExponentFloat() {
3027 assertEquals( 128, FastMath.getExponent(Float.NaN));
3028 assertEquals( 128, FastMath.getExponent(Float.POSITIVE_INFINITY));
3029 assertEquals( 128, FastMath.getExponent(Float.NEGATIVE_INFINITY));
3030 assertEquals(-127, FastMath.getExponent(+0.0f));
3031 assertEquals(-127, FastMath.getExponent(-0.0f));
3032 assertEquals( 1, FastMath.getExponent(+2.0f));
3033 assertEquals( 1, FastMath.getExponent(-2.0f));
3034 for (int i = -126; i < 128; ++i) {
3035 assertEquals(i, FastMath.getExponent(FastMath.scalb(1.0f, i)));
3036 assertEquals(i, FastMath.getExponent(FastMath.scalb(1.2f, i)));
3037 assertEquals(i, FastMath.getExponent(FastMath.scalb(1.5f, i)));
3038 assertEquals(i, FastMath.getExponent(FastMath.scalb(1.999f, i)));
3039 }
3040 }
3041
3042 private static long poorManMultiplyHigh(final long p, final long q) {
3043
3044 BigInteger bigP = BigInteger.valueOf(p);
3045 if (p < 0) {
3046 bigP = BigInteger.ONE.shiftLeft(128).add(bigP);
3047 }
3048
3049 BigInteger bigQ = BigInteger.valueOf(q);
3050 if (q < 0) {
3051 bigQ = BigInteger.ONE.shiftLeft(128).add(bigQ);
3052 }
3053
3054 return bigP.multiply(bigQ).shiftRight(64).longValue();
3055
3056 }
3057
3058 private static long poorManUnsignedMultiplyHigh(final long p, final long q) {
3059
3060 BigInteger bigP = BigInteger.valueOf(p);
3061 if (p < 0) {
3062 bigP = BigInteger.ONE.shiftLeft(64).add(bigP);
3063 }
3064
3065 BigInteger bigQ = BigInteger.valueOf(q);
3066 if (q < 0) {
3067 bigQ = BigInteger.ONE.shiftLeft(64).add(bigQ);
3068 }
3069
3070 return bigP.multiply(bigQ).shiftRight(64).longValue();
3071
3072 }
3073
3074 }