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    *      http://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  package org.apache.commons.math4.legacy.core.jdkmath;
18  
19  import static org.junit.Assert.assertEquals;
20  import static org.junit.Assert.assertTrue;
21  import static org.junit.Assert.fail;
22  
23  import java.math.BigDecimal;
24  import java.math.BigInteger;
25  import java.math.RoundingMode;
26  
27  import org.junit.Assert;
28  import org.junit.Before;
29  import org.junit.Test;
30  import org.junit.jupiter.api.Assertions;
31  import org.apache.commons.numbers.core.ArithmeticUtils;
32  import org.apache.commons.numbers.core.Precision;
33  import org.apache.commons.math4.legacy.core.dfp.Dfp;
34  import org.apache.commons.math4.legacy.core.dfp.DfpField;
35  import org.apache.commons.math4.legacy.core.dfp.DfpMath;
36  import org.apache.commons.rng.UniformRandomProvider;
37  import org.apache.commons.rng.simple.RandomSource;
38  
39  // Unit test should be moved to module "commons-math-core".
40  // [Currently, it can't be because it depends on "legacy" classes.]
41  import org.apache.commons.math4.core.jdkmath.AccurateMath;
42  
43  public class AccurateMathTest {
44      // CHECKSTYLE: stop Regexp
45      // The above comment allows System.out.print
46  
47      private static final double MAX_ERROR_ULP = 0.51;
48      private static final int NUMBER_OF_TRIALS = 1000;
49  
50      private DfpField field;
51      private UniformRandomProvider generator;
52  
53      @Before
54      public void setUp() {
55          field = new DfpField(40);
56          generator = RandomSource.MT.create(6176597458463500194L);
57      }
58  
59      @Test
60      public void testMinMaxDouble() {
61          double[][] pairs = {
62              {-50.0, 50.0},
63              {Double.POSITIVE_INFINITY, 1.0},
64              {Double.NEGATIVE_INFINITY, 1.0},
65              {Double.NaN, 1.0},
66              {Double.POSITIVE_INFINITY, 0.0},
67              {Double.NEGATIVE_INFINITY, 0.0},
68              {Double.NaN, 0.0},
69              {Double.NaN, Double.NEGATIVE_INFINITY},
70              {Double.NaN, Double.POSITIVE_INFINITY},
71              {Precision.SAFE_MIN, Precision.EPSILON}
72          };
73          for (double[] pair : pairs) {
74              assertEquals("min(" + pair[0] + ", " + pair[1] + ")",
75                           Math.min(pair[0], pair[1]),
76                           AccurateMath.min(pair[0], pair[1]),
77                           Precision.EPSILON);
78              assertEquals("min(" + pair[1] + ", " + pair[0] + ")",
79                           Math.min(pair[1], pair[0]),
80                           AccurateMath.min(pair[1], pair[0]),
81                           Precision.EPSILON);
82              assertEquals("max(" + pair[0] + ", " + pair[1] + ")",
83                           Math.max(pair[0], pair[1]),
84                           AccurateMath.max(pair[0], pair[1]),
85                           Precision.EPSILON);
86              assertEquals("max(" + pair[1] + ", " + pair[0] + ")",
87                           Math.max(pair[1], pair[0]),
88                           AccurateMath.max(pair[1], pair[0]),
89                           Precision.EPSILON);
90          }
91      }
92  
93      @Test
94      public void testMinMaxFloat() {
95          float[][] pairs = {
96              {-50.0f, 50.0f},
97              {Float.POSITIVE_INFINITY, 1.0f},
98              {Float.NEGATIVE_INFINITY, 1.0f},
99              {Float.NaN, 1.0f},
100             {Float.POSITIVE_INFINITY, 0.0f},
101             {Float.NEGATIVE_INFINITY, 0.0f},
102             {Float.NaN, 0.0f},
103             {Float.NaN, Float.NEGATIVE_INFINITY},
104             {Float.NaN, Float.POSITIVE_INFINITY}
105         };
106         for (float[] pair : pairs) {
107             assertEquals("min(" + pair[0] + ", " + pair[1] + ")",
108                     Math.min(pair[0], pair[1]),
109                     AccurateMath.min(pair[0], pair[1]),
110                     Precision.EPSILON);
111             assertEquals("min(" + pair[1] + ", " + pair[0] + ")",
112                     Math.min(pair[1], pair[0]),
113                     AccurateMath.min(pair[1], pair[0]),
114                     Precision.EPSILON);
115             assertEquals("max(" + pair[0] + ", " + pair[1] + ")",
116                     Math.max(pair[0], pair[1]),
117                     AccurateMath.max(pair[0], pair[1]),
118                     Precision.EPSILON);
119             assertEquals("max(" + pair[1] + ", " + pair[0] + ")",
120                     Math.max(pair[1], pair[0]),
121                     AccurateMath.max(pair[1], pair[0]),
122                     Precision.EPSILON);
123         }
124     }
125 
126     @Test
127     public void testConstants() {
128         assertEquals(Math.PI, AccurateMath.PI, 1.0e-20);
129         assertEquals(Math.E, AccurateMath.E, 1.0e-20);
130     }
131 
132     @Test
133     public void testAtan2() {
134         double y1 = 1.2713504628280707e10;
135         double x1 = -5.674940885228782e-10;
136         assertEquals(Math.atan2(y1, x1), AccurateMath.atan2(y1, x1), 2 * Precision.EPSILON);
137         double y2 = 0.0;
138         double x2 = Double.POSITIVE_INFINITY;
139         assertEquals(Math.atan2(y2, x2), AccurateMath.atan2(y2, x2), Precision.SAFE_MIN);
140     }
141 
142     @Test
143     public void testHyperbolic() {
144         double maxErr = 0;
145         for (double x = -30; x < 30; x += 0.001) {
146             double tst = AccurateMath.sinh(x);
147             double ref = Math.sinh(x);
148             maxErr = AccurateMath.max(maxErr, AccurateMath.abs(ref - tst) / AccurateMath.ulp(ref));
149         }
150         assertEquals(0, maxErr, 2);
151 
152         maxErr = 0;
153         for (double x = -30; x < 30; x += 0.001) {
154             double tst = AccurateMath.cosh(x);
155             double ref = Math.cosh(x);
156             maxErr = AccurateMath.max(maxErr, AccurateMath.abs(ref - tst) / AccurateMath.ulp(ref));
157         }
158         assertEquals(0, maxErr, 2);
159 
160         maxErr = 0;
161         for (double x = -0.5; x < 0.5; x += 0.001) {
162             double tst = AccurateMath.tanh(x);
163             double ref = Math.tanh(x);
164             maxErr = AccurateMath.max(maxErr, AccurateMath.abs(ref - tst) / AccurateMath.ulp(ref));
165         }
166         assertEquals(0, maxErr, 4);
167     }
168 
169     @Test
170     public void testMath904() {
171         final double x = -1;
172         final double y = (5 + 1e-15) * 1e15;
173         assertEquals(Math.pow(x, y),
174                      AccurateMath.pow(x, y), 0);
175         assertEquals(Math.pow(x, -y),
176                 AccurateMath.pow(x, -y), 0);
177     }
178 
179     @Test
180     public void testMath905LargePositive() {
181         final double start = StrictMath.log(Double.MAX_VALUE);
182         final double endT = StrictMath.sqrt(2) * StrictMath.sqrt(Double.MAX_VALUE);
183         final double end = 2 * StrictMath.log(endT);
184 
185         double maxErr = 0;
186         for (double x = start; x < end; x += 1e-3) {
187             final double tst = AccurateMath.cosh(x);
188             final double ref = Math.cosh(x);
189             maxErr = AccurateMath.max(maxErr, AccurateMath.abs(ref - tst) / AccurateMath.ulp(ref));
190         }
191         assertEquals(0, maxErr, 3);
192 
193         for (double x = start; x < end; x += 1e-3) {
194             final double tst = AccurateMath.sinh(x);
195             final double ref = Math.sinh(x);
196             maxErr = AccurateMath.max(maxErr, AccurateMath.abs(ref - tst) / AccurateMath.ulp(ref));
197         }
198         assertEquals(0, maxErr, 3);
199     }
200 
201     @Test
202     public void testMath905LargeNegative() {
203         final double start = -StrictMath.log(Double.MAX_VALUE);
204         final double endT = StrictMath.sqrt(2) * StrictMath.sqrt(Double.MAX_VALUE);
205         final double end = -2 * StrictMath.log(endT);
206 
207         double maxErr = 0;
208         for (double x = start; x > end; x -= 1e-3) {
209             final double tst = AccurateMath.cosh(x);
210             final double ref = Math.cosh(x);
211             maxErr = AccurateMath.max(maxErr, AccurateMath.abs(ref - tst) / AccurateMath.ulp(ref));
212         }
213         assertEquals(0, maxErr, 3);
214 
215         for (double x = start; x > end; x -= 1e-3) {
216             final double tst = AccurateMath.sinh(x);
217             final double ref = Math.sinh(x);
218             maxErr = AccurateMath.max(maxErr, AccurateMath.abs(ref - tst) / AccurateMath.ulp(ref));
219         }
220         assertEquals(0, maxErr, 3);
221     }
222 
223     @Test
224     public void testMath1269() {
225         final double arg = 709.8125;
226         final double vM = Math.exp(arg);
227         final double vFM = AccurateMath.exp(arg);
228         assertTrue("exp(" + arg + ") is " + vFM + " instead of " + vM,
229                 Precision.equalsIncludingNaN(vM, vFM));
230     }
231 
232     @Test
233     public void testHyperbolicInverses() {
234         double maxErr = 0;
235         for (double x = -30; x < 30; x += 0.01) {
236             maxErr = AccurateMath.max(maxErr, AccurateMath.abs(x - AccurateMath.sinh(AccurateMath.asinh(x))) / (2 * AccurateMath.ulp(x)));
237         }
238         assertEquals(0, maxErr, 3);
239 
240         maxErr = 0;
241         for (double x = 1; x < 30; x += 0.01) {
242             maxErr = AccurateMath.max(maxErr, AccurateMath.abs(x - AccurateMath.cosh(AccurateMath.acosh(x))) / (2 * AccurateMath.ulp(x)));
243         }
244         assertEquals(0, maxErr, 2);
245 
246         maxErr = 0;
247         for (double x = -1 + Precision.EPSILON; x < 1 - Precision.EPSILON; x += 0.0001) {
248             maxErr = AccurateMath.max(maxErr, AccurateMath.abs(x - AccurateMath.tanh(AccurateMath.atanh(x))) / (2 * AccurateMath.ulp(x)));
249         }
250         assertEquals(0, maxErr, 2);
251     }
252 
253     @Test
254     public void testLogAccuracy() {
255         double maxerrulp = 0.0;
256 
257         for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
258             double x = Math.exp(generator.nextDouble() * 1416.0 - 708.0) * generator.nextDouble();
259             // double x = generator.nextDouble()*2.0;
260             double tst = AccurateMath.log(x);
261             double ref = DfpMath.log(field.newDfp(x)).toDouble();
262             double err = (tst - ref) / ref;
263 
264             if (err != 0.0) {
265                 double ulp = Math.abs(ref -
266                                       Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
267                 double errulp = field.newDfp(tst).subtract(DfpMath.log(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
268 //                System.out.println(x + "\t" + tst + "\t" + ref + "\t" + err + "\t" + errulp);
269 
270                 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
271             }
272         }
273 
274         assertTrue("log() had errors in excess of " + MAX_ERROR_ULP + " ULP", maxerrulp < MAX_ERROR_ULP);
275     }
276 
277     @Test
278     public void testLog10Accuracy() {
279         double maxerrulp = 0.0;
280 
281         for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
282             double x = Math.exp(generator.nextDouble() * 1416.0 - 708.0) * generator.nextDouble();
283             // double x = generator.nextDouble()*2.0;
284             double tst = AccurateMath.log10(x);
285             double ref = DfpMath.log(field.newDfp(x)).divide(DfpMath.log(field.newDfp("10"))).toDouble();
286             double err = (tst - ref) / ref;
287 
288             if (err != 0.0) {
289                 double ulp = Math.abs(ref -
290                                       Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
291                 double errulp = field.newDfp(tst).subtract(DfpMath.log(field.newDfp(x)).divide(DfpMath.log(field.newDfp("10")))).divide(field.newDfp(ulp)).toDouble();
292 //                System.out.println(x + "\t" + tst + "\t" + ref + "\t" + err + "\t" + errulp);
293 
294                 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
295             }
296         }
297 
298         assertTrue("log10() had errors in excess of " + MAX_ERROR_ULP + " ULP", maxerrulp < MAX_ERROR_ULP);
299     }
300 
301     @Test
302     public void testLog1pAccuracy() {
303         double maxerrulp = 0.0;
304 
305         for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
306             double x = Math.exp(generator.nextDouble() * 10.0 - 5.0) * generator.nextDouble();
307             // double x = generator.nextDouble()*2.0;
308             double tst = AccurateMath.log1p(x);
309             double ref = DfpMath.log(field.newDfp(x).add(field.getOne())).toDouble();
310             double err = (tst - ref) / ref;
311 
312             if (err != 0.0) {
313                 double ulp = Math.abs(ref -
314                                       Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
315                 double errulp = field.newDfp(tst).subtract(DfpMath.log(field.newDfp(x).add(field.getOne()))).divide(field.newDfp(ulp)).toDouble();
316 //                System.out.println(x + "\t" + tst + "\t" + ref + "\t" + err + "\t" + errulp);
317 
318                 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
319             }
320         }
321 
322         assertTrue("log1p() had errors in excess of " + MAX_ERROR_ULP + " ULP", maxerrulp < MAX_ERROR_ULP);
323     }
324 
325     @Test
326     public void testLog1pSpecialCases() {
327         assertTrue("Logp of -1.0 should be -Inf", Double.isInfinite(AccurateMath.log1p(-1.0)));
328     }
329 
330     @Test
331     public void testLogSpecialCases() {
332         assertEquals("Log of zero should be -Inf", Double.NEGATIVE_INFINITY, AccurateMath.log(0.0), 1.0);
333         assertEquals("Log of -zero should be -Inf", Double.NEGATIVE_INFINITY, AccurateMath.log(-0.0), 1.0);
334         assertTrue("Log of NaN should be NaN", Double.isNaN(AccurateMath.log(Double.NaN)));
335         assertTrue("Log of negative number should be NaN", Double.isNaN(AccurateMath.log(-1.0)));
336         assertEquals("Log of Double.MIN_VALUE should be -744.4400719213812", -744.4400719213812, AccurateMath.log(Double.MIN_VALUE), Precision.EPSILON);
337         assertEquals("Log of infinity should be infinity", Double.POSITIVE_INFINITY, AccurateMath.log(Double.POSITIVE_INFINITY), 1.0);
338     }
339 
340     @Test
341     public void testExpSpecialCases() {
342         // Smallest value that will round up to Double.MIN_VALUE
343         assertEquals(Double.MIN_VALUE, AccurateMath.exp(-745.1332191019411), Precision.EPSILON);
344         assertEquals("exp(-745.1332191019412) should be 0.0", 0.0, AccurateMath.exp(-745.1332191019412), Precision.EPSILON);
345         assertTrue("exp of NaN should be NaN", Double.isNaN(AccurateMath.exp(Double.NaN)));
346         assertEquals("exp of infinity should be infinity", Double.POSITIVE_INFINITY, AccurateMath.exp(Double.POSITIVE_INFINITY), 1.0);
347         assertEquals("exp of -infinity should be 0.0", 0.0, AccurateMath.exp(Double.NEGATIVE_INFINITY), Precision.EPSILON);
348         assertEquals("exp(1) should be Math.E", Math.E, AccurateMath.exp(1.0), Precision.EPSILON);
349     }
350 
351     @Test
352     public void testPowSpecialCases() {
353         final double EXACT = -1.0;
354 
355         assertEquals("pow(-1, 0) should be 1.0", 1.0, AccurateMath.pow(-1.0, 0.0), Precision.EPSILON);
356         assertEquals("pow(-1, -0) should be 1.0", 1.0, AccurateMath.pow(-1.0, -0.0), Precision.EPSILON);
357         assertEquals("pow(PI, 1.0) should be PI", AccurateMath.PI, AccurateMath.pow(AccurateMath.PI, 1.0), Precision.EPSILON);
358         assertEquals("pow(-PI, 1.0) should be -PI", -AccurateMath.PI, AccurateMath.pow(-AccurateMath.PI, 1.0), Precision.EPSILON);
359         assertTrue("pow(PI, NaN) should be NaN", Double.isNaN(AccurateMath.pow(Math.PI, Double.NaN)));
360         assertTrue("pow(NaN, PI) should be NaN", Double.isNaN(AccurateMath.pow(Double.NaN, Math.PI)));
361         assertEquals("pow(2.0, Infinity) should be Infinity", Double.POSITIVE_INFINITY, AccurateMath.pow(2.0, Double.POSITIVE_INFINITY), 1.0);
362         assertEquals("pow(0.5, -Infinity) should be Infinity", Double.POSITIVE_INFINITY, AccurateMath.pow(0.5, Double.NEGATIVE_INFINITY), 1.0);
363         assertEquals("pow(0.5, Infinity) should be 0.0", 0.0, AccurateMath.pow(0.5, Double.POSITIVE_INFINITY), Precision.EPSILON);
364         assertEquals("pow(2.0, -Infinity) should be 0.0", 0.0, AccurateMath.pow(2.0, Double.NEGATIVE_INFINITY), Precision.EPSILON);
365         assertEquals("pow(0.0, 0.5) should be 0.0", 0.0, AccurateMath.pow(0.0, 0.5), Precision.EPSILON);
366         assertEquals("pow(Infinity, -0.5) should be 0.0", 0.0, AccurateMath.pow(Double.POSITIVE_INFINITY, -0.5), Precision.EPSILON);
367         assertEquals("pow(0.0, -0.5) should be Inf", Double.POSITIVE_INFINITY, AccurateMath.pow(0.0, -0.5), 1.0);
368         assertEquals("pow(Inf, 0.5) should be Inf", Double.POSITIVE_INFINITY, AccurateMath.pow(Double.POSITIVE_INFINITY, 0.5), 1.0);
369         assertEquals("pow(-0.0, -3.0) should be -Inf", Double.NEGATIVE_INFINITY, AccurateMath.pow(-0.0, -3.0), 1.0);
370         assertEquals("pow(-0.0, Infinity) should be 0.0", 0.0, AccurateMath.pow(-0.0, Double.POSITIVE_INFINITY), Precision.EPSILON);
371         assertTrue("pow(-0.0, NaN) should be NaN", Double.isNaN(AccurateMath.pow(-0.0, Double.NaN)));
372         assertEquals("pow(-0.0, -tiny) should be Infinity", Double.POSITIVE_INFINITY, AccurateMath.pow(-0.0, -Double.MIN_VALUE), 1.0);
373         assertEquals("pow(-0.0, -huge) should be Infinity", Double.POSITIVE_INFINITY, AccurateMath.pow(-0.0, -Double.MAX_VALUE), 1.0);
374         assertEquals("pow(-Inf, 3.0) should be -Inf", Double.NEGATIVE_INFINITY, AccurateMath.pow(Double.NEGATIVE_INFINITY, 3.0), 1.0);
375         assertEquals("pow(-Inf, -3.0) should be -0.0", -0.0, AccurateMath.pow(Double.NEGATIVE_INFINITY, -3.0), EXACT);
376         assertEquals("pow(-0.0, -3.5) should be Inf", Double.POSITIVE_INFINITY, AccurateMath.pow(-0.0, -3.5), 1.0);
377         assertEquals("pow(Inf, 3.5) should be Inf", Double.POSITIVE_INFINITY, AccurateMath.pow(Double.POSITIVE_INFINITY, 3.5), 1.0);
378         assertEquals("pow(-2.0, 3.0) should be -8.0", -8.0, AccurateMath.pow(-2.0, 3.0), Precision.EPSILON);
379         assertTrue("pow(-2.0, 3.5) should be NaN", Double.isNaN(AccurateMath.pow(-2.0, 3.5)));
380         assertTrue("pow(NaN, -Infinity) should be NaN", Double.isNaN(AccurateMath.pow(Double.NaN, Double.NEGATIVE_INFINITY)));
381         assertEquals("pow(NaN, 0.0) should be 1.0", 1.0, AccurateMath.pow(Double.NaN, 0.0), Precision.EPSILON);
382         assertEquals("pow(-Infinity, -Infinity) should be 0.0", 0.0, AccurateMath.pow(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY), Precision.EPSILON);
383         assertEquals("pow(-huge, -huge) should be 0.0", 0.0, AccurateMath.pow(-Double.MAX_VALUE, -Double.MAX_VALUE), Precision.EPSILON);
384         assertTrue("pow(-huge,  huge) should be +Inf", Double.isInfinite(AccurateMath.pow(-Double.MAX_VALUE, Double.MAX_VALUE)));
385         assertTrue("pow(NaN, -Infinity) should be NaN", Double.isNaN(AccurateMath.pow(Double.NaN, Double.NEGATIVE_INFINITY)));
386         assertEquals("pow(NaN, -0.0) should be 1.0", 1.0, AccurateMath.pow(Double.NaN, -0.0), Precision.EPSILON);
387         assertEquals("pow(-Infinity, -Infinity) should be 0.0", 0.0, AccurateMath.pow(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY), Precision.EPSILON);
388         assertEquals("pow(-huge, -huge) should be 0.0", 0.0, AccurateMath.pow(-Double.MAX_VALUE, -Double.MAX_VALUE), Precision.EPSILON);
389         assertEquals("pow(-huge,  huge) should be +Inf", Double.POSITIVE_INFINITY, AccurateMath.pow(-Double.MAX_VALUE, Double.MAX_VALUE), 1.0);
390 
391         // Added tests for a 100% coverage
392 
393         assertTrue("pow(+Inf, NaN) should be NaN", Double.isNaN(AccurateMath.pow(Double.POSITIVE_INFINITY, Double.NaN)));
394         assertTrue("pow(1.0, +Inf) should be NaN", Double.isNaN(AccurateMath.pow(1.0, Double.POSITIVE_INFINITY)));
395         assertTrue("pow(-Inf, NaN) should be NaN", Double.isNaN(AccurateMath.pow(Double.NEGATIVE_INFINITY, Double.NaN)));
396         assertEquals("pow(-Inf, -1.0) should be -0.0", -0.0, AccurateMath.pow(Double.NEGATIVE_INFINITY, -1.0), EXACT);
397         assertEquals("pow(-Inf, -2.0) should be 0.0", 0.0, AccurateMath.pow(Double.NEGATIVE_INFINITY, -2.0), EXACT);
398         assertEquals("pow(-Inf, 1.0) should be -Inf", Double.NEGATIVE_INFINITY, AccurateMath.pow(Double.NEGATIVE_INFINITY, 1.0), 1.0);
399         assertEquals("pow(-Inf, 2.0) should be +Inf", Double.POSITIVE_INFINITY, AccurateMath.pow(Double.NEGATIVE_INFINITY, 2.0), 1.0);
400         assertTrue("pow(1.0, -Inf) should be NaN", Double.isNaN(AccurateMath.pow(1.0, Double.NEGATIVE_INFINITY)));
401         assertEquals("pow(-0.0, 1.0) should be -0.0", -0.0, AccurateMath.pow(-0.0, 1.0), EXACT);
402         assertEquals("pow(0.0, 1.0) should be 0.0", 0.0, AccurateMath.pow(0.0, 1.0), EXACT);
403         assertEquals("pow(0.0, +Inf) should be 0.0", 0.0, AccurateMath.pow(0.0, Double.POSITIVE_INFINITY), EXACT);
404         assertEquals("pow(-0.0, even) should be 0.0", 0.0, AccurateMath.pow(-0.0, 6.0), EXACT);
405         assertEquals("pow(-0.0, odd) should be -0.0", -0.0, AccurateMath.pow(-0.0, 13.0), EXACT);
406         assertEquals("pow(-0.0, -even) should be +Inf", Double.POSITIVE_INFINITY, AccurateMath.pow(-0.0, -6.0), EXACT);
407         assertEquals("pow(-0.0, -odd) should be -Inf", Double.NEGATIVE_INFINITY, AccurateMath.pow(-0.0, -13.0), EXACT);
408         assertEquals("pow(-2.0, 4.0) should be 16.0", 16.0, AccurateMath.pow(-2.0, 4.0), EXACT);
409         assertEquals("pow(-2.0, 4.5) should be NaN", Double.NaN, AccurateMath.pow(-2.0, 4.5), EXACT);
410         assertEquals("pow(-0.0, -0.0) should be 1.0", 1.0, AccurateMath.pow(-0.0, -0.0), EXACT);
411         assertEquals("pow(-0.0, 0.0) should be 1.0", 1.0, AccurateMath.pow(-0.0, 0.0), EXACT);
412         assertEquals("pow(0.0, -0.0) should be 1.0", 1.0, AccurateMath.pow(0.0, -0.0), EXACT);
413         assertEquals("pow(0.0, 0.0) should be 1.0", 1.0, AccurateMath.pow(0.0, 0.0), EXACT);
414     }
415 
416     @Test(timeout = 20000L)
417     public void testPowAllSpecialCases() {
418         final double EXACT = -1.0;
419         final double[] DOUBLES = new double[] {
420             Double.NEGATIVE_INFINITY, -0.0, Double.NaN, 0.0, Double.POSITIVE_INFINITY,
421             Long.MIN_VALUE, Integer.MIN_VALUE, Short.MIN_VALUE, Byte.MIN_VALUE,
422             -(double)Long.MIN_VALUE, -(double)Integer.MIN_VALUE, -(double)Short.MIN_VALUE, -(double)Byte.MIN_VALUE,
423             Byte.MAX_VALUE, Short.MAX_VALUE, Integer.MAX_VALUE, Long.MAX_VALUE,
424             -Byte.MAX_VALUE, -Short.MAX_VALUE, -Integer.MAX_VALUE, -Long.MAX_VALUE,
425             Float.MAX_VALUE, Double.MAX_VALUE, Double.MIN_VALUE, Float.MIN_VALUE,
426             -Float.MAX_VALUE, -Double.MAX_VALUE, -Double.MIN_VALUE, -Float.MIN_VALUE,
427             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,
428             -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
429         };
430 
431         // Special cases from Math.pow javadoc:
432         // If the second argument is positive or negative zero, then the result is 1.0.
433         for (double d : DOUBLES) {
434             assertEquals(1.0, AccurateMath.pow(d, 0.0), EXACT);
435         }
436         for (double d : DOUBLES) {
437             assertEquals(1.0, AccurateMath.pow(d, -0.0), EXACT);
438         }
439         // If the second argument is 1.0, then the result is the same as the first argument.
440         for (double d : DOUBLES) {
441             assertEquals(d, AccurateMath.pow(d, 1.0), EXACT);
442         }
443         // If the second argument is NaN, then the result is NaN.
444         for (double d : DOUBLES) {
445             assertEquals(Double.NaN, AccurateMath.pow(d, Double.NaN), EXACT);
446         }
447         // If the first argument is NaN and the second argument is nonzero, then the result is NaN.
448         for (double i : DOUBLES) {
449             if (i != 0.0) {
450                 assertEquals(Double.NaN, AccurateMath.pow(Double.NaN, i), EXACT);
451             }
452         }
453         // If the absolute value of the first argument is greater than 1 and the second argument is positive infinity, or
454         // the absolute value of the first argument is less than 1 and the second argument is negative infinity, then the result is positive infinity.
455         for (double d : DOUBLES) {
456             if (Math.abs(d) > 1.0) {
457                 assertEquals(Double.POSITIVE_INFINITY, AccurateMath.pow(d, Double.POSITIVE_INFINITY), EXACT);
458             }
459         }
460         for (double d : DOUBLES) {
461             if (Math.abs(d) < 1.0) {
462                 assertEquals(Double.POSITIVE_INFINITY, AccurateMath.pow(d, Double.NEGATIVE_INFINITY), EXACT);
463             }
464         }
465         // If the absolute value of the first argument is greater than 1 and the second argument is negative infinity, or
466         // the absolute value of the first argument is less than 1 and the second argument is positive infinity, then the result is positive zero.
467         for (double d : DOUBLES) {
468             if (Math.abs(d) > 1.0) {
469                 assertEquals(0.0, AccurateMath.pow(d, Double.NEGATIVE_INFINITY), EXACT);
470             }
471         }
472         for (double d : DOUBLES) {
473             if (Math.abs(d) < 1.0) {
474                 assertEquals(0.0, AccurateMath.pow(d, Double.POSITIVE_INFINITY), EXACT);
475             }
476         }
477         // If the absolute value of the first argument equals 1 and the second argument is infinite, then the result is NaN.
478         assertEquals(Double.NaN, AccurateMath.pow(1.0, Double.POSITIVE_INFINITY), EXACT);
479         assertEquals(Double.NaN, AccurateMath.pow(1.0, Double.NEGATIVE_INFINITY), EXACT);
480         assertEquals(Double.NaN, AccurateMath.pow(-1.0, Double.POSITIVE_INFINITY), EXACT);
481         assertEquals(Double.NaN, AccurateMath.pow(-1.0, Double.NEGATIVE_INFINITY), EXACT);
482         // If the first argument is positive zero and the second argument is greater than zero, or
483         // the first argument is positive infinity and the second argument is less than zero, then the result is positive zero.
484         for (double i : DOUBLES) {
485             if (i > 0.0) {
486                 assertEquals(0.0, AccurateMath.pow(0.0, i), EXACT);
487             }
488         }
489         for (double i : DOUBLES) {
490             if (i < 0.0) {
491                 assertEquals(0.0, AccurateMath.pow(Double.POSITIVE_INFINITY, i), EXACT);
492             }
493         }
494         // If the first argument is positive zero and the second argument is less than zero, or
495         // the first argument is positive infinity and the second argument is greater than zero, then the result is positive infinity.
496         for (double i : DOUBLES) {
497             if (i < 0.0) {
498                 assertEquals(Double.POSITIVE_INFINITY, AccurateMath.pow(0.0, i), EXACT);
499             }
500         }
501         for (double i : DOUBLES) {
502             if (i > 0.0) {
503                 assertEquals(Double.POSITIVE_INFINITY, AccurateMath.pow(Double.POSITIVE_INFINITY, i), EXACT);
504             }
505         }
506         // If the first argument is negative zero and the second argument is greater than zero but not a finite odd integer, or
507         // 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.
508         for (double i : DOUBLES) {
509             if (i > 0.0 && (Double.isInfinite(i) || i % 2.0 == 0.0)) {
510                 assertEquals(0.0, AccurateMath.pow(-0.0, i), EXACT);
511             }
512         }
513         for (double i : DOUBLES) {
514             if (i < 0.0 && (Double.isInfinite(i) || i % 2.0 == 0.0)) {
515                 assertEquals(0.0, AccurateMath.pow(Double.NEGATIVE_INFINITY, i), EXACT);
516             }
517         }
518         // If the first argument is negative zero and the second argument is a positive finite odd integer, or
519         // the first argument is negative infinity and the second argument is a negative finite odd integer, then the result is negative zero.
520         for (double i : DOUBLES) {
521             if (i > 0.0 && i % 2.0 == 1.0) {
522                 assertEquals(-0.0, AccurateMath.pow(-0.0, i), EXACT);
523             }
524         }
525         for (double i : DOUBLES) {
526             if (i < 0.0 && i % 2.0 == -1.0) {
527                 assertEquals(-0.0, AccurateMath.pow(Double.NEGATIVE_INFINITY, i), EXACT);
528             }
529         }
530         // If the first argument is negative zero and the second argument is less than zero but not a finite odd integer, or
531         // 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.
532         for (double i : DOUBLES) {
533             if (i > 0.0 && (Double.isInfinite(i) || i % 2.0 == 0.0)) {
534                 assertEquals(Double.POSITIVE_INFINITY, AccurateMath.pow(Double.NEGATIVE_INFINITY, i), EXACT);
535             }
536         }
537         for (double i : DOUBLES) {
538             if (i < 0.0 && (Double.isInfinite(i) || i % 2.0 == 0.0)) {
539                 assertEquals(Double.POSITIVE_INFINITY, AccurateMath.pow(-0.0, i), EXACT);
540             }
541         }
542         // If the first argument is negative zero and the second argument is a negative finite odd integer, or
543         // the first argument is negative infinity and the second argument is a positive finite odd integer, then the result is negative infinity.
544         for (double i : DOUBLES) {
545             if (i > 0.0 && i % 2.0 == 1.0) {
546                 assertEquals(Double.NEGATIVE_INFINITY, AccurateMath.pow(Double.NEGATIVE_INFINITY, i), EXACT);
547             }
548         }
549         for (double i : DOUBLES) {
550             if (i < 0.0 && i % 2.0 == -1.0) {
551                 assertEquals(Double.NEGATIVE_INFINITY, AccurateMath.pow(-0.0, i), EXACT);
552             }
553         }
554         for (double d : DOUBLES) {
555             // If the first argument is finite and less than zero
556             if (d < 0.0 && Math.abs(d) <= Double.MAX_VALUE) {
557                 for (double i : DOUBLES) {
558                     if (Math.abs(i) <= Double.MAX_VALUE) {
559                         // 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
560                         if (i % 2.0 == 0.0) {
561                             assertEquals(AccurateMath.pow(-d, i), AccurateMath.pow(d, i), EXACT);
562                         } else if (Math.abs(i) % 2.0 == 1.0) {
563                             // 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
564                             assertEquals(-AccurateMath.pow(-d, i), AccurateMath.pow(d, i), EXACT);
565                         } else {
566                             // if the second argument is finite and not an integer, then the result is NaN.
567                             assertEquals(Double.NaN, AccurateMath.pow(d, i), EXACT);
568                         }
569                     }
570                 }
571             }
572         }
573         // If both arguments are integers, then the result is exactly equal to the mathematical result of raising the first argument to the power
574         // of the second argument if that result can in fact be represented exactly as a double value.
575         final int TOO_BIG_TO_CALCULATE = 18; // This value is empirical: 2^18 > 200.000 resulting bits after raising d to power i.
576         for (double d : DOUBLES) {
577             if (d % 1.0 == 0.0) {
578                 boolean dNegative = Double.doubleToRawLongBits(d) < 0L;
579                 for (double i : DOUBLES) {
580                     if (i % 1.0 == 0.0) {
581                         BigInteger bd = BigDecimal.valueOf(d).toBigInteger().abs();
582                         BigInteger bi = BigDecimal.valueOf(i).toBigInteger().abs();
583                         double expected;
584                         if (bd.bitLength() > 1 && bi.bitLength() > 1 && 32 - Integer.numberOfLeadingZeros(bd.bitLength()) + bi.bitLength() > TOO_BIG_TO_CALCULATE) {
585                             // Result would be too big.
586                             expected = i < 0.0 ? 0.0 : Double.POSITIVE_INFINITY;
587                         } else {
588                             BigInteger res = ArithmeticUtils.pow(bd, bi);
589                             if (i >= 0.0) {
590                                 expected = res.doubleValue();
591                             } else if (res.signum() == 0) {
592                                 expected = Double.POSITIVE_INFINITY;
593                             } else {
594                                 expected = BigDecimal.ONE.divide(new BigDecimal(res), 1024, RoundingMode.HALF_UP).doubleValue();
595                             }
596                         }
597                         if (dNegative && bi.testBit(0)) {
598                             expected = -expected;
599                         }
600                         assertEquals(d + "^" + i + "=" + expected + ", Math.pow=" + Math.pow(d, i), expected, AccurateMath.pow(d, i), expected == 0.0 || Double.isInfinite(expected) || Double.isNaN(expected) ? EXACT : 2.0 * Math.ulp(expected));
601                     }
602                 }
603             }
604         }
605     }
606 
607     @Test
608     public void testPowLargeIntegralDouble() {
609         double y = AccurateMath.scalb(1.0, 65);
610         assertEquals(Double.POSITIVE_INFINITY, AccurateMath.pow(AccurateMath.nextUp(1.0), y),    1.0);
611         assertEquals(1.0,                      AccurateMath.pow(1.0, y),                     1.0);
612         assertEquals(0.0,                      AccurateMath.pow(AccurateMath.nextDown(1.0), y),  1.0);
613         assertEquals(0.0,                      AccurateMath.pow(AccurateMath.nextUp(-1.0), y),   1.0);
614         assertEquals(1.0,                      AccurateMath.pow(-1.0, y),                    1.0);
615         assertEquals(Double.POSITIVE_INFINITY, AccurateMath.pow(AccurateMath.nextDown(-1.0), y), 1.0);
616     }
617 
618     @Test
619     public void testAtan2SpecialCases() {
620 
621         assertTrue("atan2(NaN, 0.0) should be NaN", Double.isNaN(AccurateMath.atan2(Double.NaN, 0.0)));
622         assertTrue("atan2(0.0, NaN) should be NaN", Double.isNaN(AccurateMath.atan2(0.0, Double.NaN)));
623 
624         final double pinf = Double.POSITIVE_INFINITY;
625         final double ninf = Double.NEGATIVE_INFINITY;
626         // Test using fractions of pi
627         assertAtan2(+0.0,  0.0,  0.0, 1.0);
628         assertAtan2(+0.0, -0.0,  1.0, 1.0);
629         assertAtan2(+0.0,  0.1,  0.0, 1.0);
630         assertAtan2(+0.0, -0.1,  1.0, 1.0);
631         assertAtan2(+0.0, pinf,  0.0, 1.0);
632         assertAtan2(+0.0, ninf,  1.0, 1.0);
633         assertAtan2(-0.0,  0.0, -0.0, 1.0);
634         assertAtan2(-0.0, -0.0, -1.0, 1.0);
635         assertAtan2(-0.0,  0.1, -0.0, 1.0);
636         assertAtan2(-0.0, -0.1, -1.0, 1.0);
637         assertAtan2(-0.0, pinf, -0.0, 1.0);
638         assertAtan2(-0.0, ninf, -1.0, 1.0);
639         assertAtan2(+0.1,  0.0,  1.0, 2.0);
640         assertAtan2(+0.1, -0.0,  1.0, 2.0);
641         assertAtan2(+0.1,  0.1,  1.0, 4.0);
642         assertAtan2(+0.1, -0.1,  3.0, 4.0);
643         assertAtan2(+0.1, pinf,  0.0, 1.0);
644         assertAtan2(+0.1, ninf,  1.0, 1.0);
645         assertAtan2(-0.1,  0.0, -1.0, 2.0);
646         assertAtan2(-0.1, -0.0, -1.0, 2.0);
647         assertAtan2(-0.1,  0.1, -1.0, 4.0);
648         assertAtan2(-0.1, -0.1, -3.0, 4.0);
649         assertAtan2(-0.1, pinf, -0.0, 1.0);
650         assertAtan2(-0.1, ninf, -1.0, 1.0);
651         assertAtan2(pinf,  0.0,  1.0, 2.0);
652         assertAtan2(pinf, -0.0,  1.0, 2.0);
653         assertAtan2(pinf,  0.1,  1.0, 2.0);
654         assertAtan2(pinf, -0.1,  1.0, 2.0);
655         assertAtan2(pinf, pinf,  1.0, 4.0);
656         assertAtan2(pinf, ninf,  3.0, 4.0);
657         assertAtan2(ninf,  0.0, -1.0, 2.0);
658         assertAtan2(ninf, -0.0, -1.0, 2.0);
659         assertAtan2(ninf,  0.1, -1.0, 2.0);
660         assertAtan2(ninf, -0.1, -1.0, 2.0);
661         assertAtan2(ninf, pinf, -1.0, 4.0);
662         assertAtan2(ninf, ninf, -3.0, 4.0);
663     }
664 
665     /**
666      * Assert the atan2(y, x) value is a fraction of pi.
667      *
668      * @param y ordinate
669      * @param x abscissa
670      * @param numerator numerator of the fraction of pi (including the sign)
671      * @param denominator denominator of the fraction of pi
672      */
673     private static void assertAtan2(double y, double x, double numerator, double denominator) {
674         final double v = AccurateMath.atan2(y, x);
675         if (numerator == 0) {
676             // Exact including the sign.
677             Assertions.assertEquals(numerator, v,
678                 () -> String.format("atan2(%s, %s) should be %s but was %s", y, x, numerator, v));
679         } else {
680             final double expected = AccurateMath.PI * numerator / denominator;
681             Assertions.assertEquals(expected, v, Precision.EPSILON,
682                 () -> String.format("atan2(%s, %s) should be pi * %s / %s", y, x, numerator, denominator));
683         }
684     }
685 
686     @Test
687     public void testPowAccuracy() {
688         double maxerrulp = 0.0;
689 
690         for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
691             double x = (generator.nextDouble() * 2.0 + 0.25);
692             double y = (generator.nextDouble() * 1200.0 - 600.0) * generator.nextDouble();
693             /*
694              * double x = AccurateMath.floor(generator.nextDouble()*1024.0 - 512.0); double
695              * y; if (x != 0) y = AccurateMath.floor(512.0 / AccurateMath.abs(x)); else
696              * y = generator.nextDouble()*1200.0; y = y - y/2; x = AccurateMath.pow(2.0, x) *
697              * generator.nextDouble(); y = y * generator.nextDouble();
698              */
699 
700             // double x = generator.nextDouble()*2.0;
701             double tst = AccurateMath.pow(x, y);
702             double ref = DfpMath.pow(field.newDfp(x), field.newDfp(y)).toDouble();
703             double err = (tst - ref) / ref;
704 
705             if (err != 0) {
706                 double ulp = Math.abs(ref -
707                                       Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
708                 double errulp = field.newDfp(tst).subtract(DfpMath.pow(field.newDfp(x), field.newDfp(y))).divide(field.newDfp(ulp)).toDouble();
709 //                System.out.println(x + "\t" + y + "\t" + tst + "\t" + ref + "\t" + err + "\t" + errulp);
710 
711                 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
712             }
713         }
714 
715         assertTrue("pow() had errors in excess of " + MAX_ERROR_ULP + " ULP", maxerrulp < MAX_ERROR_ULP);
716     }
717 
718     @Test
719     public void testExpAccuracy() {
720         double maxerrulp = 0.0;
721 
722         for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
723             /* double x = 1.0 + i/1024.0/2.0; */
724             double x = ((generator.nextDouble() * 1416.0) - 708.0) * generator.nextDouble();
725             // double x = (generator.nextDouble() * 20.0) - 10.0;
726             // double x = ((generator.nextDouble() * 2.0) - 1.0) * generator.nextDouble();
727             /* double x = 3.0 / 512.0 * i - 3.0; */
728             double tst = AccurateMath.exp(x);
729             double ref = DfpMath.exp(field.newDfp(x)).toDouble();
730             double err = (tst - ref) / ref;
731 
732             if (err != 0) {
733                 double ulp = Math.abs(ref -
734                                       Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
735                 double errulp = field.newDfp(tst).subtract(DfpMath.exp(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
736 //                System.out.println(x + "\t" + tst + "\t" + ref + "\t" + err + "\t" + errulp);
737 
738                 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
739             }
740         }
741 
742         assertTrue("exp() had errors in excess of " + MAX_ERROR_ULP + " ULP", maxerrulp < MAX_ERROR_ULP);
743     }
744 
745     @Test
746     public void testSinAccuracy() {
747         double maxerrulp = 0.0;
748 
749         for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
750             /* double x = 1.0 + i/1024.0/2.0; */
751             // double x = ((generator.nextDouble() * 1416.0) - 708.0) * generator.nextDouble();
752             double x = ((generator.nextDouble() * Math.PI) - Math.PI / 2.0) *
753                        Math.pow(2, 21) * generator.nextDouble();
754             // double x = (generator.nextDouble() * 20.0) - 10.0;
755             // double x = ((generator.nextDouble() * 2.0) - 1.0) * generator.nextDouble();
756             /* double x = 3.0 / 512.0 * i - 3.0; */
757             double tst = AccurateMath.sin(x);
758             double ref = DfpMath.sin(field.newDfp(x)).toDouble();
759             double err = (tst - ref) / ref;
760 
761             if (err != 0) {
762                 double ulp = Math.abs(ref -
763                                       Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
764                 double errulp = field.newDfp(tst).subtract(DfpMath.sin(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
765 //                System.out.println(x + "\t" + tst + "\t" + ref + "\t" + err + "\t" + errulp);
766 
767                 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
768             }
769         }
770 
771         assertTrue("sin() had errors in excess of " + MAX_ERROR_ULP + " ULP", maxerrulp < MAX_ERROR_ULP);
772     }
773 
774     @Test
775     public void testCosAccuracy() {
776         double maxerrulp = 0.0;
777 
778         for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
779             /* double x = 1.0 + i/1024.0/2.0; */
780             // double x = ((generator.nextDouble() * 1416.0) - 708.0) * generator.nextDouble();
781             double x = ((generator.nextDouble() * Math.PI) - Math.PI / 2.0) *
782                        Math.pow(2, 21) * generator.nextDouble();
783             // double x = (generator.nextDouble() * 20.0) - 10.0;
784             // double x = ((generator.nextDouble() * 2.0) - 1.0) * generator.nextDouble();
785             /* double x = 3.0 / 512.0 * i - 3.0; */
786             double tst = AccurateMath.cos(x);
787             double ref = DfpMath.cos(field.newDfp(x)).toDouble();
788             double err = (tst - ref) / ref;
789 
790             if (err != 0) {
791                 double ulp = Math.abs(ref -
792                                       Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
793                 double errulp = field.newDfp(tst).subtract(DfpMath.cos(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
794 //                System.out.println(x + "\t" + tst + "\t" + ref + "\t" + err + "\t" + errulp);
795 
796                 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
797             }
798         }
799 
800         assertTrue("cos() had errors in excess of " + MAX_ERROR_ULP + " ULP", maxerrulp < MAX_ERROR_ULP);
801     }
802 
803     @Test
804     public void testTanAccuracy() {
805         double maxerrulp = 0.0;
806 
807         for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
808             /* double x = 1.0 + i/1024.0/2.0; */
809             // double x = ((generator.nextDouble() * 1416.0) - 708.0) * generator.nextDouble();
810             double x = ((generator.nextDouble() * Math.PI) - Math.PI / 2.0) *
811                        Math.pow(2, 12) * generator.nextDouble();
812             // double x = (generator.nextDouble() * 20.0) - 10.0;
813             // double x = ((generator.nextDouble() * 2.0) - 1.0) * generator.nextDouble();
814             /* double x = 3.0 / 512.0 * i - 3.0; */
815             double tst = AccurateMath.tan(x);
816             double ref = DfpMath.tan(field.newDfp(x)).toDouble();
817             double err = (tst - ref) / ref;
818 
819             if (err != 0) {
820                 double ulp = Math.abs(ref -
821                                       Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
822                 double errulp = field.newDfp(tst).subtract(DfpMath.tan(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
823 //                System.out.println(x + "\t" + tst + "\t" + ref + "\t" + err + "\t" + errulp);
824 
825                 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
826             }
827         }
828 
829         assertTrue("tan() had errors in excess of " + MAX_ERROR_ULP + " ULP", maxerrulp < MAX_ERROR_ULP);
830     }
831 
832     @Test
833     public void testAtanAccuracy() {
834         double maxerrulp = 0.0;
835 
836         for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
837             /* double x = 1.0 + i/1024.0/2.0; */
838             // double x = ((generator.nextDouble() * 1416.0) - 708.0) * generator.nextDouble();
839             // double x = ((generator.nextDouble() * Math.PI) - Math.PI/2.0) *
840             // generator.nextDouble();
841             double x = ((generator.nextDouble() * 16.0) - 8.0) * generator.nextDouble();
842 
843             // double x = (generator.nextDouble() * 20.0) - 10.0;
844             // double x = ((generator.nextDouble() * 2.0) - 1.0) * generator.nextDouble();
845             /* double x = 3.0 / 512.0 * i - 3.0; */
846             double tst = AccurateMath.atan(x);
847             double ref = DfpMath.atan(field.newDfp(x)).toDouble();
848             double err = (tst - ref) / ref;
849 
850             if (err != 0) {
851                 double ulp = Math.abs(ref -
852                                       Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
853                 double errulp = field.newDfp(tst).subtract(DfpMath.atan(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
854 //                System.out.println(x + "\t" + tst + "\t" + ref + "\t" + err + "\t" + errulp);
855 
856                 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
857             }
858         }
859 
860         assertTrue("atan() had errors in excess of " + MAX_ERROR_ULP + " ULP", maxerrulp < MAX_ERROR_ULP);
861     }
862 
863     @Test
864     public void testAtan2Accuracy() {
865         double maxerrulp = 0.0;
866 
867         for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
868             /* double x = 1.0 + i/1024.0/2.0; */
869             // double x = ((generator.nextDouble() * 1416.0) - 708.0) * generator.nextDouble();
870             double x = generator.nextDouble() - 0.5;
871             double y = generator.nextDouble() - 0.5;
872             // double x = (generator.nextDouble() * 20.0) - 10.0;
873             // double x = ((generator.nextDouble() * 2.0) - 1.0) * generator.nextDouble();
874             /* double x = 3.0 / 512.0 * i - 3.0; */
875             double tst = AccurateMath.atan2(y, x);
876             Dfp refdfp = DfpMath.atan(field.newDfp(y).divide(field.newDfp(x)));
877             /* Make adjustments for sign */
878             if (x < 0.0) {
879                 if (y > 0.0) {
880                     refdfp = field.getPi().add(refdfp);
881                 } else {
882                     refdfp = refdfp.subtract(field.getPi());
883                 }
884             }
885 
886             double ref = refdfp.toDouble();
887             double err = (tst - ref) / ref;
888 
889             if (err != 0) {
890                 double ulp = Math.abs(ref -
891                                       Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
892                 double errulp = field.newDfp(tst).subtract(refdfp).divide(field.newDfp(ulp)).toDouble();
893 //                System.out.println(x + "\t" + y + "\t" + tst + "\t" + ref + "\t" + errulp);
894 
895                 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
896             }
897         }
898 
899         assertTrue("atan2() had errors in excess of " + MAX_ERROR_ULP + " ULP", maxerrulp < MAX_ERROR_ULP);
900     }
901 
902     @Test
903     public void testExpm1Accuracy() {
904         double maxerrulp = 0.0;
905 
906         for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
907             /* double x = 1.0 + i/1024.0/2.0; */
908             // double x = (generator.nextDouble() * 20.0) - 10.0;
909             double x = ((generator.nextDouble() * 16.0) - 8.0) * generator.nextDouble();
910             /* double x = 3.0 / 512.0 * i - 3.0; */
911             double tst = AccurateMath.expm1(x);
912             double ref = DfpMath.exp(field.newDfp(x)).subtract(field.getOne()).toDouble();
913             double err = (tst - ref) / ref;
914 
915             if (err != 0) {
916                 double ulp = Math.abs(ref -
917                                       Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
918                 double errulp = field.newDfp(tst).subtract(DfpMath.exp(field.newDfp(x)).subtract(field.getOne())).divide(field.newDfp(ulp)).toDouble();
919 //                System.out.println(x + "\t" + tst + "\t" + ref + "\t" + err + "\t" + errulp);
920 
921                 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
922             }
923         }
924 
925         assertTrue("expm1() had errors in excess of " + MAX_ERROR_ULP + " ULP", maxerrulp < MAX_ERROR_ULP);
926     }
927 
928     @Test
929     public void testAsinAccuracy() {
930         double maxerrulp = 0.0;
931 
932         for (int i = 0; i < 10000; i++) {
933             double x = ((generator.nextDouble() * 2.0) - 1.0) * generator.nextDouble();
934 
935             double tst = AccurateMath.asin(x);
936             double ref = DfpMath.asin(field.newDfp(x)).toDouble();
937             double err = (tst - ref) / ref;
938 
939             if (err != 0) {
940                 double ulp = Math.abs(ref - Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
941                 double errulp = field.newDfp(tst).subtract(DfpMath.asin(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
942                 //System.out.println(x+"\t"+tst+"\t"+ref+"\t"+err+"\t"+errulp);
943 
944                 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
945             }
946         }
947 
948         assertTrue("asin() had errors in excess of " + MAX_ERROR_ULP + " ULP", maxerrulp < MAX_ERROR_ULP);
949     }
950 
951     @Test
952     public void testAcosAccuracy() {
953         double maxerrulp = 0.0;
954 
955         for (int i = 0; i < 10000; i++) {
956             double x = ((generator.nextDouble() * 2.0) - 1.0) * generator.nextDouble();
957 
958             double tst = AccurateMath.acos(x);
959             double ref = DfpMath.acos(field.newDfp(x)).toDouble();
960             double err = (tst - ref) / ref;
961 
962             if (err != 0) {
963                 double ulp = Math.abs(ref - Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
964                 double errulp = field.newDfp(tst).subtract(DfpMath.acos(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
965                 //System.out.println(x+"\t"+tst+"\t"+ref+"\t"+err+"\t"+errulp);
966 
967                 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
968             }
969         }
970 
971         assertTrue("acos() had errors in excess of " + MAX_ERROR_ULP + " ULP", maxerrulp < MAX_ERROR_ULP);
972     }
973 
974     /**
975      * Added tests for a 100% coverage of acos().
976      */
977     @Test
978     public void testAcosSpecialCases() {
979 
980         assertTrue("acos(NaN) should be NaN", Double.isNaN(AccurateMath.acos(Double.NaN)));
981         assertTrue("acos(-1.1) should be NaN", Double.isNaN(AccurateMath.acos(-1.1)));
982         assertTrue("acos(-1.1) should be NaN", Double.isNaN(AccurateMath.acos(1.1)));
983         assertEquals("acos(-1.0) should be PI", AccurateMath.acos(-1.0), AccurateMath.PI, Precision.EPSILON);
984         assertEquals("acos(1.0) should be 0.0", AccurateMath.acos(1.0), 0.0, Precision.EPSILON);
985         assertEquals("acos(0.0) should be PI/2", AccurateMath.acos(0.0), AccurateMath.PI / 2.0, Precision.EPSILON);
986     }
987 
988     /**
989      * Added tests for a 100% coverage of asin().
990      */
991     @Test
992     public void testAsinSpecialCases() {
993 
994         assertTrue("asin(NaN) should be NaN", Double.isNaN(AccurateMath.asin(Double.NaN)));
995         assertTrue("asin(1.1) should be NaN", Double.isNaN(AccurateMath.asin(1.1)));
996         assertTrue("asin(-1.1) should be NaN", Double.isNaN(AccurateMath.asin(-1.1)));
997         assertEquals("asin(1.0) should be PI/2", AccurateMath.asin(1.0), AccurateMath.PI / 2.0, Precision.EPSILON);
998         assertEquals("asin(-1.0) should be -PI/2", AccurateMath.asin(-1.0), -AccurateMath.PI / 2.0, Precision.EPSILON);
999         assertEquals("asin(0.0) should be 0.0", AccurateMath.asin(0.0), 0.0, Precision.EPSILON);
1000     }
1001 
1002     private Dfp cosh(Dfp x) {
1003         return DfpMath.exp(x).add(DfpMath.exp(x.negate())).divide(2);
1004     }
1005 
1006     private Dfp sinh(Dfp x) {
1007         return DfpMath.exp(x).subtract(DfpMath.exp(x.negate())).divide(2);
1008     }
1009 
1010     private Dfp tanh(Dfp x) {
1011         return sinh(x).divide(cosh(x));
1012     }
1013 
1014     @Test
1015     public void testSinhAccuracy() {
1016         double maxerrulp = 0.0;
1017 
1018         for (int i = 0; i < 10000; i++) {
1019             double x = ((generator.nextDouble() * 16.0) - 8.0) * generator.nextDouble();
1020 
1021             double tst = AccurateMath.sinh(x);
1022             double ref = sinh(field.newDfp(x)).toDouble();
1023             double err = (tst - ref) / ref;
1024 
1025             if (err != 0) {
1026                 double ulp = Math.abs(ref - Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
1027                 double errulp = field.newDfp(tst).subtract(sinh(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
1028                 //System.out.println(x+"\t"+tst+"\t"+ref+"\t"+err+"\t"+errulp);
1029                 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
1030             }
1031         }
1032 
1033         assertTrue("sinh() had errors in excess of " + MAX_ERROR_ULP + " ULP", maxerrulp < MAX_ERROR_ULP);
1034     }
1035 
1036     @Test
1037     public void testCoshAccuracy() {
1038         double maxerrulp = 0.0;
1039 
1040         for (int i = 0; i < 10000; i++) {
1041             double x = ((generator.nextDouble() * 16.0) - 8.0) * generator.nextDouble();
1042 
1043             double tst = AccurateMath.cosh(x);
1044             double ref = cosh(field.newDfp(x)).toDouble();
1045             double err = (tst - ref) / ref;
1046 
1047             if (err != 0) {
1048                 double ulp = Math.abs(ref - Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
1049                 double errulp = field.newDfp(tst).subtract(cosh(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
1050                 //System.out.println(x+"\t"+tst+"\t"+ref+"\t"+err+"\t"+errulp);
1051                 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
1052             }
1053         }
1054 
1055         assertTrue("cosh() had errors in excess of " + MAX_ERROR_ULP + " ULP", maxerrulp < MAX_ERROR_ULP);
1056     }
1057 
1058     @Test
1059     public void testTanhAccuracy() {
1060         double maxerrulp = 0.0;
1061 
1062         for (int i = 0; i < 10000; i++) {
1063             double x = ((generator.nextDouble() * 16.0) - 8.0) * generator.nextDouble();
1064 
1065             double tst = AccurateMath.tanh(x);
1066             double ref = tanh(field.newDfp(x)).toDouble();
1067             double err = (tst - ref) / ref;
1068 
1069             if (err != 0) {
1070                 double ulp = Math.abs(ref - Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
1071                 double errulp = field.newDfp(tst).subtract(tanh(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
1072                 //System.out.println(x+"\t"+tst+"\t"+ref+"\t"+err+"\t"+errulp);
1073                 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
1074             }
1075         }
1076 
1077         assertTrue("tanh() had errors in excess of " + MAX_ERROR_ULP + " ULP", maxerrulp < MAX_ERROR_ULP);
1078     }
1079 
1080     @Test
1081     public void testCbrtAccuracy() {
1082         double maxerrulp = 0.0;
1083 
1084         for (int i = 0; i < 10000; i++) {
1085             double x = ((generator.nextDouble() * 200.0) - 100.0) * generator.nextDouble();
1086 
1087             double tst = AccurateMath.cbrt(x);
1088             double ref = cbrt(field.newDfp(x)).toDouble();
1089             double err = (tst - ref) / ref;
1090 
1091             if (err != 0) {
1092                 double ulp = Math.abs(ref - Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
1093                 double errulp = field.newDfp(tst).subtract(cbrt(field.newDfp(x))).divide(field.newDfp(ulp)).toDouble();
1094                 //System.out.println(x+"\t"+tst+"\t"+ref+"\t"+err+"\t"+errulp);
1095                 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
1096             }
1097         }
1098 
1099         assertTrue("cbrt() had errors in excess of " + MAX_ERROR_ULP + " ULP", maxerrulp < MAX_ERROR_ULP);
1100     }
1101 
1102     private Dfp cbrt(Dfp x) {
1103         boolean negative = false;
1104 
1105         if (x.lessThan(field.getZero())) {
1106             negative = true;
1107             x = x.negate();
1108         }
1109 
1110         Dfp y = DfpMath.pow(x, field.getOne().divide(3));
1111 
1112         if (negative) {
1113             y = y.negate();
1114         }
1115 
1116         return y;
1117     }
1118 
1119     @Test
1120     public void testToDegrees() {
1121         double maxerrulp = 0.0;
1122         for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
1123             double x = generator.nextDouble();
1124             double tst = field.newDfp(x).multiply(180).divide(field.getPi()).toDouble();
1125             double ref = AccurateMath.toDegrees(x);
1126             double err = (tst - ref) / ref;
1127 
1128             if (err != 0) {
1129                 double ulp = Math.abs(ref -
1130                                       Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
1131                 double errulp = field.newDfp(tst).subtract(DfpMath.exp(field.newDfp(x)).subtract(field.getOne())).divide(field.newDfp(ulp)).toDouble();
1132 //                System.out.println(x + "\t" + tst + "\t" + ref + "\t" + err + "\t" + errulp);
1133 
1134                 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
1135             }
1136         }
1137         assertTrue("toDegrees() had errors in excess of " + MAX_ERROR_ULP + " ULP", maxerrulp < MAX_ERROR_ULP);
1138     }
1139 
1140     @Test
1141     public void testToRadians() {
1142         double maxerrulp = 0.0;
1143         for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
1144             double x = generator.nextDouble();
1145             double tst = field.newDfp(x).multiply(field.getPi()).divide(180).toDouble();
1146             double ref = AccurateMath.toRadians(x);
1147             double err = (tst - ref) / ref;
1148 
1149             if (err != 0) {
1150                 double ulp = Math.abs(ref -
1151                                       Double.longBitsToDouble((Double.doubleToLongBits(ref) ^ 1)));
1152                 double errulp = field.newDfp(tst).subtract(DfpMath.exp(field.newDfp(x)).subtract(field.getOne())).divide(field.newDfp(ulp)).toDouble();
1153 //                System.out.println(x + "\t" + tst + "\t" + ref + "\t" + err + "\t" + errulp);
1154 
1155                 maxerrulp = Math.max(maxerrulp, Math.abs(errulp));
1156             }
1157         }
1158 
1159         assertTrue("toRadians() had errors in excess of " + MAX_ERROR_ULP + " ULP", maxerrulp < MAX_ERROR_ULP);
1160     }
1161 
1162     @Test
1163     public void testNextAfter() {
1164         // 0x402fffffffffffff 0x404123456789abcd -> 4030000000000000
1165         assertEquals(16.0, AccurateMath.nextUp(15.999999999999998), 0.0);
1166 
1167         // 0xc02fffffffffffff 0x404123456789abcd -> c02ffffffffffffe
1168         assertEquals(-15.999999999999996, AccurateMath.nextAfter(-15.999999999999998, 34.27555555555555), 0.0);
1169 
1170         // 0x402fffffffffffff 0x400123456789abcd -> 402ffffffffffffe
1171         assertEquals(15.999999999999996, AccurateMath.nextDown(15.999999999999998), 0.0);
1172 
1173         // 0xc02fffffffffffff 0x400123456789abcd -> c02ffffffffffffe
1174         assertEquals(-15.999999999999996, AccurateMath.nextAfter(-15.999999999999998, 2.142222222222222), 0.0);
1175 
1176         // 0x4020000000000000 0x404123456789abcd -> 4020000000000001
1177         assertEquals(8.000000000000002, AccurateMath.nextAfter(8.0, 34.27555555555555), 0.0);
1178 
1179         // 0xc020000000000000 0x404123456789abcd -> c01fffffffffffff
1180         assertEquals(-7.999999999999999, AccurateMath.nextAfter(-8.0, 34.27555555555555), 0.0);
1181 
1182         // 0x4020000000000000 0x400123456789abcd -> 401fffffffffffff
1183         assertEquals(7.999999999999999, AccurateMath.nextAfter(8.0, 2.142222222222222), 0.0);
1184 
1185         // 0xc020000000000000 0x400123456789abcd -> c01fffffffffffff
1186         assertEquals(-7.999999999999999, AccurateMath.nextAfter(-8.0, 2.142222222222222), 0.0);
1187 
1188         // 0x3f2e43753d36a223 0x3f2e43753d36a224 -> 3f2e43753d36a224
1189         assertEquals(2.308922399667661E-4, AccurateMath.nextAfter(2.3089223996676606E-4, 2.308922399667661E-4), 0.0);
1190 
1191         // 0x3f2e43753d36a223 0x3f2e43753d36a223 -> 3f2e43753d36a223
1192         assertEquals(2.3089223996676606E-4, AccurateMath.nextAfter(2.3089223996676606E-4, 2.3089223996676606E-4), 0.0);
1193 
1194         // 0x3f2e43753d36a223 0x3f2e43753d36a222 -> 3f2e43753d36a222
1195         assertEquals(2.3089223996676603E-4, AccurateMath.nextAfter(2.3089223996676606E-4, 2.3089223996676603E-4), 0.0);
1196 
1197         // 0x3f2e43753d36a223 0xbf2e43753d36a224 -> 3f2e43753d36a222
1198         assertEquals(2.3089223996676603E-4, AccurateMath.nextAfter(2.3089223996676606E-4, -2.308922399667661E-4), 0.0);
1199 
1200         // 0x3f2e43753d36a223 0xbf2e43753d36a223 -> 3f2e43753d36a222
1201         assertEquals(2.3089223996676603E-4, AccurateMath.nextAfter(2.3089223996676606E-4, -2.3089223996676606E-4), 0.0);
1202 
1203         // 0x3f2e43753d36a223 0xbf2e43753d36a222 -> 3f2e43753d36a222
1204         assertEquals(2.3089223996676603E-4, AccurateMath.nextAfter(2.3089223996676606E-4, -2.3089223996676603E-4), 0.0);
1205 
1206         // 0xbf2e43753d36a223 0x3f2e43753d36a224 -> bf2e43753d36a222
1207         assertEquals(-2.3089223996676603E-4, AccurateMath.nextAfter(-2.3089223996676606E-4, 2.308922399667661E-4), 0.0);
1208 
1209         // 0xbf2e43753d36a223 0x3f2e43753d36a223 -> bf2e43753d36a222
1210         assertEquals(-2.3089223996676603E-4, AccurateMath.nextAfter(-2.3089223996676606E-4, 2.3089223996676606E-4), 0.0);
1211 
1212         // 0xbf2e43753d36a223 0x3f2e43753d36a222 -> bf2e43753d36a222
1213         assertEquals(-2.3089223996676603E-4, AccurateMath.nextAfter(-2.3089223996676606E-4, 2.3089223996676603E-4), 0.0);
1214 
1215         // 0xbf2e43753d36a223 0xbf2e43753d36a224 -> bf2e43753d36a224
1216         assertEquals(-2.308922399667661E-4, AccurateMath.nextAfter(-2.3089223996676606E-4, -2.308922399667661E-4), 0.0);
1217 
1218         // 0xbf2e43753d36a223 0xbf2e43753d36a223 -> bf2e43753d36a223
1219         assertEquals(-2.3089223996676606E-4, AccurateMath.nextAfter(-2.3089223996676606E-4, -2.3089223996676606E-4), 0.0);
1220 
1221         // 0xbf2e43753d36a223 0xbf2e43753d36a222 -> bf2e43753d36a222
1222         assertEquals(-2.3089223996676603E-4, AccurateMath.nextAfter(-2.3089223996676606E-4, -2.3089223996676603E-4), 0.0);
1223     }
1224 
1225     @Test
1226     public void testDoubleNextAfterSpecialCases() {
1227         assertEquals(-Double.MAX_VALUE, AccurateMath.nextAfter(Double.NEGATIVE_INFINITY, 0D), 0D);
1228         assertEquals(Double.MAX_VALUE, AccurateMath.nextAfter(Double.POSITIVE_INFINITY, 0D), 0D);
1229         assertEquals(Double.NaN, AccurateMath.nextAfter(Double.NaN, 0D), 0D);
1230         assertEquals(Double.POSITIVE_INFINITY, AccurateMath.nextAfter(Double.MAX_VALUE, Double.POSITIVE_INFINITY), 0D);
1231         assertEquals(Double.NEGATIVE_INFINITY, AccurateMath.nextAfter(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY), 0D);
1232         assertEquals(Double.MIN_VALUE, AccurateMath.nextAfter(0D, 1D), 0D);
1233         assertEquals(-Double.MIN_VALUE, AccurateMath.nextAfter(0D, -1D), 0D);
1234         assertEquals(0D, AccurateMath.nextAfter(Double.MIN_VALUE, -1), 0D);
1235         assertEquals(0D, AccurateMath.nextAfter(-Double.MIN_VALUE, 1), 0D);
1236     }
1237 
1238     @Test
1239     public void testFloatNextAfterSpecialCases() {
1240         assertEquals(-Float.MAX_VALUE, AccurateMath.nextAfter(Float.NEGATIVE_INFINITY, 0F), 0F);
1241         assertEquals(Float.MAX_VALUE, AccurateMath.nextAfter(Float.POSITIVE_INFINITY, 0F), 0F);
1242         assertEquals(Float.NaN, AccurateMath.nextAfter(Float.NaN, 0F), 0F);
1243         assertEquals(Float.POSITIVE_INFINITY, AccurateMath.nextUp(Float.MAX_VALUE), 0F);
1244         assertEquals(Float.NEGATIVE_INFINITY, AccurateMath.nextDown(-Float.MAX_VALUE), 0F);
1245         assertEquals(Float.MIN_VALUE, AccurateMath.nextAfter(0F, 1F), 0F);
1246         assertEquals(-Float.MIN_VALUE, AccurateMath.nextAfter(0F, -1F), 0F);
1247         assertEquals(0F, AccurateMath.nextAfter(Float.MIN_VALUE, -1F), 0F);
1248         assertEquals(0F, AccurateMath.nextAfter(-Float.MIN_VALUE, 1F), 0F);
1249     }
1250 
1251     @Test
1252     public void testDoubleScalbSpecialCases() {
1253         assertEquals(2.5269841324701218E-175,  AccurateMath.scalb(2.2250738585072014E-308, 442), 0D);
1254         assertEquals(1.307993905256674E297,    AccurateMath.scalb(1.1102230246251565E-16, 1040), 0D);
1255         assertEquals(7.2520887996488946E-217,  AccurateMath.scalb(Double.MIN_VALUE,        356), 0D);
1256         assertEquals(8.98846567431158E307,     AccurateMath.scalb(Double.MIN_VALUE,       2097), 0D);
1257         assertEquals(Double.POSITIVE_INFINITY, AccurateMath.scalb(Double.MIN_VALUE,       2098), 0D);
1258         assertEquals(1.1125369292536007E-308,  AccurateMath.scalb(2.225073858507201E-308,   -1), 0D);
1259         assertEquals(1.0E-323,                 AccurateMath.scalb(Double.MAX_VALUE,      -2097), 0D);
1260         assertEquals(Double.MIN_VALUE,         AccurateMath.scalb(Double.MAX_VALUE,      -2098), 0D);
1261         assertEquals(0,                        AccurateMath.scalb(Double.MAX_VALUE,      -2099), 0D);
1262         assertEquals(Double.POSITIVE_INFINITY, AccurateMath.scalb(Double.POSITIVE_INFINITY, -1000000), 0D);
1263         assertEquals(Double.NEGATIVE_INFINITY, AccurateMath.scalb(-1.1102230246251565E-16, 1078), 0D);
1264         assertEquals(Double.NEGATIVE_INFINITY, AccurateMath.scalb(-1.1102230246251565E-16,  1079), 0D);
1265         assertEquals(Double.NEGATIVE_INFINITY, AccurateMath.scalb(-2.2250738585072014E-308, 2047), 0D);
1266         assertEquals(Double.NEGATIVE_INFINITY, AccurateMath.scalb(-2.2250738585072014E-308, 2048), 0D);
1267         assertEquals(Double.NEGATIVE_INFINITY, AccurateMath.scalb(-1.7976931348623157E308,  2147483647), 0D);
1268         assertEquals(Double.POSITIVE_INFINITY, AccurateMath.scalb(+1.7976931348623157E308,  2147483647), 0D);
1269         assertEquals(Double.NEGATIVE_INFINITY, AccurateMath.scalb(-1.1102230246251565E-16,  2147483647), 0D);
1270         assertEquals(Double.POSITIVE_INFINITY, AccurateMath.scalb(+1.1102230246251565E-16,  2147483647), 0D);
1271         assertEquals(Double.NEGATIVE_INFINITY, AccurateMath.scalb(-2.2250738585072014E-308, 2147483647), 0D);
1272         assertEquals(Double.POSITIVE_INFINITY, AccurateMath.scalb(+2.2250738585072014E-308, 2147483647), 0D);
1273     }
1274 
1275     @Test
1276     public void testFloatScalbSpecialCases() {
1277         assertEquals(0f, AccurateMath.scalb(Float.MIN_VALUE, -30), 0F);
1278         assertEquals(2 * Float.MIN_VALUE, AccurateMath.scalb(Float.MIN_VALUE, 1), 0F);
1279         assertEquals(7.555786e22f, AccurateMath.scalb(Float.MAX_VALUE, -52), 0F);
1280         assertEquals(1.7014118e38f, AccurateMath.scalb(Float.MIN_VALUE, 276), 0F);
1281         assertEquals(Float.POSITIVE_INFINITY, AccurateMath.scalb(Float.MIN_VALUE, 277), 0F);
1282         assertEquals(5.8774718e-39f, AccurateMath.scalb(1.1754944e-38f, -1), 0F);
1283         assertEquals(2 * Float.MIN_VALUE, AccurateMath.scalb(Float.MAX_VALUE, -276), 0F);
1284         assertEquals(Float.MIN_VALUE, AccurateMath.scalb(Float.MAX_VALUE, -277), 0F);
1285         assertEquals(0, AccurateMath.scalb(Float.MAX_VALUE, -278), 0F);
1286         assertEquals(Float.POSITIVE_INFINITY, AccurateMath.scalb(Float.POSITIVE_INFINITY, -1000000), 0F);
1287         assertEquals(-3.13994498e38f, AccurateMath.scalb(-1.1e-7f, 151), 0F);
1288         assertEquals(Float.NEGATIVE_INFINITY, AccurateMath.scalb(-1.1e-7f, 152), 0F);
1289         assertEquals(Float.POSITIVE_INFINITY, AccurateMath.scalb(3.4028235E38f, 2147483647), 0F);
1290         assertEquals(Float.NEGATIVE_INFINITY, AccurateMath.scalb(-3.4028235E38f, 2147483647), 0F);
1291     }
1292 
1293     @Test
1294     public void testSignumDouble() {
1295         final double delta = 0.0;
1296         assertEquals(1.0, AccurateMath.signum(2.0), delta);
1297         assertEquals(0.0, AccurateMath.signum(0.0), delta);
1298         assertEquals(-1.0, AccurateMath.signum(-2.0), delta);
1299         Assert.assertTrue(Double.isNaN(AccurateMath.signum(Double.NaN)));
1300     }
1301 
1302     @Test
1303     public void testSignumFloat() {
1304         final float delta = 0.0F;
1305         assertEquals(1.0F, AccurateMath.signum(2.0F), delta);
1306         assertEquals(0.0F, AccurateMath.signum(0.0F), delta);
1307         assertEquals(-1.0F, AccurateMath.signum(-2.0F), delta);
1308         Assert.assertTrue(Double.isNaN(AccurateMath.signum(Float.NaN)));
1309     }
1310 
1311     @Test
1312     public void testLogWithBase() {
1313         assertEquals(2.0, AccurateMath.log(2, 4), 0);
1314         assertEquals(3.0, AccurateMath.log(2, 8), 0);
1315         assertTrue(Double.isNaN(AccurateMath.log(-1, 1)));
1316         assertTrue(Double.isNaN(AccurateMath.log(1, -1)));
1317         assertTrue(Double.isNaN(AccurateMath.log(0, 0)));
1318         assertEquals(0, AccurateMath.log(0, 10), 0);
1319         assertEquals(Double.NEGATIVE_INFINITY, AccurateMath.log(10, 0), 0);
1320     }
1321 
1322     @Test
1323     public void testIndicatorDouble() {
1324         double delta = 0.0;
1325         assertEquals(1.0, AccurateMath.copySign(1d, 2.0), delta);
1326         assertEquals(1.0, AccurateMath.copySign(1d, 0.0), delta);
1327         assertEquals(-1.0, AccurateMath.copySign(1d, -0.0), delta);
1328         assertEquals(1.0, AccurateMath.copySign(1d, Double.POSITIVE_INFINITY), delta);
1329         assertEquals(-1.0, AccurateMath.copySign(1d, Double.NEGATIVE_INFINITY), delta);
1330         assertEquals(1.0, AccurateMath.copySign(1d, Double.NaN), delta);
1331         assertEquals(-1.0, AccurateMath.copySign(1d, -2.0), delta);
1332     }
1333 
1334     @Test
1335     public void testIndicatorFloat() {
1336         float delta = 0.0F;
1337         assertEquals(1.0F, AccurateMath.copySign(1d, 2.0F), delta);
1338         assertEquals(1.0F, AccurateMath.copySign(1d, 0.0F), delta);
1339         assertEquals(-1.0F, AccurateMath.copySign(1d, -0.0F), delta);
1340         assertEquals(1.0F, AccurateMath.copySign(1d, Float.POSITIVE_INFINITY), delta);
1341         assertEquals(-1.0F, AccurateMath.copySign(1d, Float.NEGATIVE_INFINITY), delta);
1342         assertEquals(1.0F, AccurateMath.copySign(1d, Float.NaN), delta);
1343         assertEquals(-1.0F, AccurateMath.copySign(1d, -2.0F), delta);
1344     }
1345 
1346     @Test
1347     public void testIntPow() {
1348         final int maxExp = 300;
1349         DfpField localField = new DfpField(40);
1350         final double base = 1.23456789;
1351         Dfp baseDfp = localField.newDfp(base);
1352         Dfp dfpPower = localField.getOne();
1353         for (int i = 0; i < maxExp; i++) {
1354             assertEquals("exp=" + i, dfpPower.toDouble(), AccurateMath.pow(base, i),
1355                          0.6 * AccurateMath.ulp(dfpPower.toDouble()));
1356             dfpPower = dfpPower.multiply(baseDfp);
1357         }
1358     }
1359 
1360     @Test
1361     public void testIntPowHuge() {
1362         assertTrue(Double.isInfinite(AccurateMath.pow(AccurateMath.scalb(1.0, 500), 4)));
1363     }
1364 
1365     @Test(timeout = 5000L) // This test must finish in finite time.
1366     public void testIntPowLongMinValue() {
1367         assertEquals(1.0, AccurateMath.pow(1.0, Long.MIN_VALUE), -1.0);
1368     }
1369 
1370     @Test(timeout = 5000L)
1371     public void testIntPowSpecialCases() {
1372         final double EXACT = -1.0;
1373         final double[] DOUBLES = new double[] {
1374             Double.NEGATIVE_INFINITY, -0.0, Double.NaN, 0.0, Double.POSITIVE_INFINITY,
1375             Long.MIN_VALUE, Integer.MIN_VALUE, Short.MIN_VALUE, Byte.MIN_VALUE,
1376             -(double)Long.MIN_VALUE, -(double)Integer.MIN_VALUE, -(double)Short.MIN_VALUE, -(double)Byte.MIN_VALUE,
1377             Byte.MAX_VALUE, Short.MAX_VALUE, Integer.MAX_VALUE, Long.MAX_VALUE,
1378             -Byte.MAX_VALUE, -Short.MAX_VALUE, -Integer.MAX_VALUE, -Long.MAX_VALUE,
1379             Float.MAX_VALUE, Double.MAX_VALUE, Double.MIN_VALUE, Float.MIN_VALUE,
1380             -Float.MAX_VALUE, -Double.MAX_VALUE, -Double.MIN_VALUE, -Float.MIN_VALUE,
1381             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,
1382             -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
1383         };
1384 
1385         final long[] 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};
1386         // Special cases from Math.pow javadoc:
1387         // If the second argument is positive or negative zero, then the result is 1.0.
1388         for (double d : DOUBLES) {
1389             assertEquals(1.0, AccurateMath.pow(d, 0L), EXACT);
1390         }
1391         // If the second argument is 1.0, then the result is the same as the first argument.
1392         for (double d : DOUBLES) {
1393             assertEquals(d, AccurateMath.pow(d, 1L), EXACT);
1394         }
1395         // If the second argument is NaN, then the result is NaN. <- Impossible with int.
1396         // If the first argument is NaN and the second argument is nonzero, then the result is NaN.
1397         for (long i : INTS) {
1398             if (i != 0L) {
1399                 assertEquals(Double.NaN, AccurateMath.pow(Double.NaN, i), EXACT);
1400             }
1401         }
1402         // If the absolute value of the first argument is greater than 1 and the second argument is positive infinity, or
1403         // the absolute value of the first argument is less than 1 and the second argument is negative infinity, then the result is positive infinity.
1404         for (double d : DOUBLES) {
1405             if (Math.abs(d) > 1.0) {
1406                 assertEquals(Double.POSITIVE_INFINITY, AccurateMath.pow(d, Long.MAX_VALUE - 1L), EXACT);
1407             }
1408         }
1409         for (double d : DOUBLES) {
1410             if (Math.abs(d) < 1.0) {
1411                 assertEquals(Double.POSITIVE_INFINITY, AccurateMath.pow(d, Long.MIN_VALUE), EXACT);
1412             }
1413         }
1414         // Note: Long.MAX_VALUE isn't actually an infinity, so its parity affects the sign of resulting infinity.
1415         for (double d : DOUBLES) {
1416             if (Math.abs(d) > 1.0) {
1417                 assertTrue(Double.isInfinite(AccurateMath.pow(d, Long.MAX_VALUE)));
1418             }
1419         }
1420         for (double d : DOUBLES) {
1421             if (Math.abs(d) < 1.0) {
1422                 assertTrue(Double.isInfinite(AccurateMath.pow(d, Long.MIN_VALUE + 1L)));
1423             }
1424         }
1425         // If the absolute value of the first argument is greater than 1 and the second argument is negative infinity, or
1426         // the absolute value of the first argument is less than 1 and the second argument is positive infinity, then the result is positive zero.
1427         for (double d : DOUBLES) {
1428             if (Math.abs(d) > 1.0) {
1429                 assertEquals(0.0, AccurateMath.pow(d, Long.MIN_VALUE), EXACT);
1430             }
1431         }
1432         for (double d : DOUBLES) {
1433             if (Math.abs(d) < 1.0) {
1434                 assertEquals(0.0, AccurateMath.pow(d, Long.MAX_VALUE - 1L), EXACT);
1435             }
1436         }
1437         // Note: Long.MAX_VALUE isn't actually an infinity, so its parity affects the sign of resulting zero.
1438         for (double d : DOUBLES) {
1439             if (Math.abs(d) > 1.0) {
1440                 assertEquals(0.0, AccurateMath.pow(d, Long.MIN_VALUE + 1L), 0.0);
1441             }
1442         }
1443         for (double d : DOUBLES) {
1444             if (Math.abs(d) < 1.0) {
1445                 assertEquals(0.0, AccurateMath.pow(d, Long.MAX_VALUE), 0.0);
1446             }
1447         }
1448         // If the absolute value of the first argument equals 1 and the second argument is infinite, then the result is NaN. <- Impossible with int.
1449         // If the first argument is positive zero and the second argument is greater than zero, or
1450         // the first argument is positive infinity and the second argument is less than zero, then the result is positive zero.
1451         for (long i : INTS) {
1452             if (i > 0L) {
1453                 assertEquals(0.0, AccurateMath.pow(0.0, i), EXACT);
1454             }
1455         }
1456         for (long i : INTS) {
1457             if (i < 0L) {
1458                 assertEquals(0.0, AccurateMath.pow(Double.POSITIVE_INFINITY, i), EXACT);
1459             }
1460         }
1461         // If the first argument is positive zero and the second argument is less than zero, or
1462         // the first argument is positive infinity and the second argument is greater than zero, then the result is positive infinity.
1463         for (long i : INTS) {
1464             if (i < 0L) {
1465                 assertEquals(Double.POSITIVE_INFINITY, AccurateMath.pow(0.0, i), EXACT);
1466             }
1467         }
1468         for (long i : INTS) {
1469             if (i > 0L) {
1470                 assertEquals(Double.POSITIVE_INFINITY, AccurateMath.pow(Double.POSITIVE_INFINITY, i), EXACT);
1471             }
1472         }
1473         // If the first argument is negative zero and the second argument is greater than zero but not a finite odd integer, or
1474         // 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.
1475         for (long i : INTS) {
1476             if (i > 0L && (i & 1L) == 0L) {
1477                 assertEquals(0.0, AccurateMath.pow(-0.0, i), EXACT);
1478             }
1479         }
1480         for (long i : INTS) {
1481             if (i < 0L && (i & 1L) == 0L) {
1482                 assertEquals(0.0, AccurateMath.pow(Double.NEGATIVE_INFINITY, i), EXACT);
1483             }
1484         }
1485         // If the first argument is negative zero and the second argument is a positive finite odd integer, or
1486         // the first argument is negative infinity and the second argument is a negative finite odd integer, then the result is negative zero.
1487         for (long i : INTS) {
1488             if (i > 0L && (i & 1L) == 1L) {
1489                 assertEquals(-0.0, AccurateMath.pow(-0.0, i), EXACT);
1490             }
1491         }
1492         for (long i : INTS) {
1493             if (i < 0L && (i & 1L) == 1L) {
1494                 assertEquals(-0.0, AccurateMath.pow(Double.NEGATIVE_INFINITY, i), EXACT);
1495             }
1496         }
1497         // If the first argument is negative zero and the second argument is less than zero but not a finite odd integer, or
1498         // 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.
1499         for (long i : INTS) {
1500             if (i > 0L && (i & 1L) == 0L) {
1501                 assertEquals(Double.POSITIVE_INFINITY, AccurateMath.pow(Double.NEGATIVE_INFINITY, i), EXACT);
1502             }
1503         }
1504         for (long i : INTS) {
1505             if (i < 0L && (i & 1L) == 0L) {
1506                 assertEquals(Double.POSITIVE_INFINITY, AccurateMath.pow(-0.0, i), EXACT);
1507             }
1508         }
1509         // If the first argument is negative zero and the second argument is a negative finite odd integer, or
1510         // the first argument is negative infinity and the second argument is a positive finite odd integer, then the result is negative infinity.
1511         for (long i : INTS) {
1512             if (i > 0L && (i & 1L) == 1L) {
1513                 assertEquals(Double.NEGATIVE_INFINITY, AccurateMath.pow(Double.NEGATIVE_INFINITY, i), EXACT);
1514             }
1515         }
1516         for (long i : INTS) {
1517             if (i < 0L && (i & 1L) == 1L) {
1518                 assertEquals(Double.NEGATIVE_INFINITY, AccurateMath.pow(-0.0, i), EXACT);
1519             }
1520         }
1521         for (double d : DOUBLES) {
1522             // If the first argument is finite and less than zero
1523             if (d < 0.0 && Math.abs(d) <= Double.MAX_VALUE) {
1524                 for (long i : INTS) {
1525                     // 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
1526                     if ((i & 1L) == 0L) {
1527                         assertEquals(AccurateMath.pow(-d, i), AccurateMath.pow(d, i), EXACT);
1528                     } else {
1529                         // 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
1530                         assertEquals(-AccurateMath.pow(-d, i), AccurateMath.pow(d, i), EXACT);
1531                     }
1532                     // if the second argument is finite and not an integer, then the result is NaN. <- Impossible with int.
1533                 }
1534             }
1535         }
1536         // If both arguments are integers, then the result is exactly equal to the mathematical result of raising the first argument to the power
1537         // of the second argument if that result can in fact be represented exactly as a double value. <- Other tests.
1538     }
1539 
1540     @Test
1541     public void testIncrementExactInt() {
1542         int[] specialValues = new int[] {
1543             Integer.MIN_VALUE, Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2,
1544             Integer.MAX_VALUE, Integer.MAX_VALUE - 1, Integer.MAX_VALUE - 2,
1545             -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1546             -1 - (Integer.MIN_VALUE / 2), 0 - (Integer.MIN_VALUE / 2), 1 - (Integer.MIN_VALUE / 2),
1547             -1 + (Integer.MAX_VALUE / 2), 0 + (Integer.MAX_VALUE / 2), 1 + (Integer.MAX_VALUE / 2),
1548         };
1549         for (int a : specialValues) {
1550             BigInteger bdA   = BigInteger.valueOf(a);
1551             BigInteger bdSum = bdA.add(BigInteger.ONE);
1552             if (bdSum.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0 ||
1553                 bdSum.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) {
1554                 try {
1555                     AccurateMath.incrementExact(a);
1556                     Assert.fail("an exception should have been thrown");
1557                 } catch (ArithmeticException mae) {
1558                     // expected
1559                 }
1560             } else {
1561                 assertEquals(bdSum, BigInteger.valueOf(AccurateMath.incrementExact(a)));
1562             }
1563         }
1564     }
1565 
1566     @Test
1567     public void testDecrementExactInt() {
1568         int[] specialValues = new int[] {
1569             Integer.MIN_VALUE, Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2,
1570             Integer.MAX_VALUE, Integer.MAX_VALUE - 1, Integer.MAX_VALUE - 2,
1571             -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1572             -1 - (Integer.MIN_VALUE / 2), 0 - (Integer.MIN_VALUE / 2), 1 - (Integer.MIN_VALUE / 2),
1573             -1 + (Integer.MAX_VALUE / 2), 0 + (Integer.MAX_VALUE / 2), 1 + (Integer.MAX_VALUE / 2),
1574         };
1575         for (int a : specialValues) {
1576             BigInteger bdA   = BigInteger.valueOf(a);
1577             BigInteger bdSub = bdA.subtract(BigInteger.ONE);
1578             if (bdSub.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0 ||
1579                 bdSub.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) {
1580                 try {
1581                     AccurateMath.decrementExact(a);
1582                     fail("an exception should have been thrown");
1583                 } catch (ArithmeticException mae) {
1584                     // expected
1585                 }
1586             } else {
1587                 assertEquals(bdSub, BigInteger.valueOf(AccurateMath.decrementExact(a)));
1588             }
1589         }
1590     }
1591 
1592     @Test
1593     public void testAddExactInt() {
1594         int[] specialValues = new int[] {
1595             Integer.MIN_VALUE, Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2,
1596             Integer.MAX_VALUE, Integer.MAX_VALUE - 1, Integer.MAX_VALUE - 2,
1597             -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1598             -1 - (Integer.MIN_VALUE / 2), 0 - (Integer.MIN_VALUE / 2), 1 - (Integer.MIN_VALUE / 2),
1599             -1 + (Integer.MAX_VALUE / 2), 0 + (Integer.MAX_VALUE / 2), 1 + (Integer.MAX_VALUE / 2),
1600         };
1601         for (int a : specialValues) {
1602             for (int b : specialValues) {
1603                 BigInteger bdA   = BigInteger.valueOf(a);
1604                 BigInteger bdB   = BigInteger.valueOf(b);
1605                 BigInteger bdSum = bdA.add(bdB);
1606                 if (bdSum.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0 ||
1607                         bdSum.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) {
1608                     try {
1609                         AccurateMath.addExact(a, b);
1610                         fail("an exception should have been thrown");
1611                     } catch (ArithmeticException mae) {
1612                         // expected
1613                     }
1614                 } else {
1615                     assertEquals(bdSum, BigInteger.valueOf(AccurateMath.addExact(a, b)));
1616                 }
1617             }
1618         }
1619     }
1620 
1621     @Test
1622     public void testAddExactLong() {
1623         long[] specialValues = new long[] {
1624             Long.MIN_VALUE, Long.MIN_VALUE + 1, Long.MIN_VALUE + 2,
1625             Long.MAX_VALUE, Long.MAX_VALUE - 1, Long.MAX_VALUE - 2,
1626             -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1627             -1 - (Long.MIN_VALUE / 2), 0 - (Long.MIN_VALUE / 2), 1 - (Long.MIN_VALUE / 2),
1628             -1 + (Long.MAX_VALUE / 2), 0 + (Long.MAX_VALUE / 2), 1 + (Long.MAX_VALUE / 2),
1629         };
1630         for (long a : specialValues) {
1631             for (long b : specialValues) {
1632                 BigInteger bdA   = BigInteger.valueOf(a);
1633                 BigInteger bdB   = BigInteger.valueOf(b);
1634                 BigInteger bdSum = bdA.add(bdB);
1635                 if (bdSum.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 0 ||
1636                         bdSum.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) {
1637                     try {
1638                         AccurateMath.addExact(a, b);
1639                         fail("an exception should have been thrown");
1640                     } catch (ArithmeticException mae) {
1641                         // expected
1642                     }
1643                 } else {
1644                     assertEquals(bdSum, BigInteger.valueOf(AccurateMath.addExact(a, b)));
1645                 }
1646             }
1647         }
1648     }
1649 
1650     @Test
1651     public void testSubtractExactInt() {
1652         int[] specialValues = new int[] {
1653             Integer.MIN_VALUE, Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2,
1654             Integer.MAX_VALUE, Integer.MAX_VALUE - 1, Integer.MAX_VALUE - 2,
1655             -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1656             -1 - (Integer.MIN_VALUE / 2), 0 - (Integer.MIN_VALUE / 2), 1 - (Integer.MIN_VALUE / 2),
1657             -1 + (Integer.MAX_VALUE / 2), 0 + (Integer.MAX_VALUE / 2), 1 + (Integer.MAX_VALUE / 2),
1658         };
1659         for (int a : specialValues) {
1660             for (int b : specialValues) {
1661                 BigInteger bdA   = BigInteger.valueOf(a);
1662                 BigInteger bdB   = BigInteger.valueOf(b);
1663                 BigInteger bdSub = bdA.subtract(bdB);
1664                 if (bdSub.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0 ||
1665                         bdSub.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) {
1666                     try {
1667                         AccurateMath.subtractExact(a, b);
1668                         fail("an exception should have been thrown");
1669                     } catch (ArithmeticException mae) {
1670                         // expected
1671                     }
1672                 } else {
1673                     assertEquals(bdSub, BigInteger.valueOf(AccurateMath.subtractExact(a, b)));
1674                 }
1675             }
1676         }
1677     }
1678 
1679     @Test
1680     public void testSubtractExactLong() {
1681         long[] specialValues = new long[] {
1682             Long.MIN_VALUE, Long.MIN_VALUE + 1, Long.MIN_VALUE + 2,
1683             Long.MAX_VALUE, Long.MAX_VALUE - 1, Long.MAX_VALUE - 2,
1684             -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1685             -1 - (Long.MIN_VALUE / 2), 0 - (Long.MIN_VALUE / 2), 1 - (Long.MIN_VALUE / 2),
1686             -1 + (Long.MAX_VALUE / 2), 0 + (Long.MAX_VALUE / 2), 1 + (Long.MAX_VALUE / 2),
1687         };
1688         for (long a : specialValues) {
1689             for (long b : specialValues) {
1690                 BigInteger bdA   = BigInteger.valueOf(a);
1691                 BigInteger bdB   = BigInteger.valueOf(b);
1692                 BigInteger bdSub = bdA.subtract(bdB);
1693                 if (bdSub.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 0 ||
1694                         bdSub.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) {
1695                     try {
1696                         AccurateMath.subtractExact(a, b);
1697                         fail("an exception should have been thrown");
1698                     } catch (ArithmeticException mae) {
1699                         // expected
1700                     }
1701                 } else {
1702                     assertEquals(bdSub, BigInteger.valueOf(AccurateMath.subtractExact(a, b)));
1703                 }
1704             }
1705         }
1706     }
1707 
1708     @Test
1709     public void testMultiplyExactInt() {
1710         int[] specialValues = new int[] {
1711             Integer.MIN_VALUE, Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2,
1712             Integer.MAX_VALUE, Integer.MAX_VALUE - 1, Integer.MAX_VALUE - 2,
1713             -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1714             -1 - (Integer.MIN_VALUE / 2), 0 - (Integer.MIN_VALUE / 2), 1 - (Integer.MIN_VALUE / 2),
1715             -1 + (Integer.MAX_VALUE / 2), 0 + (Integer.MAX_VALUE / 2), 1 + (Integer.MAX_VALUE / 2),
1716         };
1717         for (int a : specialValues) {
1718             for (int b : specialValues) {
1719                 BigInteger bdA   = BigInteger.valueOf(a);
1720                 BigInteger bdB   = BigInteger.valueOf(b);
1721                 BigInteger bdMul = bdA.multiply(bdB);
1722                 if (bdMul.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0 ||
1723                     bdMul.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) {
1724                     try {
1725                         AccurateMath.multiplyExact(a, b);
1726                         fail("an exception should have been thrown " + a + b);
1727                     } catch (ArithmeticException mae) {
1728                         // expected
1729                     }
1730                 } else {
1731                     assertEquals(bdMul, BigInteger.valueOf(AccurateMath.multiplyExact(a, b)));
1732                 }
1733             }
1734         }
1735     }
1736 
1737     @Test
1738     public void testMultiplyExactLong() {
1739         long[] specialValues = new long[] {
1740             Long.MIN_VALUE, Long.MIN_VALUE + 1, Long.MIN_VALUE + 2,
1741             Long.MAX_VALUE, Long.MAX_VALUE - 1, Long.MAX_VALUE - 2,
1742             -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1743             -1 - (Long.MIN_VALUE / 2), 0 - (Long.MIN_VALUE / 2), 1 - (Long.MIN_VALUE / 2),
1744             -1 + (Long.MAX_VALUE / 2), 0 + (Long.MAX_VALUE / 2), 1 + (Long.MAX_VALUE / 2),
1745         };
1746         for (long a : specialValues) {
1747             for (long b : specialValues) {
1748                 BigInteger bdA   = BigInteger.valueOf(a);
1749                 BigInteger bdB   = BigInteger.valueOf(b);
1750                 BigInteger bdMul = bdA.multiply(bdB);
1751                 if (bdMul.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 0 ||
1752                     bdMul.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) {
1753                     try {
1754                         AccurateMath.multiplyExact(a, b);
1755                         fail("an exception should have been thrown " + a + b);
1756                     } catch (ArithmeticException mae) {
1757                         // expected
1758                     }
1759                 } else {
1760                     assertEquals(bdMul, BigInteger.valueOf(AccurateMath.multiplyExact(a, b)));
1761                 }
1762             }
1763         }
1764     }
1765 
1766     @Test(expected = ArithmeticException.class)
1767     public void testToIntExactTooLow() {
1768         AccurateMath.toIntExact(-1L + Integer.MIN_VALUE);
1769     }
1770 
1771     @Test(expected = ArithmeticException.class)
1772     public void testToIntExactTooHigh() {
1773         AccurateMath.toIntExact(+1L + Integer.MAX_VALUE);
1774     }
1775 
1776     @Test
1777     public void testToIntExact() {
1778         for (int n = -1000; n < 1000; ++n) {
1779             assertEquals(n, AccurateMath.toIntExact(0L + n));
1780         }
1781         assertEquals(Integer.MIN_VALUE, AccurateMath.toIntExact(0L + Integer.MIN_VALUE));
1782         assertEquals(Integer.MAX_VALUE, AccurateMath.toIntExact(0L + Integer.MAX_VALUE));
1783     }
1784 
1785     @Test
1786     public void testFloorDivInt() {
1787         assertEquals(+1, AccurateMath.floorDiv(+4, +3));
1788         assertEquals(-2, AccurateMath.floorDiv(-4, +3));
1789         assertEquals(-2, AccurateMath.floorDiv(+4, -3));
1790         assertEquals(+1, AccurateMath.floorDiv(-4, -3));
1791         try {
1792             AccurateMath.floorDiv(1, 0);
1793             fail("an exception should have been thrown");
1794         } catch (ArithmeticException mae) {
1795             // expected
1796         }
1797         for (int a = -100; a <= 100; ++a) {
1798             for (int b = -100; b <= 100; ++b) {
1799                 if (b != 0) {
1800                     assertEquals(poorManFloorDiv(a, b), AccurateMath.floorDiv(a, b));
1801                 }
1802             }
1803         }
1804     }
1805 
1806     @Test
1807     public void testFloorModInt() {
1808         assertEquals(+1, AccurateMath.floorMod(+4, +3));
1809         assertEquals(+2, AccurateMath.floorMod(-4, +3));
1810         assertEquals(-2, AccurateMath.floorMod(+4, -3));
1811         assertEquals(-1, AccurateMath.floorMod(-4, -3));
1812         try {
1813             AccurateMath.floorMod(1, 0);
1814             fail("an exception should have been thrown");
1815         } catch (ArithmeticException mae) {
1816             // expected
1817         }
1818         for (int a = -100; a <= 100; ++a) {
1819             for (int b = -100; b <= 100; ++b) {
1820                 if (b != 0) {
1821                     assertEquals(poorManFloorMod(a, b), AccurateMath.floorMod(a, b));
1822                 }
1823             }
1824         }
1825     }
1826 
1827     @Test
1828     public void testFloorDivModInt() {
1829         UniformRandomProvider rng = RandomSource.WELL_1024_A.create(0x7ccab45edeaab90aL);
1830         for (int i = 0; i < 10000; ++i) {
1831             int a = rng.nextInt();
1832             int b = rng.nextInt();
1833             if (b == 0) {
1834                 try {
1835                     AccurateMath.floorDiv(a, b);
1836                     fail("an exception should have been thrown");
1837                 } catch (ArithmeticException mae) {
1838                     // expected
1839                 }
1840             } else {
1841                 int d = AccurateMath.floorDiv(a, b);
1842                 int m = AccurateMath.floorMod(a, b);
1843                 assertEquals(AccurateMath.toIntExact(poorManFloorDiv(a, b)), d);
1844                 assertEquals(AccurateMath.toIntExact(poorManFloorMod(a, b)), m);
1845                 assertEquals(a, d * b + m);
1846                 if (b < 0) {
1847                     assertTrue(m <= 0);
1848                     assertTrue(-m < -b);
1849                 } else {
1850                     assertTrue(m >= 0);
1851                     assertTrue(m < b);
1852                 }
1853             }
1854         }
1855     }
1856 
1857     @Test
1858     public void testFloorDivLong() {
1859         assertEquals(+1L, AccurateMath.floorDiv(+4L, +3L));
1860         assertEquals(-2L, AccurateMath.floorDiv(-4L, +3L));
1861         assertEquals(-2L, AccurateMath.floorDiv(+4L, -3L));
1862         assertEquals(+1L, AccurateMath.floorDiv(-4L, -3L));
1863         try {
1864             AccurateMath.floorDiv(1L, 0L);
1865             fail("an exception should have been thrown");
1866         } catch (ArithmeticException mae) {
1867             // expected
1868         }
1869         for (long a = -100L; a <= 100L; ++a) {
1870             for (long b = -100L; b <= 100L; ++b) {
1871                 if (b != 0) {
1872                     assertEquals(poorManFloorDiv(a, b), AccurateMath.floorDiv(a, b));
1873                 }
1874             }
1875         }
1876     }
1877 
1878     @Test
1879     public void testFloorModLong() {
1880         assertEquals(+1L, AccurateMath.floorMod(+4L, +3L));
1881         assertEquals(+2L, AccurateMath.floorMod(-4L, +3L));
1882         assertEquals(-2L, AccurateMath.floorMod(+4L, -3L));
1883         assertEquals(-1L, AccurateMath.floorMod(-4L, -3L));
1884         try {
1885             AccurateMath.floorMod(1L, 0L);
1886             fail("an exception should have been thrown");
1887         } catch (ArithmeticException mae) {
1888             // expected
1889         }
1890         for (long a = -100L; a <= 100L; ++a) {
1891             for (long b = -100L; b <= 100L; ++b) {
1892                 if (b != 0) {
1893                     assertEquals(poorManFloorMod(a, b), AccurateMath.floorMod(a, b));
1894                 }
1895             }
1896         }
1897     }
1898 
1899     @Test
1900     public void testFloorDivModLong() {
1901         UniformRandomProvider rng = RandomSource.WELL_1024_A.create(0xb87b9bc14c96ccd5L);
1902         for (int i = 0; i < 10000; ++i) {
1903             long a = rng.nextLong();
1904             long b = rng.nextLong();
1905             if (b == 0) {
1906                 try {
1907                     AccurateMath.floorDiv(a, b);
1908                     fail("an exception should have been thrown");
1909                 } catch (ArithmeticException mae) {
1910                     // expected
1911                 }
1912             } else {
1913                 long d = AccurateMath.floorDiv(a, b);
1914                 long m = AccurateMath.floorMod(a, b);
1915                 assertEquals(poorManFloorDiv(a, b), d);
1916                 assertEquals(poorManFloorMod(a, b), m);
1917                 assertEquals(a, d * b + m);
1918                 if (b < 0) {
1919                     assertTrue(m <= 0);
1920                     assertTrue(-m < -b);
1921                 } else {
1922                     assertTrue(m >= 0);
1923                     assertTrue(m < b);
1924                 }
1925             }
1926         }
1927     }
1928 
1929     private long poorManFloorDiv(long a, long b) {
1930 
1931         // find q0, r0 such that a = q0 b + r0
1932         BigInteger q0 = BigInteger.valueOf(a / b);
1933         BigInteger r0 = BigInteger.valueOf(a % b);
1934         BigInteger fd = BigInteger.valueOf(Integer.MIN_VALUE);
1935         BigInteger bigB = BigInteger.valueOf(b);
1936 
1937         for (int k = -2; k < 2; ++k) {
1938             // find another pair q, r such that a = q b + r
1939             BigInteger bigK = BigInteger.valueOf(k);
1940             BigInteger q = q0.subtract(bigK);
1941             BigInteger r = r0.add(bigK.multiply(bigB));
1942             if (r.abs().compareTo(bigB.abs()) < 0 &&
1943                 (r.longValue() == 0L || ((r.longValue() ^ b) & 0x8000000000000000L) == 0)) {
1944                 if (fd.compareTo(q) < 0) {
1945                     fd = q;
1946                 }
1947             }
1948         }
1949 
1950         return fd.longValue();
1951     }
1952 
1953     private long poorManFloorMod(long a, long b) {
1954         return a - b * poorManFloorDiv(a, b);
1955     }
1956 
1957     /**
1958      * http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6430675
1959      */
1960     @Test
1961     public void testRoundDown() {
1962         double x = 0x1.fffffffffffffp-2; // greatest floating point value less than 0.5
1963         assertTrue(x < 0.5d);
1964         assertEquals(0, AccurateMath.round(x));
1965 
1966         x = 4503599627370497.0; // x = Math.pow(2, 52) + 1;
1967         assertEquals("4503599627370497", new BigDecimal(x).toString());
1968         assertEquals(x, Math.rint(x), 0.0);
1969         assertEquals(x, AccurateMath.round(x), 0.0);
1970         //assertTrue(x == Math.round(x)); // fails with Java 7, fixed in Java 8
1971     }
1972 }