1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with this
4    * work for additional information regarding copyright ownership. The ASF
5    * licenses this file to You under the Apache License, Version 2.0 (the
6    * "License"); you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
9    * or agreed to in writing, software distributed under the License is
10   * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11   * KIND, either express or implied. See the License for the specific language
12   * governing permissions and limitations under the License.
13   */
14  package org.apache.commons.math.util;
15  
16  import java.math.BigDecimal;
17  
18  import junit.framework.Test;
19  import junit.framework.TestCase;
20  import junit.framework.TestSuite;
21  
22  import org.apache.commons.math.TestUtils;
23  
24  /**
25   * Test cases for the MathUtils class.
26   * @version $Revision: 619980 $ $Date: 2007-08-16 15:36:33 -0500 (Thu, 16 Aug
27   *          2007) $
28   */
29  public final class MathUtilsTest extends TestCase {
30  
31      public MathUtilsTest(String name) {
32          super(name);
33      }
34  
35      public static Test suite() {
36          TestSuite suite = new TestSuite(MathUtilsTest.class);
37          suite.setName("MathUtils Tests");
38          return suite;
39      }
40  
41      /**
42       * Exact recursive implementation to test against
43       */
44      private long binomialCoefficient(int n, int k) {
45          if ((n == k) || (k == 0)) {
46              return 1;
47          }
48          if ((k == 1) || (k == n - 1)) {
49              return n;
50          }
51          return binomialCoefficient(n - 1, k - 1) + binomialCoefficient(n - 1, k);
52      }
53  
54      /**
55       * Exact direct multiplication implementation to test against
56       */
57      private long factorial(int n) {
58          long result = 1;
59          for (int i = 2; i <= n; i++) {
60              result *= i;
61          }
62          return result;
63      }
64  
65      /** Verify that b(0,0) = 1 */
66      public void test0Choose0() {
67          assertEquals(MathUtils.binomialCoefficientDouble(0, 0), 1d, 0);
68          assertEquals(MathUtils.binomialCoefficientLog(0, 0), 0d, 0);
69          assertEquals(MathUtils.binomialCoefficient(0, 0), 1);
70      }
71  
72      public void testAddAndCheck() {
73          int big = Integer.MAX_VALUE;
74          int bigNeg = Integer.MIN_VALUE;
75          assertEquals(big, MathUtils.addAndCheck(big, 0));
76          try {
77              MathUtils.addAndCheck(big, 1);
78              fail("Expecting ArithmeticException");
79          } catch (ArithmeticException ex) {
80          }
81          try {
82              MathUtils.addAndCheck(bigNeg, -1);
83              fail("Expecting ArithmeticException");
84          } catch (ArithmeticException ex) {
85          }
86      }
87  
88      public void testAddAndCheckLong() {
89          long max = Long.MAX_VALUE;
90          long min = Long.MIN_VALUE;
91          assertEquals(max, MathUtils.addAndCheck(max, 0L));
92          assertEquals(min, MathUtils.addAndCheck(min, 0L));
93          assertEquals(max, MathUtils.addAndCheck(0L, max));
94          assertEquals(min, MathUtils.addAndCheck(0L, min));
95          assertEquals(1, MathUtils.addAndCheck(-1L, 2L));
96          assertEquals(1, MathUtils.addAndCheck(2L, -1L));
97          testAddAndCheckLongFailure(max, 1L);
98          testAddAndCheckLongFailure(min, -1L);
99          testAddAndCheckLongFailure(1L, max);
100         testAddAndCheckLongFailure(-1L, min);
101     }
102 
103     private void testAddAndCheckLongFailure(long a, long b) {
104         try {
105             MathUtils.addAndCheck(a, b);
106             fail("Expecting ArithmeticException");
107         } catch (ArithmeticException ex) {
108             // success
109         }
110     }
111 
112     public void testBinomialCoefficient() {
113         long[] bcoef5 = {
114             1,
115             5,
116             10,
117             10,
118             5,
119             1 };
120         long[] bcoef6 = {
121             1,
122             6,
123             15,
124             20,
125             15,
126             6,
127             1 };
128         for (int i = 0; i < 6; i++) {
129             assertEquals("5 choose " + i, bcoef5[i], MathUtils.binomialCoefficient(5, i));
130         }
131         for (int i = 0; i < 7; i++) {
132             assertEquals("6 choose " + i, bcoef6[i], MathUtils.binomialCoefficient(6, i));
133         }
134 
135         for (int n = 1; n < 10; n++) {
136             for (int k = 0; k <= n; k++) {
137                 assertEquals(n + " choose " + k, binomialCoefficient(n, k), MathUtils.binomialCoefficient(n, k));
138                 assertEquals(n + " choose " + k, (double)binomialCoefficient(n, k), MathUtils.binomialCoefficientDouble(n, k), Double.MIN_VALUE);
139                 assertEquals(n + " choose " + k, Math.log((double)binomialCoefficient(n, k)), MathUtils.binomialCoefficientLog(n, k), 10E-12);
140             }
141         }
142 
143         /*
144          * Takes a long time for recursion to unwind, but succeeds and yields
145          * exact value = 2,333,606,220
146          * assertEquals(MathUtils.binomialCoefficient(34,17),
147          * binomialCoefficient(34,17));
148          */
149     }
150 
151     public void testBinomialCoefficientFail() {
152         try {
153             MathUtils.binomialCoefficient(4, 5);
154             fail("expecting IllegalArgumentException");
155         } catch (IllegalArgumentException ex) {
156             ;
157         }
158 
159         try {
160             MathUtils.binomialCoefficientDouble(4, 5);
161             fail("expecting IllegalArgumentException");
162         } catch (IllegalArgumentException ex) {
163             ;
164         }
165 
166         try {
167             MathUtils.binomialCoefficientLog(4, 5);
168             fail("expecting IllegalArgumentException");
169         } catch (IllegalArgumentException ex) {
170             ;
171         }
172         try {
173             MathUtils.binomialCoefficient(67, 34);
174             fail("expecting ArithmeticException");
175         } catch (ArithmeticException ex) {
176             ;
177         }
178         double x = MathUtils.binomialCoefficientDouble(1030, 515);
179         assertTrue("expecting infinite binomial coefficient", Double.isInfinite(x));
180     }
181 
182     public void testCosh() {
183         double x = 3.0;
184         double expected = 10.06766;
185         assertEquals(expected, MathUtils.cosh(x), 1.0e-5);
186     }
187 
188     public void testCoshNaN() {
189         assertTrue(Double.isNaN(MathUtils.cosh(Double.NaN)));
190     }
191 
192     public void testEquals() {
193         double[] testArray = {
194             Double.NaN,
195             Double.POSITIVE_INFINITY,
196             Double.NEGATIVE_INFINITY,
197             1d,
198             0d };
199         for (int i = 0; i < testArray.length; i++) {
200             for (int j = 0; j < testArray.length; j++) {
201                 if (i == j) {
202                     assertTrue(MathUtils.equals(testArray[i], testArray[j]));
203                     assertTrue(MathUtils.equals(testArray[j], testArray[i]));
204                 } else {
205                     assertTrue(!MathUtils.equals(testArray[i], testArray[j]));
206                     assertTrue(!MathUtils.equals(testArray[j], testArray[i]));
207                 }
208             }
209         }
210     }
211 
212     public void testArrayEquals() {
213         assertFalse(MathUtils.equals(new double[] { 1d }, null));
214         assertFalse(MathUtils.equals(null, new double[] { 1d }));
215         assertTrue(MathUtils.equals((double[]) null, (double[]) null));
216 
217         assertFalse(MathUtils.equals(new double[] { 1d }, new double[0]));
218         assertTrue(MathUtils.equals(new double[] { 1d }, new double[] { 1d }));
219         assertTrue(MathUtils.equals(new double[] {
220                                       Double.NaN, Double.POSITIVE_INFINITY,
221                                       Double.NEGATIVE_INFINITY, 1d, 0d
222                                     }, new double[] {
223                                       Double.NaN, Double.POSITIVE_INFINITY,
224                                       Double.NEGATIVE_INFINITY, 1d, 0d
225                                     }));
226         assertFalse(MathUtils.equals(new double[] { Double.POSITIVE_INFINITY },
227                                      new double[] { Double.NEGATIVE_INFINITY }));
228         assertFalse(MathUtils.equals(new double[] { 1d },
229                                      new double[] { MathUtils.nextAfter(1d, 2d) }));
230 
231     }
232 
233     public void testFactorial() {
234         for (int i = 1; i < 10; i++) {
235             assertEquals(i + "! ", factorial(i), MathUtils.factorial(i));
236             assertEquals(i + "! ", (double)factorial(i), MathUtils.factorialDouble(i), Double.MIN_VALUE);
237             assertEquals(i + "! ", Math.log((double)factorial(i)), MathUtils.factorialLog(i), 10E-12);
238         }
239         assertEquals("0", 1, MathUtils.factorial(0));
240         assertEquals("0", 1.0d, MathUtils.factorialDouble(0), 1E-14);
241         assertEquals("0", 0.0d, MathUtils.factorialLog(0), 1E-14);
242     }
243 
244     public void testFactorialFail() {
245         try {
246             MathUtils.factorial(-1);
247             fail("expecting IllegalArgumentException");
248         } catch (IllegalArgumentException ex) {
249             ;
250         }
251         try {
252             MathUtils.factorialDouble(-1);
253             fail("expecting IllegalArgumentException");
254         } catch (IllegalArgumentException ex) {
255             ;
256         }
257         try {
258             MathUtils.factorialLog(-1);
259             fail("expecting IllegalArgumentException");
260         } catch (IllegalArgumentException ex) {
261             ;
262         }
263         try {
264             MathUtils.factorial(21);
265             fail("expecting ArithmeticException");
266         } catch (ArithmeticException ex) {
267             ;
268         }
269         assertTrue("expecting infinite factorial value", Double.isInfinite(MathUtils.factorialDouble(171)));
270     }
271 
272     public void testGcd() {
273         int a = 30;
274         int b = 50;
275         int c = 77;
276 
277         assertEquals(0, MathUtils.gcd(0, 0));
278 
279         assertEquals(b, MathUtils.gcd(0, b));
280         assertEquals(a, MathUtils.gcd(a, 0));
281         assertEquals(b, MathUtils.gcd(0, -b));
282         assertEquals(a, MathUtils.gcd(-a, 0));
283 
284         assertEquals(10, MathUtils.gcd(a, b));
285         assertEquals(10, MathUtils.gcd(-a, b));
286         assertEquals(10, MathUtils.gcd(a, -b));
287         assertEquals(10, MathUtils.gcd(-a, -b));
288 
289         assertEquals(1, MathUtils.gcd(a, c));
290         assertEquals(1, MathUtils.gcd(-a, c));
291         assertEquals(1, MathUtils.gcd(a, -c));
292         assertEquals(1, MathUtils.gcd(-a, -c));
293     }
294 
295     public void testHash() {
296         double[] testArray = {
297             Double.NaN,
298             Double.POSITIVE_INFINITY,
299             Double.NEGATIVE_INFINITY,
300             1d,
301             0d,
302             1E-14,
303             (1 + 1E-14),
304             Double.MIN_VALUE,
305             Double.MAX_VALUE };
306         for (int i = 0; i < testArray.length; i++) {
307             for (int j = 0; j < testArray.length; j++) {
308                 if (i == j) {
309                     assertEquals(MathUtils.hash(testArray[i]), MathUtils.hash(testArray[j]));
310                     assertEquals(MathUtils.hash(testArray[j]), MathUtils.hash(testArray[i]));
311                 } else {
312                     assertTrue(MathUtils.hash(testArray[i]) != MathUtils.hash(testArray[j]));
313                     assertTrue(MathUtils.hash(testArray[j]) != MathUtils.hash(testArray[i]));
314                 }
315             }
316         }
317     }
318 
319     public void testArrayHash() {
320         assertEquals(0, MathUtils.hash((double[]) null));
321         assertEquals(MathUtils.hash(new double[] {
322                                       Double.NaN, Double.POSITIVE_INFINITY,
323                                       Double.NEGATIVE_INFINITY, 1d, 0d
324                                     }),
325                      MathUtils.hash(new double[] {
326                                       Double.NaN, Double.POSITIVE_INFINITY,
327                                       Double.NEGATIVE_INFINITY, 1d, 0d
328                                     }));
329         assertFalse(MathUtils.hash(new double[] { 1d }) ==
330                     MathUtils.hash(new double[] { MathUtils.nextAfter(1d, 2d) }));
331         assertFalse(MathUtils.hash(new double[] { 1d }) ==
332                     MathUtils.hash(new double[] { 1d, 1d }));
333     }
334 
335     public void testIndicatorByte() {
336         assertEquals((byte)1, MathUtils.indicator((byte)2));
337         assertEquals((byte)1, MathUtils.indicator((byte)0));
338         assertEquals((byte)(-1), MathUtils.indicator((byte)(-2)));
339     }
340 
341     public void testIndicatorDouble() {
342         double delta = 0.0;
343         assertEquals(1.0, MathUtils.indicator(2.0), delta);
344         assertEquals(1.0, MathUtils.indicator(0.0), delta);
345         assertEquals(-1.0, MathUtils.indicator(-2.0), delta);
346     }
347 
348     public void testIndicatorFloat() {
349         float delta = 0.0F;
350         assertEquals(1.0F, MathUtils.indicator(2.0F), delta);
351         assertEquals(1.0F, MathUtils.indicator(0.0F), delta);
352         assertEquals(-1.0F, MathUtils.indicator(-2.0F), delta);
353     }
354 
355     public void testIndicatorInt() {
356         assertEquals((int)1, MathUtils.indicator((int)(2)));
357         assertEquals((int)1, MathUtils.indicator((int)(0)));
358         assertEquals((int)(-1), MathUtils.indicator((int)(-2)));
359     }
360 
361     public void testIndicatorLong() {
362         assertEquals(1L, MathUtils.indicator(2L));
363         assertEquals(1L, MathUtils.indicator(0L));
364         assertEquals(-1L, MathUtils.indicator(-2L));
365     }
366 
367     public void testIndicatorShort() {
368         assertEquals((short)1, MathUtils.indicator((short)2));
369         assertEquals((short)1, MathUtils.indicator((short)0));
370         assertEquals((short)(-1), MathUtils.indicator((short)(-2)));
371     }
372 
373     public void testLcm() {
374         int a = 30;
375         int b = 50;
376         int c = 77;
377 
378         assertEquals(0, MathUtils.lcm(0, b));
379         assertEquals(0, MathUtils.lcm(a, 0));
380         assertEquals(b, MathUtils.lcm(1, b));
381         assertEquals(a, MathUtils.lcm(a, 1));
382         assertEquals(150, MathUtils.lcm(a, b));
383         assertEquals(150, MathUtils.lcm(-a, b));
384         assertEquals(150, MathUtils.lcm(a, -b));
385         assertEquals(2310, MathUtils.lcm(a, c));
386 
387         try {
388             MathUtils.lcm(Integer.MAX_VALUE, Integer.MAX_VALUE - 1);
389             fail("Expecting ArithmeticException");
390         } catch (ArithmeticException ex) {
391             // expected
392         }
393     }
394 
395     public void testLog() {
396         assertEquals(2.0, MathUtils.log(2, 4), 0);
397         assertEquals(3.0, MathUtils.log(2, 8), 0);
398         assertTrue(Double.isNaN(MathUtils.log(-1, 1)));
399         assertTrue(Double.isNaN(MathUtils.log(1, -1)));
400         assertTrue(Double.isNaN(MathUtils.log(0, 0)));
401         assertEquals(0, MathUtils.log(0, 10), 0);
402         assertEquals(Double.NEGATIVE_INFINITY, MathUtils.log(10, 0), 0);
403     }
404 
405     public void testMulAndCheck() {
406         int big = Integer.MAX_VALUE;
407         int bigNeg = Integer.MIN_VALUE;
408         assertEquals(big, MathUtils.mulAndCheck(big, 1));
409         try {
410             MathUtils.mulAndCheck(big, 2);
411             fail("Expecting ArithmeticException");
412         } catch (ArithmeticException ex) {
413         }
414         try {
415             MathUtils.mulAndCheck(bigNeg, 2);
416             fail("Expecting ArithmeticException");
417         } catch (ArithmeticException ex) {
418         }
419     }
420 
421     public void testMulAndCheckLong() {
422         long max = Long.MAX_VALUE;
423         long min = Long.MIN_VALUE;
424         assertEquals(max, MathUtils.mulAndCheck(max, 1L));
425         assertEquals(min, MathUtils.mulAndCheck(min, 1L));
426         assertEquals(0L, MathUtils.mulAndCheck(max, 0L));
427         assertEquals(0L, MathUtils.mulAndCheck(min, 0L));
428         assertEquals(max, MathUtils.mulAndCheck(1L, max));
429         assertEquals(min, MathUtils.mulAndCheck(1L, min));
430         assertEquals(0L, MathUtils.mulAndCheck(0L, max));
431         assertEquals(0L, MathUtils.mulAndCheck(0L, min));
432         testMulAndCheckLongFailure(max, 2L);
433         testMulAndCheckLongFailure(2L, max);
434         testMulAndCheckLongFailure(min, 2L);
435         testMulAndCheckLongFailure(2L, min);
436         testMulAndCheckLongFailure(min, -1L);
437         testMulAndCheckLongFailure(-1L, min);
438     }
439 
440     private void testMulAndCheckLongFailure(long a, long b) {
441         try {
442             MathUtils.mulAndCheck(a, b);
443             fail("Expecting ArithmeticException");
444         } catch (ArithmeticException ex) {
445             // success
446         }
447     }
448 
449     public void testNextAfter() {
450         // 0x402fffffffffffff 0x404123456789abcd -> 4030000000000000
451         assertEquals(16.0, MathUtils.nextAfter(15.999999999999998, 34.27555555555555), 0.0);
452 
453         // 0xc02fffffffffffff 0x404123456789abcd -> c02ffffffffffffe
454         assertEquals(-15.999999999999996, MathUtils.nextAfter(-15.999999999999998, 34.27555555555555), 0.0);
455 
456         // 0x402fffffffffffff 0x400123456789abcd -> 402ffffffffffffe
457         assertEquals(15.999999999999996, MathUtils.nextAfter(15.999999999999998, 2.142222222222222), 0.0);
458 
459         // 0xc02fffffffffffff 0x400123456789abcd -> c02ffffffffffffe
460         assertEquals(-15.999999999999996, MathUtils.nextAfter(-15.999999999999998, 2.142222222222222), 0.0);
461 
462         // 0x4020000000000000 0x404123456789abcd -> 4020000000000001
463         assertEquals(8.000000000000002, MathUtils.nextAfter(8.0, 34.27555555555555), 0.0);
464 
465         // 0xc020000000000000 0x404123456789abcd -> c01fffffffffffff
466         assertEquals(-7.999999999999999, MathUtils.nextAfter(-8.0, 34.27555555555555), 0.0);
467 
468         // 0x4020000000000000 0x400123456789abcd -> 401fffffffffffff
469         assertEquals(7.999999999999999, MathUtils.nextAfter(8.0, 2.142222222222222), 0.0);
470 
471         // 0xc020000000000000 0x400123456789abcd -> c01fffffffffffff
472         assertEquals(-7.999999999999999, MathUtils.nextAfter(-8.0, 2.142222222222222), 0.0);
473 
474         // 0x3f2e43753d36a223 0x3f2e43753d36a224 -> 3f2e43753d36a224
475         assertEquals(2.308922399667661E-4, MathUtils.nextAfter(2.3089223996676606E-4, 2.308922399667661E-4), 0.0);
476 
477         // 0x3f2e43753d36a223 0x3f2e43753d36a223 -> 3f2e43753d36a224
478         assertEquals(2.308922399667661E-4, MathUtils.nextAfter(2.3089223996676606E-4, 2.3089223996676606E-4), 0.0);
479 
480         // 0x3f2e43753d36a223 0x3f2e43753d36a222 -> 3f2e43753d36a222
481         assertEquals(2.3089223996676603E-4, MathUtils.nextAfter(2.3089223996676606E-4, 2.3089223996676603E-4), 0.0);
482 
483         // 0x3f2e43753d36a223 0xbf2e43753d36a224 -> 3f2e43753d36a222
484         assertEquals(2.3089223996676603E-4, MathUtils.nextAfter(2.3089223996676606E-4, -2.308922399667661E-4), 0.0);
485 
486         // 0x3f2e43753d36a223 0xbf2e43753d36a223 -> 3f2e43753d36a222
487         assertEquals(2.3089223996676603E-4, MathUtils.nextAfter(2.3089223996676606E-4, -2.3089223996676606E-4), 0.0);
488 
489         // 0x3f2e43753d36a223 0xbf2e43753d36a222 -> 3f2e43753d36a222
490         assertEquals(2.3089223996676603E-4, MathUtils.nextAfter(2.3089223996676606E-4, -2.3089223996676603E-4), 0.0);
491 
492         // 0xbf2e43753d36a223 0x3f2e43753d36a224 -> bf2e43753d36a222
493         assertEquals(-2.3089223996676603E-4, MathUtils.nextAfter(-2.3089223996676606E-4, 2.308922399667661E-4), 0.0);
494 
495         // 0xbf2e43753d36a223 0x3f2e43753d36a223 -> bf2e43753d36a222
496         assertEquals(-2.3089223996676603E-4, MathUtils.nextAfter(-2.3089223996676606E-4, 2.3089223996676606E-4), 0.0);
497 
498         // 0xbf2e43753d36a223 0x3f2e43753d36a222 -> bf2e43753d36a222
499         assertEquals(-2.3089223996676603E-4, MathUtils.nextAfter(-2.3089223996676606E-4, 2.3089223996676603E-4), 0.0);
500 
501         // 0xbf2e43753d36a223 0xbf2e43753d36a224 -> bf2e43753d36a224
502         assertEquals(-2.308922399667661E-4, MathUtils.nextAfter(-2.3089223996676606E-4, -2.308922399667661E-4), 0.0);
503 
504         // 0xbf2e43753d36a223 0xbf2e43753d36a223 -> bf2e43753d36a224
505         assertEquals(-2.308922399667661E-4, MathUtils.nextAfter(-2.3089223996676606E-4, -2.3089223996676606E-4), 0.0);
506 
507         // 0xbf2e43753d36a223 0xbf2e43753d36a222 -> bf2e43753d36a222
508         assertEquals(-2.3089223996676603E-4, MathUtils.nextAfter(-2.3089223996676606E-4, -2.3089223996676603E-4), 0.0);
509 
510     }
511 
512     public void testNextAfterSpecialCases() {
513         assertTrue(Double.isInfinite(MathUtils.nextAfter(Double.NEGATIVE_INFINITY, 0)));
514         assertTrue(Double.isInfinite(MathUtils.nextAfter(Double.POSITIVE_INFINITY, 0)));
515         assertTrue(Double.isNaN(MathUtils.nextAfter(Double.NaN, 0)));
516         assertTrue(Double.isInfinite(MathUtils.nextAfter(Double.MAX_VALUE, Double.POSITIVE_INFINITY)));
517         assertTrue(Double.isInfinite(MathUtils.nextAfter(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY)));
518         assertEquals(Double.MIN_VALUE, MathUtils.nextAfter(0, 1), 0);
519         assertEquals(-Double.MIN_VALUE, MathUtils.nextAfter(0, -1), 0);
520         assertEquals(0, MathUtils.nextAfter(Double.MIN_VALUE, -1), 0);
521         assertEquals(0, MathUtils.nextAfter(-Double.MIN_VALUE, 1), 0);
522     }
523 
524     public void testNormalizeAngle() {
525         for (double a = -15.0; a <= 15.0; a += 0.1) {
526             for (double b = -15.0; b <= 15.0; b += 0.2) {
527                 double c = MathUtils.normalizeAngle(a, b);
528                 assertTrue((b - Math.PI) <= c);
529                 assertTrue(c <= (b + Math.PI));
530                 double twoK = Math.rint((a - c) / Math.PI);
531                 assertEquals(c, a - twoK * Math.PI, 1.0e-14);
532             }
533         }
534     }
535 
536     public void testRoundDouble() {
537         double x = 1.234567890;
538         assertEquals(1.23, MathUtils.round(x, 2), 0.0);
539         assertEquals(1.235, MathUtils.round(x, 3), 0.0);
540         assertEquals(1.2346, MathUtils.round(x, 4), 0.0);
541 
542         // JIRA MATH-151
543         assertEquals(39.25, MathUtils.round(39.245, 2), 0.0);
544         assertEquals(39.24, MathUtils.round(39.245, 2, BigDecimal.ROUND_DOWN), 0.0);
545         double xx = 39.0;
546         xx = xx + 245d / 1000d;
547         assertEquals(39.25, MathUtils.round(xx, 2), 0.0);
548 
549         // BZ 35904
550         assertEquals(30.1d, MathUtils.round(30.095d, 2), 0.0d);
551         assertEquals(30.1d, MathUtils.round(30.095d, 1), 0.0d);
552         assertEquals(33.1d, MathUtils.round(33.095d, 1), 0.0d);
553         assertEquals(33.1d, MathUtils.round(33.095d, 2), 0.0d);
554         assertEquals(50.09d, MathUtils.round(50.085d, 2), 0.0d);
555         assertEquals(50.19d, MathUtils.round(50.185d, 2), 0.0d);
556         assertEquals(50.01d, MathUtils.round(50.005d, 2), 0.0d);
557         assertEquals(30.01d, MathUtils.round(30.005d, 2), 0.0d);
558         assertEquals(30.65d, MathUtils.round(30.645d, 2), 0.0d);
559 
560         assertEquals(1.24, MathUtils.round(x, 2, BigDecimal.ROUND_CEILING), 0.0);
561         assertEquals(1.235, MathUtils.round(x, 3, BigDecimal.ROUND_CEILING), 0.0);
562         assertEquals(1.2346, MathUtils.round(x, 4, BigDecimal.ROUND_CEILING), 0.0);
563         assertEquals(-1.23, MathUtils.round(-x, 2, BigDecimal.ROUND_CEILING), 0.0);
564         assertEquals(-1.234, MathUtils.round(-x, 3, BigDecimal.ROUND_CEILING), 0.0);
565         assertEquals(-1.2345, MathUtils.round(-x, 4, BigDecimal.ROUND_CEILING), 0.0);
566 
567         assertEquals(1.23, MathUtils.round(x, 2, BigDecimal.ROUND_DOWN), 0.0);
568         assertEquals(1.234, MathUtils.round(x, 3, BigDecimal.ROUND_DOWN), 0.0);
569         assertEquals(1.2345, MathUtils.round(x, 4, BigDecimal.ROUND_DOWN), 0.0);
570         assertEquals(-1.23, MathUtils.round(-x, 2, BigDecimal.ROUND_DOWN), 0.0);
571         assertEquals(-1.234, MathUtils.round(-x, 3, BigDecimal.ROUND_DOWN), 0.0);
572         assertEquals(-1.2345, MathUtils.round(-x, 4, BigDecimal.ROUND_DOWN), 0.0);
573 
574         assertEquals(1.23, MathUtils.round(x, 2, BigDecimal.ROUND_FLOOR), 0.0);
575         assertEquals(1.234, MathUtils.round(x, 3, BigDecimal.ROUND_FLOOR), 0.0);
576         assertEquals(1.2345, MathUtils.round(x, 4, BigDecimal.ROUND_FLOOR), 0.0);
577         assertEquals(-1.24, MathUtils.round(-x, 2, BigDecimal.ROUND_FLOOR), 0.0);
578         assertEquals(-1.235, MathUtils.round(-x, 3, BigDecimal.ROUND_FLOOR), 0.0);
579         assertEquals(-1.2346, MathUtils.round(-x, 4, BigDecimal.ROUND_FLOOR), 0.0);
580 
581         assertEquals(1.23, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_DOWN), 0.0);
582         assertEquals(1.235, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
583         assertEquals(1.2346, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_DOWN), 0.0);
584         assertEquals(-1.23, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_DOWN), 0.0);
585         assertEquals(-1.235, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
586         assertEquals(-1.2346, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_DOWN), 0.0);
587         assertEquals(1.234, MathUtils.round(1.2345, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
588         assertEquals(-1.234, MathUtils.round(-1.2345, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
589 
590         assertEquals(1.23, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_EVEN), 0.0);
591         assertEquals(1.235, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
592         assertEquals(1.2346, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_EVEN), 0.0);
593         assertEquals(-1.23, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_EVEN), 0.0);
594         assertEquals(-1.235, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
595         assertEquals(-1.2346, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_EVEN), 0.0);
596         assertEquals(1.234, MathUtils.round(1.2345, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
597         assertEquals(-1.234, MathUtils.round(-1.2345, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
598         assertEquals(1.236, MathUtils.round(1.2355, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
599         assertEquals(-1.236, MathUtils.round(-1.2355, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
600 
601         assertEquals(1.23, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_UP), 0.0);
602         assertEquals(1.235, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_UP), 0.0);
603         assertEquals(1.2346, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_UP), 0.0);
604         assertEquals(-1.23, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_UP), 0.0);
605         assertEquals(-1.235, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_UP), 0.0);
606         assertEquals(-1.2346, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_UP), 0.0);
607         assertEquals(1.235, MathUtils.round(1.2345, 3, BigDecimal.ROUND_HALF_UP), 0.0);
608         assertEquals(-1.235, MathUtils.round(-1.2345, 3, BigDecimal.ROUND_HALF_UP), 0.0);
609 
610         assertEquals(-1.23, MathUtils.round(-1.23, 2, BigDecimal.ROUND_UNNECESSARY), 0.0);
611         assertEquals(1.23, MathUtils.round(1.23, 2, BigDecimal.ROUND_UNNECESSARY), 0.0);
612 
613         try {
614             MathUtils.round(1.234, 2, BigDecimal.ROUND_UNNECESSARY);
615             fail();
616         } catch (ArithmeticException ex) {
617             // success
618         }
619 
620         assertEquals(1.24, MathUtils.round(x, 2, BigDecimal.ROUND_UP), 0.0);
621         assertEquals(1.235, MathUtils.round(x, 3, BigDecimal.ROUND_UP), 0.0);
622         assertEquals(1.2346, MathUtils.round(x, 4, BigDecimal.ROUND_UP), 0.0);
623         assertEquals(-1.24, MathUtils.round(-x, 2, BigDecimal.ROUND_UP), 0.0);
624         assertEquals(-1.235, MathUtils.round(-x, 3, BigDecimal.ROUND_UP), 0.0);
625         assertEquals(-1.2346, MathUtils.round(-x, 4, BigDecimal.ROUND_UP), 0.0);
626 
627         try {
628             MathUtils.round(1.234, 2, 1923);
629             fail();
630         } catch (IllegalArgumentException ex) {
631             // success
632         }
633 
634         // MATH-151
635         assertEquals(39.25, MathUtils.round(39.245, 2, BigDecimal.ROUND_HALF_UP), 0.0);
636 
637         // special values
638         TestUtils.assertEquals(Double.NaN, MathUtils.round(Double.NaN, 2), 0.0);
639         assertEquals(0.0, MathUtils.round(0.0, 2), 0.0);
640         assertEquals(Double.POSITIVE_INFINITY, MathUtils.round(Double.POSITIVE_INFINITY, 2), 0.0);
641         assertEquals(Double.NEGATIVE_INFINITY, MathUtils.round(Double.NEGATIVE_INFINITY, 2), 0.0);
642     }
643 
644     public void testRoundFloat() {
645         float x = 1.234567890f;
646         assertEquals(1.23f, MathUtils.round(x, 2), 0.0);
647         assertEquals(1.235f, MathUtils.round(x, 3), 0.0);
648         assertEquals(1.2346f, MathUtils.round(x, 4), 0.0);
649 
650         // BZ 35904
651         assertEquals(30.1f, MathUtils.round(30.095f, 2), 0.0f);
652         assertEquals(30.1f, MathUtils.round(30.095f, 1), 0.0f);
653         assertEquals(50.09f, MathUtils.round(50.085f, 2), 0.0f);
654         assertEquals(50.19f, MathUtils.round(50.185f, 2), 0.0f);
655         assertEquals(50.01f, MathUtils.round(50.005f, 2), 0.0f);
656         assertEquals(30.01f, MathUtils.round(30.005f, 2), 0.0f);
657         assertEquals(30.65f, MathUtils.round(30.645f, 2), 0.0f);
658 
659         assertEquals(1.24f, MathUtils.round(x, 2, BigDecimal.ROUND_CEILING), 0.0);
660         assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_CEILING), 0.0);
661         assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_CEILING), 0.0);
662         assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_CEILING), 0.0);
663         assertEquals(-1.234f, MathUtils.round(-x, 3, BigDecimal.ROUND_CEILING), 0.0);
664         assertEquals(-1.2345f, MathUtils.round(-x, 4, BigDecimal.ROUND_CEILING), 0.0);
665 
666         assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_DOWN), 0.0);
667         assertEquals(1.234f, MathUtils.round(x, 3, BigDecimal.ROUND_DOWN), 0.0);
668         assertEquals(1.2345f, MathUtils.round(x, 4, BigDecimal.ROUND_DOWN), 0.0);
669         assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_DOWN), 0.0);
670         assertEquals(-1.234f, MathUtils.round(-x, 3, BigDecimal.ROUND_DOWN), 0.0);
671         assertEquals(-1.2345f, MathUtils.round(-x, 4, BigDecimal.ROUND_DOWN), 0.0);
672 
673         assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_FLOOR), 0.0);
674         assertEquals(1.234f, MathUtils.round(x, 3, BigDecimal.ROUND_FLOOR), 0.0);
675         assertEquals(1.2345f, MathUtils.round(x, 4, BigDecimal.ROUND_FLOOR), 0.0);
676         assertEquals(-1.24f, MathUtils.round(-x, 2, BigDecimal.ROUND_FLOOR), 0.0);
677         assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_FLOOR), 0.0);
678         assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_FLOOR), 0.0);
679 
680         assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_DOWN), 0.0);
681         assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
682         assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_DOWN), 0.0);
683         assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_DOWN), 0.0);
684         assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
685         assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_DOWN), 0.0);
686         assertEquals(1.234f, MathUtils.round(1.2345f, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
687         assertEquals(-1.234f, MathUtils.round(-1.2345f, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
688 
689         assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_EVEN), 0.0);
690         assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
691         assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_EVEN), 0.0);
692         assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_EVEN), 0.0);
693         assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
694         assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_EVEN), 0.0);
695         assertEquals(1.234f, MathUtils.round(1.2345f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
696         assertEquals(-1.234f, MathUtils.round(-1.2345f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
697         assertEquals(1.236f, MathUtils.round(1.2355f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
698         assertEquals(-1.236f, MathUtils.round(-1.2355f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
699 
700         assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_UP), 0.0);
701         assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_UP), 0.0);
702         assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_UP), 0.0);
703         assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_UP), 0.0);
704         assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_UP), 0.0);
705         assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_UP), 0.0);
706         assertEquals(1.235f, MathUtils.round(1.2345f, 3, BigDecimal.ROUND_HALF_UP), 0.0);
707         assertEquals(-1.235f, MathUtils.round(-1.2345f, 3, BigDecimal.ROUND_HALF_UP), 0.0);
708 
709         assertEquals(-1.23f, MathUtils.round(-1.23f, 2, BigDecimal.ROUND_UNNECESSARY), 0.0);
710         assertEquals(1.23f, MathUtils.round(1.23f, 2, BigDecimal.ROUND_UNNECESSARY), 0.0);
711 
712         try {
713             MathUtils.round(1.234f, 2, BigDecimal.ROUND_UNNECESSARY);
714             fail();
715         } catch (ArithmeticException ex) {
716             // success
717         }
718 
719         assertEquals(1.24f, MathUtils.round(x, 2, BigDecimal.ROUND_UP), 0.0);
720         assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_UP), 0.0);
721         assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_UP), 0.0);
722         assertEquals(-1.24f, MathUtils.round(-x, 2, BigDecimal.ROUND_UP), 0.0);
723         assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_UP), 0.0);
724         assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_UP), 0.0);
725 
726         try {
727             MathUtils.round(1.234f, 2, 1923);
728             fail();
729         } catch (IllegalArgumentException ex) {
730             // success
731         }
732 
733         // special values
734         TestUtils.assertEquals(Float.NaN, MathUtils.round(Float.NaN, 2), 0.0f);
735         assertEquals(0.0f, MathUtils.round(0.0f, 2), 0.0f);
736         assertEquals(Float.POSITIVE_INFINITY, MathUtils.round(Float.POSITIVE_INFINITY, 2), 0.0f);
737         assertEquals(Float.NEGATIVE_INFINITY, MathUtils.round(Float.NEGATIVE_INFINITY, 2), 0.0f);
738     }
739 
740     public void testSignByte() {
741         assertEquals((byte)1, MathUtils.indicator((byte)2));
742         assertEquals((byte)(-1), MathUtils.indicator((byte)(-2)));
743     }
744 
745     public void testSignDouble() {
746         double delta = 0.0;
747         assertEquals(1.0, MathUtils.indicator(2.0), delta);
748         assertEquals(-1.0, MathUtils.indicator(-2.0), delta);
749     }
750 
751     public void testSignFloat() {
752         float delta = 0.0F;
753         assertEquals(1.0F, MathUtils.indicator(2.0F), delta);
754         assertEquals(-1.0F, MathUtils.indicator(-2.0F), delta);
755     }
756 
757     public void testSignInt() {
758         assertEquals((int)1, MathUtils.indicator((int)(2)));
759         assertEquals((int)(-1), MathUtils.indicator((int)(-2)));
760     }
761 
762     public void testSignLong() {
763         assertEquals(1L, MathUtils.indicator(2L));
764         assertEquals(-1L, MathUtils.indicator(-2L));
765     }
766 
767     public void testSignShort() {
768         assertEquals((short)1, MathUtils.indicator((short)2));
769         assertEquals((short)(-1), MathUtils.indicator((short)(-2)));
770     }
771 
772     public void testSinh() {
773         double x = 3.0;
774         double expected = 10.01787;
775         assertEquals(expected, MathUtils.sinh(x), 1.0e-5);
776     }
777 
778     public void testSinhNaN() {
779         assertTrue(Double.isNaN(MathUtils.sinh(Double.NaN)));
780     }
781 
782     public void testSubAndCheck() {
783         int big = Integer.MAX_VALUE;
784         int bigNeg = Integer.MIN_VALUE;
785         assertEquals(big, MathUtils.subAndCheck(big, 0));
786         try {
787             MathUtils.subAndCheck(big, -1);
788             fail("Expecting ArithmeticException");
789         } catch (ArithmeticException ex) {
790         }
791         try {
792             MathUtils.subAndCheck(bigNeg, 1);
793             fail("Expecting ArithmeticException");
794         } catch (ArithmeticException ex) {
795         }
796     }
797 
798     public void testSubAndCheckErrorMessage() {
799         int big = Integer.MAX_VALUE;
800         try {
801             MathUtils.subAndCheck(big, -1);
802             fail("Expecting ArithmeticException");
803         } catch (ArithmeticException ex) {
804             assertEquals("overflow: subtract", ex.getMessage());
805         }
806     }
807 
808     public void testSubAndCheckLong() {
809         long max = Long.MAX_VALUE;
810         long min = Long.MIN_VALUE;
811         assertEquals(max, MathUtils.subAndCheck(max, 0));
812         assertEquals(min, MathUtils.subAndCheck(min, 0));
813         assertEquals(-max, MathUtils.subAndCheck(0, max));
814         testSubAndCheckLongFailure(0L, min);
815         testSubAndCheckLongFailure(max, -1L);
816         testSubAndCheckLongFailure(min, 1L);
817     }
818 
819     private void testSubAndCheckLongFailure(long a, long b) {
820         try {
821             MathUtils.subAndCheck(a, b);
822             fail("Expecting ArithmeticException");
823         } catch (ArithmeticException ex) {
824             // success
825         }
826 
827     }
828 }