001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements. See the NOTICE file distributed with this
004     * work for additional information regarding copyright ownership. The ASF
005     * licenses this file to You under the Apache License, Version 2.0 (the
006     * "License"); you may not use this file except in compliance with the License.
007     * You may obtain a copy of the License at
008     * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
009     * or agreed to in writing, software distributed under the License is
010     * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
011     * KIND, either express or implied. See the License for the specific language
012     * governing permissions and limitations under the License.
013     */
014    package org.apache.commons.math.util;
015    
016    import java.math.BigDecimal;
017    import java.math.BigInteger;
018    import java.util.ArrayList;
019    import java.util.HashMap;
020    import java.util.List;
021    import java.util.Map;
022    
023    import junit.framework.Test;
024    import junit.framework.TestCase;
025    import junit.framework.TestSuite;
026    
027    import org.apache.commons.math.random.RandomDataImpl;
028    import org.apache.commons.math.TestUtils;
029    
030    /**
031     * Test cases for the MathUtils class.
032     * @version $Revision: 790243 $ $Date: 2007-08-16 15:36:33 -0500 (Thu, 16 Aug
033     *          2007) $
034     */
035    public final class MathUtilsTest extends TestCase {
036    
037        public MathUtilsTest(String name) {
038            super(name);
039        }
040    
041        public static Test suite() {
042            TestSuite suite = new TestSuite(MathUtilsTest.class);
043            suite.setName("MathUtils Tests");
044            return suite;
045        }
046    
047        /** cached binomial coefficients */
048        private static final List<Map<Integer, Long>> binomialCache = new ArrayList<Map<Integer, Long>>();
049    
050        /**
051         * Exact (caching) recursive implementation to test against
052         */
053        private long binomialCoefficient(int n, int k) throws ArithmeticException {
054            if (binomialCache.size() > n) {
055                Long cachedResult = binomialCache.get(n).get(Integer.valueOf(k));
056                if (cachedResult != null) {
057                    return cachedResult.longValue();
058                }
059            }
060            long result = -1;
061            if ((n == k) || (k == 0)) {
062                result = 1;
063            } else if ((k == 1) || (k == n - 1)) {
064                result = n;
065            } else {
066                // Reduce stack depth for larger values of n
067                if (k < n - 100) {
068                    binomialCoefficient(n - 100, k);
069                }
070                if (k > 100) {
071                    binomialCoefficient(n - 100, k - 100);
072                }
073                result = MathUtils.addAndCheck(binomialCoefficient(n - 1, k - 1),
074                    binomialCoefficient(n - 1, k));
075            }
076            if (result == -1) {
077                throw new ArithmeticException(
078                    "error computing binomial coefficient");
079            }
080            for (int i = binomialCache.size(); i < n + 1; i++) {
081                binomialCache.add(new HashMap<Integer, Long>());
082            }
083            binomialCache.get(n).put(Integer.valueOf(k), Long.valueOf(result));
084            return result;
085        }
086    
087        /**
088         * Exact direct multiplication implementation to test against
089         */
090        private long factorial(int n) {
091            long result = 1;
092            for (int i = 2; i <= n; i++) {
093                result *= i;
094            }
095            return result;
096        }
097    
098        /** Verify that b(0,0) = 1 */
099        public void test0Choose0() {
100            assertEquals(MathUtils.binomialCoefficientDouble(0, 0), 1d, 0);
101            assertEquals(MathUtils.binomialCoefficientLog(0, 0), 0d, 0);
102            assertEquals(MathUtils.binomialCoefficient(0, 0), 1);
103        }
104    
105        public void testAddAndCheck() {
106            int big = Integer.MAX_VALUE;
107            int bigNeg = Integer.MIN_VALUE;
108            assertEquals(big, MathUtils.addAndCheck(big, 0));
109            try {
110                MathUtils.addAndCheck(big, 1);
111                fail("Expecting ArithmeticException");
112            } catch (ArithmeticException ex) {
113            }
114            try {
115                MathUtils.addAndCheck(bigNeg, -1);
116                fail("Expecting ArithmeticException");
117            } catch (ArithmeticException ex) {
118            }
119        }
120    
121        public void testAddAndCheckLong() {
122            long max = Long.MAX_VALUE;
123            long min = Long.MIN_VALUE;
124            assertEquals(max, MathUtils.addAndCheck(max, 0L));
125            assertEquals(min, MathUtils.addAndCheck(min, 0L));
126            assertEquals(max, MathUtils.addAndCheck(0L, max));
127            assertEquals(min, MathUtils.addAndCheck(0L, min));
128            assertEquals(1, MathUtils.addAndCheck(-1L, 2L));
129            assertEquals(1, MathUtils.addAndCheck(2L, -1L));
130            assertEquals(-3, MathUtils.addAndCheck(-2L, -1L));
131            assertEquals(min, MathUtils.addAndCheck(min + 1, -1L));
132            testAddAndCheckLongFailure(max, 1L);
133            testAddAndCheckLongFailure(min, -1L);
134            testAddAndCheckLongFailure(1L, max);
135            testAddAndCheckLongFailure(-1L, min);
136        }
137    
138        private void testAddAndCheckLongFailure(long a, long b) {
139            try {
140                MathUtils.addAndCheck(a, b);
141                fail("Expecting ArithmeticException");
142            } catch (ArithmeticException ex) {
143                // success
144            }
145        }
146    
147        public void testBinomialCoefficient() {
148            long[] bcoef5 = {
149                1,
150                5,
151                10,
152                10,
153                5,
154                1 };
155            long[] bcoef6 = {
156                1,
157                6,
158                15,
159                20,
160                15,
161                6,
162                1 };
163            for (int i = 0; i < 6; i++) {
164                assertEquals("5 choose " + i, bcoef5[i], MathUtils.binomialCoefficient(5, i));
165            }
166            for (int i = 0; i < 7; i++) {
167                assertEquals("6 choose " + i, bcoef6[i], MathUtils.binomialCoefficient(6, i));
168            }
169    
170            for (int n = 1; n < 10; n++) {
171                for (int k = 0; k <= n; k++) {
172                    assertEquals(n + " choose " + k, binomialCoefficient(n, k), MathUtils.binomialCoefficient(n, k));
173                    assertEquals(n + " choose " + k, binomialCoefficient(n, k), MathUtils.binomialCoefficientDouble(n, k), Double.MIN_VALUE);
174                    assertEquals(n + " choose " + k, Math.log(binomialCoefficient(n, k)), MathUtils.binomialCoefficientLog(n, k), 10E-12);
175                }
176            }
177    
178            int[] n = { 34, 66, 100, 1500, 1500 };
179            int[] k = { 17, 33, 10, 1500 - 4, 4 };
180            for (int i = 0; i < n.length; i++) {
181                long expected = binomialCoefficient(n[i], k[i]);
182                assertEquals(n[i] + " choose " + k[i], expected,
183                    MathUtils.binomialCoefficient(n[i], k[i]));
184                assertEquals(n[i] + " choose " + k[i], expected,
185                    MathUtils.binomialCoefficientDouble(n[i], k[i]), 0.0);
186                assertEquals("log(" + n[i] + " choose " + k[i] + ")", Math.log(expected),
187                    MathUtils.binomialCoefficientLog(n[i], k[i]), 0.0);
188            }
189        }
190    
191        /**
192         * Tests correctness for large n and sharpness of upper bound in API doc
193         * JIRA: MATH-241
194         */
195        public void testBinomialCoefficientLarge() throws Exception {
196            // This tests all legal and illegal values for n <= 200.
197            for (int n = 0; n <= 200; n++) {
198                for (int k = 0; k <= n; k++) {
199                    long ourResult = -1;
200                    long exactResult = -1;
201                    boolean shouldThrow = false;
202                    boolean didThrow = false;
203                    try {
204                        ourResult = MathUtils.binomialCoefficient(n, k);
205                    } catch (ArithmeticException ex) {
206                        didThrow = true;
207                    }
208                    try {
209                        exactResult = binomialCoefficient(n, k);
210                    } catch (ArithmeticException ex) {
211                        shouldThrow = true;
212                    }
213                    assertEquals(n + " choose " + k, exactResult, ourResult);
214                    assertEquals(n + " choose " + k, shouldThrow, didThrow);
215                    assertTrue(n + " choose " + k, (n > 66 || !didThrow));
216    
217                    if (!shouldThrow && exactResult > 1) {
218                        assertEquals(n + " choose " + k, 1.,
219                            MathUtils.binomialCoefficientDouble(n, k) / exactResult, 1e-10);
220                        assertEquals(n + " choose " + k, 1,
221                            MathUtils.binomialCoefficientLog(n, k) / Math.log(exactResult), 1e-10);
222                    }
223                }
224            }
225    
226            long ourResult = MathUtils.binomialCoefficient(300, 3);
227            long exactResult = binomialCoefficient(300, 3);
228            assertEquals(exactResult, ourResult);
229    
230            ourResult = MathUtils.binomialCoefficient(700, 697);
231            exactResult = binomialCoefficient(700, 697);
232            assertEquals(exactResult, ourResult);
233    
234            // This one should throw
235            try {
236                MathUtils.binomialCoefficient(700, 300);
237                fail("Expecting ArithmeticException");
238            } catch (ArithmeticException ex) {
239                // Expected
240            }
241    
242            int n = 10000;
243            ourResult = MathUtils.binomialCoefficient(n, 3);
244            exactResult = binomialCoefficient(n, 3);
245            assertEquals(exactResult, ourResult);
246            assertEquals(1, MathUtils.binomialCoefficientDouble(n, 3) / exactResult, 1e-10);
247            assertEquals(1, MathUtils.binomialCoefficientLog(n, 3) / Math.log(exactResult), 1e-10);
248    
249        }
250    
251        public void testBinomialCoefficientFail() {
252            try {
253                MathUtils.binomialCoefficient(4, 5);
254                fail("expecting IllegalArgumentException");
255            } catch (IllegalArgumentException ex) {
256                // ignored
257            }
258    
259            try {
260                MathUtils.binomialCoefficientDouble(4, 5);
261                fail("expecting IllegalArgumentException");
262            } catch (IllegalArgumentException ex) {
263                // ignored
264            }
265    
266            try {
267                MathUtils.binomialCoefficientLog(4, 5);
268                fail("expecting IllegalArgumentException");
269            } catch (IllegalArgumentException ex) {
270                // ignored
271            }
272    
273            try {
274                MathUtils.binomialCoefficient(-1, -2);
275                fail("expecting IllegalArgumentException");
276            } catch (IllegalArgumentException ex) {
277                // ignored
278            }
279            try {
280                MathUtils.binomialCoefficientDouble(-1, -2);
281                fail("expecting IllegalArgumentException");
282            } catch (IllegalArgumentException ex) {
283                // ignored
284            }
285            try {
286                MathUtils.binomialCoefficientLog(-1, -2);
287                fail("expecting IllegalArgumentException");
288            } catch (IllegalArgumentException ex) {
289                // ignored
290            }
291    
292            try {
293                MathUtils.binomialCoefficient(67, 30);
294                fail("expecting ArithmeticException");
295            } catch (ArithmeticException ex) {
296                // ignored
297            }
298            try {
299                MathUtils.binomialCoefficient(67, 34);
300                fail("expecting ArithmeticException");
301            } catch (ArithmeticException ex) {
302                // ignored
303            }
304            double x = MathUtils.binomialCoefficientDouble(1030, 515);
305            assertTrue("expecting infinite binomial coefficient", Double
306                .isInfinite(x));
307        }
308    
309        public void testCompareTo() {
310          assertEquals(0, MathUtils.compareTo(152.33, 152.32, .011));
311          assertTrue(MathUtils.compareTo(152.308, 152.32, .011) < 0);
312          assertTrue(MathUtils.compareTo(152.33, 152.318, .011) > 0);
313        }
314        
315        public void testCosh() {
316            double x = 3.0;
317            double expected = 10.06766;
318            assertEquals(expected, MathUtils.cosh(x), 1.0e-5);
319        }
320    
321        public void testCoshNaN() {
322            assertTrue(Double.isNaN(MathUtils.cosh(Double.NaN)));
323        }
324    
325        public void testEquals() {
326            double[] testArray = {
327                Double.NaN,
328                Double.POSITIVE_INFINITY,
329                Double.NEGATIVE_INFINITY,
330                1d,
331                0d };
332            for (int i = 0; i < testArray.length; i++) {
333                for (int j = 0; j < testArray.length; j++) {
334                    if (i == j) {
335                        assertTrue(MathUtils.equals(testArray[i], testArray[j]));
336                        assertTrue(MathUtils.equals(testArray[j], testArray[i]));
337                    } else {
338                        assertTrue(!MathUtils.equals(testArray[i], testArray[j]));
339                        assertTrue(!MathUtils.equals(testArray[j], testArray[i]));
340                    }
341                }
342            }
343        }
344    
345        public void testEqualsWithAllowedDelta() {
346            assertTrue(MathUtils.equals(153.0000, 153.0000, .0625));
347            assertTrue(MathUtils.equals(153.0000, 153.0625, .0625));
348            assertTrue(MathUtils.equals(152.9375, 153.0000, .0625));
349            assertTrue(MathUtils.equals(Double.NaN, Double.NaN, 1.0));
350            assertTrue(MathUtils.equals(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0));
351            assertTrue(MathUtils.equals(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1.0));
352            assertFalse(MathUtils.equals(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0));
353            assertFalse(MathUtils.equals(153.0000, 153.0625, .0624));
354            assertFalse(MathUtils.equals(152.9374, 153.0000, .0625));
355        }
356    
357        public void testEqualsWithAllowedUlps() {
358            assertTrue(MathUtils.equals(153, 153, 1));
359    
360            assertTrue(MathUtils.equals(153, 153.00000000000003, 1));
361            assertFalse(MathUtils.equals(153, 153.00000000000006, 1));
362            assertTrue(MathUtils.equals(153, 152.99999999999997, 1));
363            assertFalse(MathUtils.equals(153, 152.99999999999994, 1));
364            
365            assertTrue(MathUtils.equals(-128, -127.99999999999999, 1));
366            assertFalse(MathUtils.equals(-128, -127.99999999999997, 1));
367            assertTrue(MathUtils.equals(-128, -128.00000000000003, 1));
368            assertFalse(MathUtils.equals(-128, -128.00000000000006, 1));
369    
370            assertTrue(MathUtils.equals(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1));
371            assertTrue(MathUtils.equals(Double.MAX_VALUE, Double.POSITIVE_INFINITY, 1));
372    
373            assertTrue(MathUtils.equals(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1));
374            assertTrue(MathUtils.equals(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY, 1));
375    
376    
377            assertTrue(MathUtils.equals(Double.NaN, Double.NaN, 1));
378    
379            assertFalse(MathUtils.equals(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 100000));
380        }
381        
382        public void testArrayEquals() {
383            assertFalse(MathUtils.equals(new double[] { 1d }, null));
384            assertFalse(MathUtils.equals(null, new double[] { 1d }));
385            assertTrue(MathUtils.equals((double[]) null, (double[]) null));
386    
387            assertFalse(MathUtils.equals(new double[] { 1d }, new double[0]));
388            assertTrue(MathUtils.equals(new double[] { 1d }, new double[] { 1d }));
389            assertTrue(MathUtils.equals(new double[] {
390                                          Double.NaN, Double.POSITIVE_INFINITY,
391                                          Double.NEGATIVE_INFINITY, 1d, 0d
392                                        }, new double[] {
393                                          Double.NaN, Double.POSITIVE_INFINITY,
394                                          Double.NEGATIVE_INFINITY, 1d, 0d
395                                        }));
396            assertFalse(MathUtils.equals(new double[] { Double.POSITIVE_INFINITY },
397                                         new double[] { Double.NEGATIVE_INFINITY }));
398            assertFalse(MathUtils.equals(new double[] { 1d },
399                                         new double[] { MathUtils.nextAfter(1d, 2d) }));
400    
401        }
402    
403        public void testFactorial() {
404            for (int i = 1; i < 21; i++) {
405                assertEquals(i + "! ", factorial(i), MathUtils.factorial(i));
406                assertEquals(i + "! ", factorial(i), MathUtils.factorialDouble(i), Double.MIN_VALUE);
407                assertEquals(i + "! ", Math.log(factorial(i)), MathUtils.factorialLog(i), 10E-12);
408            }
409            
410            assertEquals("0", 1, MathUtils.factorial(0));
411            assertEquals("0", 1.0d, MathUtils.factorialDouble(0), 1E-14);
412            assertEquals("0", 0.0d, MathUtils.factorialLog(0), 1E-14);
413        }
414    
415        public void testFactorialFail() {
416            try {
417                MathUtils.factorial(-1);
418                fail("expecting IllegalArgumentException");
419            } catch (IllegalArgumentException ex) {
420                // ignored
421            }
422            try {
423                MathUtils.factorialDouble(-1);
424                fail("expecting IllegalArgumentException");
425            } catch (IllegalArgumentException ex) {
426                // ignored
427            }
428            try {
429                MathUtils.factorialLog(-1);
430                fail("expecting IllegalArgumentException");
431            } catch (IllegalArgumentException ex) {
432                // ignored
433            }
434            try {
435                MathUtils.factorial(21);
436                fail("expecting ArithmeticException");
437            } catch (ArithmeticException ex) {
438                // ignored
439            }
440            assertTrue("expecting infinite factorial value", Double.isInfinite(MathUtils.factorialDouble(171)));
441        }
442    
443        public void testGcd() {
444            int a = 30;
445            int b = 50;
446            int c = 77;
447    
448            assertEquals(0, MathUtils.gcd(0, 0));
449    
450            assertEquals(b, MathUtils.gcd(0, b));
451            assertEquals(a, MathUtils.gcd(a, 0));
452            assertEquals(b, MathUtils.gcd(0, -b));
453            assertEquals(a, MathUtils.gcd(-a, 0));
454    
455            assertEquals(10, MathUtils.gcd(a, b));
456            assertEquals(10, MathUtils.gcd(-a, b));
457            assertEquals(10, MathUtils.gcd(a, -b));
458            assertEquals(10, MathUtils.gcd(-a, -b));
459    
460            assertEquals(1, MathUtils.gcd(a, c));
461            assertEquals(1, MathUtils.gcd(-a, c));
462            assertEquals(1, MathUtils.gcd(a, -c));
463            assertEquals(1, MathUtils.gcd(-a, -c));
464    
465            assertEquals(3 * (1<<15), MathUtils.gcd(3 * (1<<20), 9 * (1<<15)));
466    
467            assertEquals(Integer.MAX_VALUE, MathUtils.gcd(Integer.MAX_VALUE, 0));
468            assertEquals(Integer.MAX_VALUE, MathUtils.gcd(-Integer.MAX_VALUE, 0));
469            assertEquals(1<<30, MathUtils.gcd(1<<30, -Integer.MIN_VALUE));
470            try {
471                // gcd(Integer.MIN_VALUE, 0) > Integer.MAX_VALUE
472                MathUtils.gcd(Integer.MIN_VALUE, 0);
473                fail("expecting ArithmeticException");
474            } catch (ArithmeticException expected) {
475                // expected
476            }
477            try {
478                // gcd(0, Integer.MIN_VALUE) > Integer.MAX_VALUE
479                MathUtils.gcd(0, Integer.MIN_VALUE);
480                fail("expecting ArithmeticException");
481            } catch (ArithmeticException expected) {
482                // expected
483            }
484            try {
485                // gcd(Integer.MIN_VALUE, Integer.MIN_VALUE) > Integer.MAX_VALUE
486                MathUtils.gcd(Integer.MIN_VALUE, Integer.MIN_VALUE);
487                fail("expecting ArithmeticException");
488            } catch (ArithmeticException expected) {
489                // expected
490            }
491        }
492    
493        public void testHash() {
494            double[] testArray = {
495                Double.NaN,
496                Double.POSITIVE_INFINITY,
497                Double.NEGATIVE_INFINITY,
498                1d,
499                0d,
500                1E-14,
501                (1 + 1E-14),
502                Double.MIN_VALUE,
503                Double.MAX_VALUE };
504            for (int i = 0; i < testArray.length; i++) {
505                for (int j = 0; j < testArray.length; j++) {
506                    if (i == j) {
507                        assertEquals(MathUtils.hash(testArray[i]), MathUtils.hash(testArray[j]));
508                        assertEquals(MathUtils.hash(testArray[j]), MathUtils.hash(testArray[i]));
509                    } else {
510                        assertTrue(MathUtils.hash(testArray[i]) != MathUtils.hash(testArray[j]));
511                        assertTrue(MathUtils.hash(testArray[j]) != MathUtils.hash(testArray[i]));
512                    }
513                }
514            }
515        }
516    
517        public void testArrayHash() {
518            assertEquals(0, MathUtils.hash((double[]) null));
519            assertEquals(MathUtils.hash(new double[] {
520                                          Double.NaN, Double.POSITIVE_INFINITY,
521                                          Double.NEGATIVE_INFINITY, 1d, 0d
522                                        }),
523                         MathUtils.hash(new double[] {
524                                          Double.NaN, Double.POSITIVE_INFINITY,
525                                          Double.NEGATIVE_INFINITY, 1d, 0d
526                                        }));
527            assertFalse(MathUtils.hash(new double[] { 1d }) ==
528                        MathUtils.hash(new double[] { MathUtils.nextAfter(1d, 2d) }));
529            assertFalse(MathUtils.hash(new double[] { 1d }) ==
530                        MathUtils.hash(new double[] { 1d, 1d }));
531        }
532        
533        /**
534         * Make sure that permuted arrays do not hash to the same value.
535         */
536        public void testPermutedArrayHash() {
537            double[] original = new double[10];
538            double[] permuted = new double[10];
539            RandomDataImpl random = new RandomDataImpl();
540            
541            // Generate 10 distinct random values
542            for (int i = 0; i < 10; i++) {
543                original[i] = random.nextUniform(i + 0.5, i + 0.75);
544            }
545            
546            // Generate a random permutation, making sure it is not the identity
547            boolean isIdentity = true;
548            do {
549                int[] permutation = random.nextPermutation(10, 10);
550                for (int i = 0; i < 10; i++) {
551                    if (i != permutation[i]) {
552                        isIdentity = false;
553                    }
554                    permuted[i] = original[permutation[i]];
555                }
556            } while (isIdentity);
557            
558            // Verify that permuted array has different hash
559            assertFalse(MathUtils.hash(original) == MathUtils.hash(permuted));
560        }
561    
562        public void testIndicatorByte() {
563            assertEquals((byte)1, MathUtils.indicator((byte)2));
564            assertEquals((byte)1, MathUtils.indicator((byte)0));
565            assertEquals((byte)(-1), MathUtils.indicator((byte)(-2)));
566        }
567    
568        public void testIndicatorDouble() {
569            double delta = 0.0;
570            assertEquals(1.0, MathUtils.indicator(2.0), delta);
571            assertEquals(1.0, MathUtils.indicator(0.0), delta);
572            assertEquals(-1.0, MathUtils.indicator(-2.0), delta);
573            assertEquals(Double.NaN, MathUtils.indicator(Double.NaN));
574        }
575    
576        public void testIndicatorFloat() {
577            float delta = 0.0F;
578            assertEquals(1.0F, MathUtils.indicator(2.0F), delta);
579            assertEquals(1.0F, MathUtils.indicator(0.0F), delta);
580            assertEquals(-1.0F, MathUtils.indicator(-2.0F), delta);
581        }
582    
583        public void testIndicatorInt() {
584            assertEquals(1, MathUtils.indicator((2)));
585            assertEquals(1, MathUtils.indicator((0)));
586            assertEquals((-1), MathUtils.indicator((-2)));
587        }
588    
589        public void testIndicatorLong() {
590            assertEquals(1L, MathUtils.indicator(2L));
591            assertEquals(1L, MathUtils.indicator(0L));
592            assertEquals(-1L, MathUtils.indicator(-2L));
593        }
594    
595        public void testIndicatorShort() {
596            assertEquals((short)1, MathUtils.indicator((short)2));
597            assertEquals((short)1, MathUtils.indicator((short)0));
598            assertEquals((short)(-1), MathUtils.indicator((short)(-2)));
599        }
600    
601        public void testLcm() {
602            int a = 30;
603            int b = 50;
604            int c = 77;
605    
606            assertEquals(0, MathUtils.lcm(0, b));
607            assertEquals(0, MathUtils.lcm(a, 0));
608            assertEquals(b, MathUtils.lcm(1, b));
609            assertEquals(a, MathUtils.lcm(a, 1));
610            assertEquals(150, MathUtils.lcm(a, b));
611            assertEquals(150, MathUtils.lcm(-a, b));
612            assertEquals(150, MathUtils.lcm(a, -b));
613            assertEquals(150, MathUtils.lcm(-a, -b));
614            assertEquals(2310, MathUtils.lcm(a, c));
615    
616            // Assert that no intermediate value overflows:
617            // The naive implementation of lcm(a,b) would be (a*b)/gcd(a,b)
618            assertEquals((1<<20)*15, MathUtils.lcm((1<<20)*3, (1<<20)*5));
619    
620            // Special case
621            assertEquals(0, MathUtils.lcm(0, 0));
622    
623            try {
624                // lcm == abs(MIN_VALUE) cannot be represented as a nonnegative int
625                MathUtils.lcm(Integer.MIN_VALUE, 1);
626                fail("Expecting ArithmeticException");
627            } catch (ArithmeticException ex) {
628                // expected
629            }
630            
631            try {
632                // lcm == abs(MIN_VALUE) cannot be represented as a nonnegative int
633                MathUtils.lcm(Integer.MIN_VALUE, 1<<20);
634                fail("Expecting ArithmeticException");
635            } catch (ArithmeticException ex) {
636                // expected
637            }
638    
639            try {
640                MathUtils.lcm(Integer.MAX_VALUE, Integer.MAX_VALUE - 1);
641                fail("Expecting ArithmeticException");
642            } catch (ArithmeticException ex) {
643                // expected
644            }
645        }
646    
647        public void testLog() {
648            assertEquals(2.0, MathUtils.log(2, 4), 0);
649            assertEquals(3.0, MathUtils.log(2, 8), 0);
650            assertTrue(Double.isNaN(MathUtils.log(-1, 1)));
651            assertTrue(Double.isNaN(MathUtils.log(1, -1)));
652            assertTrue(Double.isNaN(MathUtils.log(0, 0)));
653            assertEquals(0, MathUtils.log(0, 10), 0);
654            assertEquals(Double.NEGATIVE_INFINITY, MathUtils.log(10, 0), 0);
655        }
656    
657        public void testMulAndCheck() {
658            int big = Integer.MAX_VALUE;
659            int bigNeg = Integer.MIN_VALUE;
660            assertEquals(big, MathUtils.mulAndCheck(big, 1));
661            try {
662                MathUtils.mulAndCheck(big, 2);
663                fail("Expecting ArithmeticException");
664            } catch (ArithmeticException ex) {
665            }
666            try {
667                MathUtils.mulAndCheck(bigNeg, 2);
668                fail("Expecting ArithmeticException");
669            } catch (ArithmeticException ex) {
670            }
671        }
672    
673        public void testMulAndCheckLong() {
674            long max = Long.MAX_VALUE;
675            long min = Long.MIN_VALUE;
676            assertEquals(max, MathUtils.mulAndCheck(max, 1L));
677            assertEquals(min, MathUtils.mulAndCheck(min, 1L));
678            assertEquals(0L, MathUtils.mulAndCheck(max, 0L));
679            assertEquals(0L, MathUtils.mulAndCheck(min, 0L));
680            assertEquals(max, MathUtils.mulAndCheck(1L, max));
681            assertEquals(min, MathUtils.mulAndCheck(1L, min));
682            assertEquals(0L, MathUtils.mulAndCheck(0L, max));
683            assertEquals(0L, MathUtils.mulAndCheck(0L, min));
684            assertEquals(1L, MathUtils.mulAndCheck(-1L, -1L));
685            assertEquals(min, MathUtils.mulAndCheck(min / 2, 2));
686            testMulAndCheckLongFailure(max, 2L);
687            testMulAndCheckLongFailure(2L, max);
688            testMulAndCheckLongFailure(min, 2L);
689            testMulAndCheckLongFailure(2L, min);
690            testMulAndCheckLongFailure(min, -1L);
691            testMulAndCheckLongFailure(-1L, min);
692        }
693    
694        private void testMulAndCheckLongFailure(long a, long b) {
695            try {
696                MathUtils.mulAndCheck(a, b);
697                fail("Expecting ArithmeticException");
698            } catch (ArithmeticException ex) {
699                // success
700            }
701        }
702    
703        public void testNextAfter() {
704            // 0x402fffffffffffff 0x404123456789abcd -> 4030000000000000
705            assertEquals(16.0, MathUtils.nextAfter(15.999999999999998, 34.27555555555555), 0.0);
706    
707            // 0xc02fffffffffffff 0x404123456789abcd -> c02ffffffffffffe
708            assertEquals(-15.999999999999996, MathUtils.nextAfter(-15.999999999999998, 34.27555555555555), 0.0);
709    
710            // 0x402fffffffffffff 0x400123456789abcd -> 402ffffffffffffe
711            assertEquals(15.999999999999996, MathUtils.nextAfter(15.999999999999998, 2.142222222222222), 0.0);
712    
713            // 0xc02fffffffffffff 0x400123456789abcd -> c02ffffffffffffe
714            assertEquals(-15.999999999999996, MathUtils.nextAfter(-15.999999999999998, 2.142222222222222), 0.0);
715    
716            // 0x4020000000000000 0x404123456789abcd -> 4020000000000001
717            assertEquals(8.000000000000002, MathUtils.nextAfter(8.0, 34.27555555555555), 0.0);
718    
719            // 0xc020000000000000 0x404123456789abcd -> c01fffffffffffff
720            assertEquals(-7.999999999999999, MathUtils.nextAfter(-8.0, 34.27555555555555), 0.0);
721    
722            // 0x4020000000000000 0x400123456789abcd -> 401fffffffffffff
723            assertEquals(7.999999999999999, MathUtils.nextAfter(8.0, 2.142222222222222), 0.0);
724    
725            // 0xc020000000000000 0x400123456789abcd -> c01fffffffffffff
726            assertEquals(-7.999999999999999, MathUtils.nextAfter(-8.0, 2.142222222222222), 0.0);
727    
728            // 0x3f2e43753d36a223 0x3f2e43753d36a224 -> 3f2e43753d36a224
729            assertEquals(2.308922399667661E-4, MathUtils.nextAfter(2.3089223996676606E-4, 2.308922399667661E-4), 0.0);
730    
731            // 0x3f2e43753d36a223 0x3f2e43753d36a223 -> 3f2e43753d36a224
732            assertEquals(2.308922399667661E-4, MathUtils.nextAfter(2.3089223996676606E-4, 2.3089223996676606E-4), 0.0);
733    
734            // 0x3f2e43753d36a223 0x3f2e43753d36a222 -> 3f2e43753d36a222
735            assertEquals(2.3089223996676603E-4, MathUtils.nextAfter(2.3089223996676606E-4, 2.3089223996676603E-4), 0.0);
736    
737            // 0x3f2e43753d36a223 0xbf2e43753d36a224 -> 3f2e43753d36a222
738            assertEquals(2.3089223996676603E-4, MathUtils.nextAfter(2.3089223996676606E-4, -2.308922399667661E-4), 0.0);
739    
740            // 0x3f2e43753d36a223 0xbf2e43753d36a223 -> 3f2e43753d36a222
741            assertEquals(2.3089223996676603E-4, MathUtils.nextAfter(2.3089223996676606E-4, -2.3089223996676606E-4), 0.0);
742    
743            // 0x3f2e43753d36a223 0xbf2e43753d36a222 -> 3f2e43753d36a222
744            assertEquals(2.3089223996676603E-4, MathUtils.nextAfter(2.3089223996676606E-4, -2.3089223996676603E-4), 0.0);
745    
746            // 0xbf2e43753d36a223 0x3f2e43753d36a224 -> bf2e43753d36a222
747            assertEquals(-2.3089223996676603E-4, MathUtils.nextAfter(-2.3089223996676606E-4, 2.308922399667661E-4), 0.0);
748    
749            // 0xbf2e43753d36a223 0x3f2e43753d36a223 -> bf2e43753d36a222
750            assertEquals(-2.3089223996676603E-4, MathUtils.nextAfter(-2.3089223996676606E-4, 2.3089223996676606E-4), 0.0);
751    
752            // 0xbf2e43753d36a223 0x3f2e43753d36a222 -> bf2e43753d36a222
753            assertEquals(-2.3089223996676603E-4, MathUtils.nextAfter(-2.3089223996676606E-4, 2.3089223996676603E-4), 0.0);
754    
755            // 0xbf2e43753d36a223 0xbf2e43753d36a224 -> bf2e43753d36a224
756            assertEquals(-2.308922399667661E-4, MathUtils.nextAfter(-2.3089223996676606E-4, -2.308922399667661E-4), 0.0);
757    
758            // 0xbf2e43753d36a223 0xbf2e43753d36a223 -> bf2e43753d36a224
759            assertEquals(-2.308922399667661E-4, MathUtils.nextAfter(-2.3089223996676606E-4, -2.3089223996676606E-4), 0.0);
760    
761            // 0xbf2e43753d36a223 0xbf2e43753d36a222 -> bf2e43753d36a222
762            assertEquals(-2.3089223996676603E-4, MathUtils.nextAfter(-2.3089223996676606E-4, -2.3089223996676603E-4), 0.0);
763    
764        }
765    
766        public void testNextAfterSpecialCases() {
767            assertTrue(Double.isInfinite(MathUtils.nextAfter(Double.NEGATIVE_INFINITY, 0)));
768            assertTrue(Double.isInfinite(MathUtils.nextAfter(Double.POSITIVE_INFINITY, 0)));
769            assertTrue(Double.isNaN(MathUtils.nextAfter(Double.NaN, 0)));
770            assertTrue(Double.isInfinite(MathUtils.nextAfter(Double.MAX_VALUE, Double.POSITIVE_INFINITY)));
771            assertTrue(Double.isInfinite(MathUtils.nextAfter(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY)));
772            assertEquals(Double.MIN_VALUE, MathUtils.nextAfter(0, 1), 0);
773            assertEquals(-Double.MIN_VALUE, MathUtils.nextAfter(0, -1), 0);
774            assertEquals(0, MathUtils.nextAfter(Double.MIN_VALUE, -1), 0);
775            assertEquals(0, MathUtils.nextAfter(-Double.MIN_VALUE, 1), 0);
776        }
777    
778        public void testScalb() {
779            assertEquals( 0.0, MathUtils.scalb(0.0, 5), 1.0e-15);
780            assertEquals(32.0, MathUtils.scalb(1.0, 5), 1.0e-15);
781            assertEquals(1.0 / 32.0, MathUtils.scalb(1.0,  -5), 1.0e-15);
782            assertEquals(Math.PI, MathUtils.scalb(Math.PI, 0), 1.0e-15);
783            assertTrue(Double.isInfinite(MathUtils.scalb(Double.POSITIVE_INFINITY, 1)));
784            assertTrue(Double.isInfinite(MathUtils.scalb(Double.NEGATIVE_INFINITY, 1)));
785            assertTrue(Double.isNaN(MathUtils.scalb(Double.NaN, 1)));
786        }
787    
788        public void testNormalizeAngle() {
789            for (double a = -15.0; a <= 15.0; a += 0.1) {
790                for (double b = -15.0; b <= 15.0; b += 0.2) {
791                    double c = MathUtils.normalizeAngle(a, b);
792                    assertTrue((b - Math.PI) <= c);
793                    assertTrue(c <= (b + Math.PI));
794                    double twoK = Math.rint((a - c) / Math.PI);
795                    assertEquals(c, a - twoK * Math.PI, 1.0e-14);
796                }
797            }
798        }
799    
800        public void testRoundDouble() {
801            double x = 1.234567890;
802            assertEquals(1.23, MathUtils.round(x, 2), 0.0);
803            assertEquals(1.235, MathUtils.round(x, 3), 0.0);
804            assertEquals(1.2346, MathUtils.round(x, 4), 0.0);
805    
806            // JIRA MATH-151
807            assertEquals(39.25, MathUtils.round(39.245, 2), 0.0);
808            assertEquals(39.24, MathUtils.round(39.245, 2, BigDecimal.ROUND_DOWN), 0.0);
809            double xx = 39.0;
810            xx = xx + 245d / 1000d;
811            assertEquals(39.25, MathUtils.round(xx, 2), 0.0);
812    
813            // BZ 35904
814            assertEquals(30.1d, MathUtils.round(30.095d, 2), 0.0d);
815            assertEquals(30.1d, MathUtils.round(30.095d, 1), 0.0d);
816            assertEquals(33.1d, MathUtils.round(33.095d, 1), 0.0d);
817            assertEquals(33.1d, MathUtils.round(33.095d, 2), 0.0d);
818            assertEquals(50.09d, MathUtils.round(50.085d, 2), 0.0d);
819            assertEquals(50.19d, MathUtils.round(50.185d, 2), 0.0d);
820            assertEquals(50.01d, MathUtils.round(50.005d, 2), 0.0d);
821            assertEquals(30.01d, MathUtils.round(30.005d, 2), 0.0d);
822            assertEquals(30.65d, MathUtils.round(30.645d, 2), 0.0d);
823    
824            assertEquals(1.24, MathUtils.round(x, 2, BigDecimal.ROUND_CEILING), 0.0);
825            assertEquals(1.235, MathUtils.round(x, 3, BigDecimal.ROUND_CEILING), 0.0);
826            assertEquals(1.2346, MathUtils.round(x, 4, BigDecimal.ROUND_CEILING), 0.0);
827            assertEquals(-1.23, MathUtils.round(-x, 2, BigDecimal.ROUND_CEILING), 0.0);
828            assertEquals(-1.234, MathUtils.round(-x, 3, BigDecimal.ROUND_CEILING), 0.0);
829            assertEquals(-1.2345, MathUtils.round(-x, 4, BigDecimal.ROUND_CEILING), 0.0);
830    
831            assertEquals(1.23, MathUtils.round(x, 2, BigDecimal.ROUND_DOWN), 0.0);
832            assertEquals(1.234, MathUtils.round(x, 3, BigDecimal.ROUND_DOWN), 0.0);
833            assertEquals(1.2345, MathUtils.round(x, 4, BigDecimal.ROUND_DOWN), 0.0);
834            assertEquals(-1.23, MathUtils.round(-x, 2, BigDecimal.ROUND_DOWN), 0.0);
835            assertEquals(-1.234, MathUtils.round(-x, 3, BigDecimal.ROUND_DOWN), 0.0);
836            assertEquals(-1.2345, MathUtils.round(-x, 4, BigDecimal.ROUND_DOWN), 0.0);
837    
838            assertEquals(1.23, MathUtils.round(x, 2, BigDecimal.ROUND_FLOOR), 0.0);
839            assertEquals(1.234, MathUtils.round(x, 3, BigDecimal.ROUND_FLOOR), 0.0);
840            assertEquals(1.2345, MathUtils.round(x, 4, BigDecimal.ROUND_FLOOR), 0.0);
841            assertEquals(-1.24, MathUtils.round(-x, 2, BigDecimal.ROUND_FLOOR), 0.0);
842            assertEquals(-1.235, MathUtils.round(-x, 3, BigDecimal.ROUND_FLOOR), 0.0);
843            assertEquals(-1.2346, MathUtils.round(-x, 4, BigDecimal.ROUND_FLOOR), 0.0);
844    
845            assertEquals(1.23, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_DOWN), 0.0);
846            assertEquals(1.235, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
847            assertEquals(1.2346, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_DOWN), 0.0);
848            assertEquals(-1.23, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_DOWN), 0.0);
849            assertEquals(-1.235, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
850            assertEquals(-1.2346, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_DOWN), 0.0);
851            assertEquals(1.234, MathUtils.round(1.2345, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
852            assertEquals(-1.234, MathUtils.round(-1.2345, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
853    
854            assertEquals(1.23, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_EVEN), 0.0);
855            assertEquals(1.235, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
856            assertEquals(1.2346, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_EVEN), 0.0);
857            assertEquals(-1.23, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_EVEN), 0.0);
858            assertEquals(-1.235, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
859            assertEquals(-1.2346, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_EVEN), 0.0);
860            assertEquals(1.234, MathUtils.round(1.2345, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
861            assertEquals(-1.234, MathUtils.round(-1.2345, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
862            assertEquals(1.236, MathUtils.round(1.2355, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
863            assertEquals(-1.236, MathUtils.round(-1.2355, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
864    
865            assertEquals(1.23, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_UP), 0.0);
866            assertEquals(1.235, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_UP), 0.0);
867            assertEquals(1.2346, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_UP), 0.0);
868            assertEquals(-1.23, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_UP), 0.0);
869            assertEquals(-1.235, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_UP), 0.0);
870            assertEquals(-1.2346, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_UP), 0.0);
871            assertEquals(1.235, MathUtils.round(1.2345, 3, BigDecimal.ROUND_HALF_UP), 0.0);
872            assertEquals(-1.235, MathUtils.round(-1.2345, 3, BigDecimal.ROUND_HALF_UP), 0.0);
873    
874            assertEquals(-1.23, MathUtils.round(-1.23, 2, BigDecimal.ROUND_UNNECESSARY), 0.0);
875            assertEquals(1.23, MathUtils.round(1.23, 2, BigDecimal.ROUND_UNNECESSARY), 0.0);
876    
877            try {
878                MathUtils.round(1.234, 2, BigDecimal.ROUND_UNNECESSARY);
879                fail();
880            } catch (ArithmeticException ex) {
881                // success
882            }
883    
884            assertEquals(1.24, MathUtils.round(x, 2, BigDecimal.ROUND_UP), 0.0);
885            assertEquals(1.235, MathUtils.round(x, 3, BigDecimal.ROUND_UP), 0.0);
886            assertEquals(1.2346, MathUtils.round(x, 4, BigDecimal.ROUND_UP), 0.0);
887            assertEquals(-1.24, MathUtils.round(-x, 2, BigDecimal.ROUND_UP), 0.0);
888            assertEquals(-1.235, MathUtils.round(-x, 3, BigDecimal.ROUND_UP), 0.0);
889            assertEquals(-1.2346, MathUtils.round(-x, 4, BigDecimal.ROUND_UP), 0.0);
890    
891            try {
892                MathUtils.round(1.234, 2, 1923);
893                fail();
894            } catch (IllegalArgumentException ex) {
895                // success
896            }
897    
898            // MATH-151
899            assertEquals(39.25, MathUtils.round(39.245, 2, BigDecimal.ROUND_HALF_UP), 0.0);
900    
901            // special values
902            TestUtils.assertEquals(Double.NaN, MathUtils.round(Double.NaN, 2), 0.0);
903            assertEquals(0.0, MathUtils.round(0.0, 2), 0.0);
904            assertEquals(Double.POSITIVE_INFINITY, MathUtils.round(Double.POSITIVE_INFINITY, 2), 0.0);
905            assertEquals(Double.NEGATIVE_INFINITY, MathUtils.round(Double.NEGATIVE_INFINITY, 2), 0.0);
906        }
907    
908        public void testRoundFloat() {
909            float x = 1.234567890f;
910            assertEquals(1.23f, MathUtils.round(x, 2), 0.0);
911            assertEquals(1.235f, MathUtils.round(x, 3), 0.0);
912            assertEquals(1.2346f, MathUtils.round(x, 4), 0.0);
913    
914            // BZ 35904
915            assertEquals(30.1f, MathUtils.round(30.095f, 2), 0.0f);
916            assertEquals(30.1f, MathUtils.round(30.095f, 1), 0.0f);
917            assertEquals(50.09f, MathUtils.round(50.085f, 2), 0.0f);
918            assertEquals(50.19f, MathUtils.round(50.185f, 2), 0.0f);
919            assertEquals(50.01f, MathUtils.round(50.005f, 2), 0.0f);
920            assertEquals(30.01f, MathUtils.round(30.005f, 2), 0.0f);
921            assertEquals(30.65f, MathUtils.round(30.645f, 2), 0.0f);
922    
923            assertEquals(1.24f, MathUtils.round(x, 2, BigDecimal.ROUND_CEILING), 0.0);
924            assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_CEILING), 0.0);
925            assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_CEILING), 0.0);
926            assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_CEILING), 0.0);
927            assertEquals(-1.234f, MathUtils.round(-x, 3, BigDecimal.ROUND_CEILING), 0.0);
928            assertEquals(-1.2345f, MathUtils.round(-x, 4, BigDecimal.ROUND_CEILING), 0.0);
929    
930            assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_DOWN), 0.0);
931            assertEquals(1.234f, MathUtils.round(x, 3, BigDecimal.ROUND_DOWN), 0.0);
932            assertEquals(1.2345f, MathUtils.round(x, 4, BigDecimal.ROUND_DOWN), 0.0);
933            assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_DOWN), 0.0);
934            assertEquals(-1.234f, MathUtils.round(-x, 3, BigDecimal.ROUND_DOWN), 0.0);
935            assertEquals(-1.2345f, MathUtils.round(-x, 4, BigDecimal.ROUND_DOWN), 0.0);
936    
937            assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_FLOOR), 0.0);
938            assertEquals(1.234f, MathUtils.round(x, 3, BigDecimal.ROUND_FLOOR), 0.0);
939            assertEquals(1.2345f, MathUtils.round(x, 4, BigDecimal.ROUND_FLOOR), 0.0);
940            assertEquals(-1.24f, MathUtils.round(-x, 2, BigDecimal.ROUND_FLOOR), 0.0);
941            assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_FLOOR), 0.0);
942            assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_FLOOR), 0.0);
943    
944            assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_DOWN), 0.0);
945            assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
946            assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_DOWN), 0.0);
947            assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_DOWN), 0.0);
948            assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
949            assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_DOWN), 0.0);
950            assertEquals(1.234f, MathUtils.round(1.2345f, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
951            assertEquals(-1.234f, MathUtils.round(-1.2345f, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
952    
953            assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_EVEN), 0.0);
954            assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
955            assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_EVEN), 0.0);
956            assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_EVEN), 0.0);
957            assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
958            assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_EVEN), 0.0);
959            assertEquals(1.234f, MathUtils.round(1.2345f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
960            assertEquals(-1.234f, MathUtils.round(-1.2345f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
961            assertEquals(1.236f, MathUtils.round(1.2355f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
962            assertEquals(-1.236f, MathUtils.round(-1.2355f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
963    
964            assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_UP), 0.0);
965            assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_UP), 0.0);
966            assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_UP), 0.0);
967            assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_UP), 0.0);
968            assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_UP), 0.0);
969            assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_UP), 0.0);
970            assertEquals(1.235f, MathUtils.round(1.2345f, 3, BigDecimal.ROUND_HALF_UP), 0.0);
971            assertEquals(-1.235f, MathUtils.round(-1.2345f, 3, BigDecimal.ROUND_HALF_UP), 0.0);
972    
973            assertEquals(-1.23f, MathUtils.round(-1.23f, 2, BigDecimal.ROUND_UNNECESSARY), 0.0);
974            assertEquals(1.23f, MathUtils.round(1.23f, 2, BigDecimal.ROUND_UNNECESSARY), 0.0);
975    
976            try {
977                MathUtils.round(1.234f, 2, BigDecimal.ROUND_UNNECESSARY);
978                fail();
979            } catch (ArithmeticException ex) {
980                // success
981            }
982    
983            assertEquals(1.24f, MathUtils.round(x, 2, BigDecimal.ROUND_UP), 0.0);
984            assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_UP), 0.0);
985            assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_UP), 0.0);
986            assertEquals(-1.24f, MathUtils.round(-x, 2, BigDecimal.ROUND_UP), 0.0);
987            assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_UP), 0.0);
988            assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_UP), 0.0);
989    
990            try {
991                MathUtils.round(1.234f, 2, 1923);
992                fail();
993            } catch (IllegalArgumentException ex) {
994                // success
995            }
996    
997            // special values
998            TestUtils.assertEquals(Float.NaN, MathUtils.round(Float.NaN, 2), 0.0f);
999            assertEquals(0.0f, MathUtils.round(0.0f, 2), 0.0f);
1000            assertEquals(Float.POSITIVE_INFINITY, MathUtils.round(Float.POSITIVE_INFINITY, 2), 0.0f);
1001            assertEquals(Float.NEGATIVE_INFINITY, MathUtils.round(Float.NEGATIVE_INFINITY, 2), 0.0f);
1002        }
1003    
1004        public void testSignByte() {
1005            assertEquals((byte) 1, MathUtils.sign((byte) 2));
1006            assertEquals((byte) 0, MathUtils.sign((byte) 0));
1007            assertEquals((byte) (-1), MathUtils.sign((byte) (-2)));
1008        }
1009    
1010        public void testSignDouble() {
1011            double delta = 0.0;
1012            assertEquals(1.0, MathUtils.sign(2.0), delta);
1013            assertEquals(0.0, MathUtils.sign(0.0), delta);
1014            assertEquals(-1.0, MathUtils.sign(-2.0), delta);
1015            TestUtils.assertSame(-0. / 0., MathUtils.sign(Double.NaN));
1016        }
1017    
1018        public void testSignFloat() {
1019            float delta = 0.0F;
1020            assertEquals(1.0F, MathUtils.sign(2.0F), delta);
1021            assertEquals(0.0F, MathUtils.sign(0.0F), delta);
1022            assertEquals(-1.0F, MathUtils.sign(-2.0F), delta);
1023            TestUtils.assertSame(Float.NaN, MathUtils.sign(Float.NaN));
1024        }
1025    
1026        public void testSignInt() {
1027            assertEquals(1, MathUtils.sign(2));
1028            assertEquals(0, MathUtils.sign(0));
1029            assertEquals((-1), MathUtils.sign((-2)));
1030        }
1031    
1032        public void testSignLong() {
1033            assertEquals(1L, MathUtils.sign(2L));
1034            assertEquals(0L, MathUtils.sign(0L));
1035            assertEquals(-1L, MathUtils.sign(-2L));
1036        }
1037    
1038        public void testSignShort() {
1039            assertEquals((short) 1, MathUtils.sign((short) 2));
1040            assertEquals((short) 0, MathUtils.sign((short) 0));
1041            assertEquals((short) (-1), MathUtils.sign((short) (-2)));
1042        }
1043    
1044        public void testSinh() {
1045            double x = 3.0;
1046            double expected = 10.01787;
1047            assertEquals(expected, MathUtils.sinh(x), 1.0e-5);
1048        }
1049    
1050        public void testSinhNaN() {
1051            assertTrue(Double.isNaN(MathUtils.sinh(Double.NaN)));
1052        }
1053    
1054        public void testSubAndCheck() {
1055            int big = Integer.MAX_VALUE;
1056            int bigNeg = Integer.MIN_VALUE;
1057            assertEquals(big, MathUtils.subAndCheck(big, 0));
1058            assertEquals(bigNeg + 1, MathUtils.subAndCheck(bigNeg, -1));
1059            assertEquals(-1, MathUtils.subAndCheck(bigNeg, -big));
1060            try {
1061                MathUtils.subAndCheck(big, -1);
1062                fail("Expecting ArithmeticException");
1063            } catch (ArithmeticException ex) {
1064            }
1065            try {
1066                MathUtils.subAndCheck(bigNeg, 1);
1067                fail("Expecting ArithmeticException");
1068            } catch (ArithmeticException ex) {
1069            }
1070        }
1071    
1072        public void testSubAndCheckErrorMessage() {
1073            int big = Integer.MAX_VALUE;
1074            try {
1075                MathUtils.subAndCheck(big, -1);
1076                fail("Expecting ArithmeticException");
1077            } catch (ArithmeticException ex) {
1078                assertEquals("overflow: subtract", ex.getMessage());
1079            }
1080        }
1081    
1082        public void testSubAndCheckLong() {
1083            long max = Long.MAX_VALUE;
1084            long min = Long.MIN_VALUE;
1085            assertEquals(max, MathUtils.subAndCheck(max, 0));
1086            assertEquals(min, MathUtils.subAndCheck(min, 0));
1087            assertEquals(-max, MathUtils.subAndCheck(0, max));
1088            assertEquals(min + 1, MathUtils.subAndCheck(min, -1));
1089            // min == -1-max
1090            assertEquals(-1, MathUtils.subAndCheck(-max - 1, -max));
1091            assertEquals(max, MathUtils.subAndCheck(-1, -1 - max));
1092            testSubAndCheckLongFailure(0L, min);
1093            testSubAndCheckLongFailure(max, -1L);
1094            testSubAndCheckLongFailure(min, 1L);
1095        }
1096    
1097        private void testSubAndCheckLongFailure(long a, long b) {
1098            try {
1099                MathUtils.subAndCheck(a, b);
1100                fail("Expecting ArithmeticException");
1101            } catch (ArithmeticException ex) {
1102                // success
1103            }
1104    
1105        }
1106    
1107        public void testPow() {
1108    
1109            assertEquals(1801088541, MathUtils.pow(21, 7));
1110            assertEquals(1, MathUtils.pow(21, 0));
1111            try {
1112                MathUtils.pow(21, -7);
1113                fail("Expecting IllegalArgumentException");
1114            } catch (IllegalArgumentException e) {
1115                // expected behavior
1116            }
1117    
1118            assertEquals(1801088541, MathUtils.pow(21, 7l));
1119            assertEquals(1, MathUtils.pow(21, 0l));
1120            try {
1121                MathUtils.pow(21, -7l);
1122                fail("Expecting IllegalArgumentException");
1123            } catch (IllegalArgumentException e) {
1124                // expected behavior
1125            }
1126    
1127            assertEquals(1801088541l, MathUtils.pow(21l, 7));
1128            assertEquals(1l, MathUtils.pow(21l, 0));
1129            try {
1130                MathUtils.pow(21l, -7);
1131                fail("Expecting IllegalArgumentException");
1132            } catch (IllegalArgumentException e) {
1133                // expected behavior
1134            }
1135    
1136            assertEquals(1801088541l, MathUtils.pow(21l, 7l));
1137            assertEquals(1l, MathUtils.pow(21l, 0l));
1138            try {
1139                MathUtils.pow(21l, -7l);
1140                fail("Expecting IllegalArgumentException");
1141            } catch (IllegalArgumentException e) {
1142                // expected behavior
1143            }
1144    
1145            BigInteger twentyOne = BigInteger.valueOf(21l);
1146            assertEquals(BigInteger.valueOf(1801088541l), MathUtils.pow(twentyOne, 7));
1147            assertEquals(BigInteger.ONE, MathUtils.pow(twentyOne, 0));
1148            try {
1149                MathUtils.pow(twentyOne, -7);
1150                fail("Expecting IllegalArgumentException");
1151            } catch (IllegalArgumentException e) {
1152                // expected behavior
1153            }
1154    
1155            assertEquals(BigInteger.valueOf(1801088541l), MathUtils.pow(twentyOne, 7l));
1156            assertEquals(BigInteger.ONE, MathUtils.pow(twentyOne, 0l));
1157            try {
1158                MathUtils.pow(twentyOne, -7l);
1159                fail("Expecting IllegalArgumentException");
1160            } catch (IllegalArgumentException e) {
1161                // expected behavior
1162            }
1163    
1164            assertEquals(BigInteger.valueOf(1801088541l), MathUtils.pow(twentyOne, BigInteger.valueOf(7l)));
1165            assertEquals(BigInteger.ONE, MathUtils.pow(twentyOne, BigInteger.ZERO));
1166            try {
1167                MathUtils.pow(twentyOne, BigInteger.valueOf(-7l));
1168                fail("Expecting IllegalArgumentException");
1169            } catch (IllegalArgumentException e) {
1170                // expected behavior
1171            }
1172    
1173            BigInteger bigOne =
1174                new BigInteger("1543786922199448028351389769265814882661837148" +
1175                               "4763915343722775611762713982220306372888519211" +
1176                               "560905579993523402015636025177602059044911261");
1177            assertEquals(bigOne, MathUtils.pow(twentyOne, 103));
1178            assertEquals(bigOne, MathUtils.pow(twentyOne, 103l));
1179            assertEquals(bigOne, MathUtils.pow(twentyOne, BigInteger.valueOf(103l)));
1180            
1181        }
1182    
1183        public void testL1DistanceDouble() {
1184            double[] p1 = { 2.5,  0.0 };
1185            double[] p2 = { -0.5, 4.0 };
1186            assertEquals(7.0, MathUtils.distance1(p1, p2));
1187        }
1188    
1189        public void testL1DistanceInt() {
1190            int[] p1 = { 3, 0 };
1191            int[] p2 = { 0, 4 };
1192            assertEquals(7, MathUtils.distance1(p1, p2));
1193        }
1194    
1195        public void testL2DistanceDouble() {
1196            double[] p1 = { 2.5,  0.0 };
1197            double[] p2 = { -0.5, 4.0 };
1198            assertEquals(5.0, MathUtils.distance(p1, p2));
1199        }
1200    
1201        public void testL2DistanceInt() {
1202            int[] p1 = { 3, 0 };
1203            int[] p2 = { 0, 4 };
1204            assertEquals(5.0, MathUtils.distance(p1, p2));
1205        }
1206    
1207        public void testLInfDistanceDouble() {
1208            double[] p1 = { 2.5,  0.0 };
1209            double[] p2 = { -0.5, 4.0 };
1210            assertEquals(4.0, MathUtils.distanceInf(p1, p2));
1211        }
1212    
1213        public void testLInfDistanceInt() {
1214            int[] p1 = { 3, 0 };
1215            int[] p2 = { 0, 4 };
1216            assertEquals(4, MathUtils.distanceInf(p1, p2));
1217        }
1218    
1219    }