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