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