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