You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by br...@apache.org on 2007/10/31 08:23:02 UTC
svn commit: r590577 - in /commons/proper/math/trunk:
src/java/org/apache/commons/math/util/MathUtils.java
src/test/org/apache/commons/math/util/MathUtilsTest.java xdocs/changes.xml
Author: brentworden
Date: Wed Oct 31 00:23:01 2007
New Revision: 590577
URL: http://svn.apache.org/viewvc?rev=590577&view=rev
Log:
MATH-154. Added addAndCheck, mulAndCheck, and subAndCheck MathUtils methods for long integer arguments.
Modified:
commons/proper/math/trunk/src/java/org/apache/commons/math/util/MathUtils.java
commons/proper/math/trunk/src/test/org/apache/commons/math/util/MathUtilsTest.java
commons/proper/math/trunk/xdocs/changes.xml
Modified: commons/proper/math/trunk/src/java/org/apache/commons/math/util/MathUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/util/MathUtils.java?rev=590577&r1=590576&r2=590577&view=diff
==============================================================================
--- commons/proper/math/trunk/src/java/org/apache/commons/math/util/MathUtils.java (original)
+++ commons/proper/math/trunk/src/java/org/apache/commons/math/util/MathUtils.java Wed Oct 31 00:23:01 2007
@@ -69,6 +69,66 @@
}
/**
+ * Add two long integers, checking for overflow.
+ *
+ * @param a an addend
+ * @param b an addend
+ * @return the sum <code>a+b</code>
+ * @throws ArithmeticException if the result can not be represented as an
+ * long
+ * @since 1.2
+ */
+ public static long addAndCheck(long a, long b) {
+ return addAndCheck(a, b, "overflow: add");
+ }
+
+ /**
+ * Add two long integers, checking for overflow.
+ *
+ * @param a an addend
+ * @param b an addend
+ * @param msg the message to use for any thrown exception.
+ * @return the sum <code>a+b</code>
+ * @throws ArithmeticException if the result can not be represented as an
+ * long
+ * @since 1.2
+ */
+ private static long addAndCheck(long a, long b, String msg) {
+ long ret;
+ if (a > b) {
+ // use symmetry to reduce boundry cases
+ ret = addAndCheck(b, a, msg);
+ } else {
+ // assert a <= b
+
+ if (a < 0) {
+ if (b < 0) {
+ // check for negative overflow
+ if (Long.MIN_VALUE - b <= a) {
+ ret = a + b;
+ } else {
+ throw new ArithmeticException(msg);
+ }
+ } else {
+ // oppisite sign addition is always safe
+ ret = a + b;
+ }
+ } else {
+ // assert a >= 0
+ // assert b >= 0
+
+ // check for positive overflow
+ if (a <= Long.MAX_VALUE - b) {
+ ret = a + b;
+ } else {
+ throw new ArithmeticException(msg);
+ }
+ }
+ }
+ return ret;
+ }
+
+ /**
* Returns an exact representation of the <a
* href="http://mathworld.wolfram.com/BinomialCoefficient.html"> Binomial
* Coefficient</a>, "<code>n choose k</code>", the number of
@@ -117,26 +177,7 @@
}
return result;
}
-
- /**
- * <p>Returns the
- * <a href="http://mathworld.wolfram.com/Logarithm.html">logarithm</a>
- * for base <code>b</code> of <code>x</code>.
- * </p>
- * <p>Returns <code>NaN<code> if either argument is negative. If
- * <code>base</code> is 0 and <code>x</code> is positive, 0 is returned.
- * If <code>base</code> is positive and <code>x</code> is 0,
- * <code>Double.NEGATIVE_INFINITY</code> is returned. If both arguments
- * are 0, the result is <code>NaN</code>.</p>
- *
- * @param base the base of the logarithm, must be greater than 0
- * @param x argument, must be greater than 0
- * @return the value of the logarithm - the number y such that base^y = x.
- */
- public static double log(double base, double x) {
- return Math.log(x)/Math.log(base);
- }
-
+
/**
* Returns a <code>double</code> representation of the <a
* href="http://mathworld.wolfram.com/BinomialCoefficient.html"> Binomial
@@ -162,7 +203,7 @@
public static double binomialCoefficientDouble(final int n, final int k) {
return Math.floor(Math.exp(binomialCoefficientLog(n, k)) + 0.5);
}
-
+
/**
* Returns the natural <code>log</code> of the <a
* href="http://mathworld.wolfram.com/BinomialCoefficient.html"> Binomial
@@ -210,7 +251,7 @@
return logSum;
}
-
+
/**
* Returns the <a href="http://mathworld.wolfram.com/HyperbolicCosine.html">
* hyperbolic cosine</a> of x.
@@ -221,7 +262,7 @@
public static double cosh(double x) {
return (Math.exp(x) + Math.exp(-x)) / 2.0;
}
-
+
/**
* Returns true iff both arguments are NaN or neither is NaN and they are
* equal
@@ -475,6 +516,25 @@
return Math.abs(mulAndCheck(a / gcd(a, b), b));
}
+ /**
+ * <p>Returns the
+ * <a href="http://mathworld.wolfram.com/Logarithm.html">logarithm</a>
+ * for base <code>b</code> of <code>x</code>.
+ * </p>
+ * <p>Returns <code>NaN<code> if either argument is negative. If
+ * <code>base</code> is 0 and <code>x</code> is positive, 0 is returned.
+ * If <code>base</code> is positive and <code>x</code> is 0,
+ * <code>Double.NEGATIVE_INFINITY</code> is returned. If both arguments
+ * are 0, the result is <code>NaN</code>.</p>
+ *
+ * @param base the base of the logarithm, must be greater than 0
+ * @param x argument, must be greater than 0
+ * @return the value of the logarithm - the number y such that base^y = x.
+ */
+ public static double log(double base, double x) {
+ return Math.log(x)/Math.log(base);
+ }
+
/**
* Multiply two integers, checking for overflow.
*
@@ -494,6 +554,61 @@
}
/**
+ * Multiply two long integers, checking for overflow.
+ *
+ * @param a first value
+ * @param b second value
+ * @return the product <code>a * b</code>
+ * @throws ArithmeticException if the result can not be represented as an
+ * long
+ * @since 1.2
+ */
+ public static long mulAndCheck(long a, long b) {
+ long ret;
+ String msg = "overflow: multiply";
+ if (a > b) {
+ // use symmetry to reduce boundry cases
+ ret = mulAndCheck(b, a);
+ } else {
+ if (a < 0) {
+ if (b < 0) {
+ // check for positive overflow with negative a, negative b
+ if (a >= Long.MAX_VALUE / b) {
+ ret = a * b;
+ } else {
+ throw new ArithmeticException(msg);
+ }
+ } else if (b > 0) {
+ // check for negative overflow with negative a, positive b
+ if (Long.MIN_VALUE / b <= a) {
+ ret = a * b;
+ } else {
+ throw new ArithmeticException(msg);
+
+ }
+ } else {
+ // assert b == 0
+ ret = 0;
+ }
+ } else if (a > 0) {
+ // assert a > 0
+ // assert b > 0
+
+ // check for positive overflow with positive a, positive b
+ if (a <= Long.MAX_VALUE / b) {
+ ret = a * b;
+ } else {
+ throw new ArithmeticException(msg);
+ }
+ } else {
+ // assert a == 0
+ ret = 0;
+ }
+ }
+ return ret;
+ }
+
+ /**
* Get the next machine representable number after a number, moving
* in the direction of another number.
* <p>
@@ -823,5 +938,31 @@
throw new ArithmeticException("overflow: subtract");
}
return (int)s;
+ }
+
+ /**
+ * Subtract two long integers, checking for overflow.
+ *
+ * @param a first value
+ * @param b second value
+ * @return the difference <code>a-b</code>
+ * @throws ArithmeticException if the result can not be represented as an
+ * long
+ * @since 1.2
+ */
+ public static long subAndCheck(long a, long b) {
+ long ret;
+ String msg = "overflow: subtract";
+ if (b == Long.MIN_VALUE) {
+ if (a < 0) {
+ ret = a - b;
+ } else {
+ throw new ArithmeticException(msg);
+ }
+ } else {
+ // use additive inverse
+ ret = addAndCheck(a, -b, msg);
+ }
+ return ret;
}
}
Modified: commons/proper/math/trunk/src/test/org/apache/commons/math/util/MathUtilsTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/org/apache/commons/math/util/MathUtilsTest.java?rev=590577&r1=590576&r2=590577&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/org/apache/commons/math/util/MathUtilsTest.java (original)
+++ commons/proper/math/trunk/src/test/org/apache/commons/math/util/MathUtilsTest.java Wed Oct 31 00:23:01 2007
@@ -1,33 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
+ * or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
*/
package org.apache.commons.math.util;
import java.math.BigDecimal;
-import org.apache.commons.math.TestUtils;
-
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
+import org.apache.commons.math.TestUtils;
+
/**
* Test cases for the MathUtils class.
- *
- * @version $Revision$ $Date$
+ * @version $Revision$ $Date: 2007-08-16 15:36:33 -0500 (Thu, 16 Aug
+ * 2007) $
*/
public final class MathUtilsTest extends TestCase {
@@ -40,7 +37,38 @@
suite.setName("MathUtils Tests");
return suite;
}
-
+
+ /**
+ * Exact recursive implementation to test against
+ */
+ private long binomialCoefficient(int n, int k) {
+ if ((n == k) || (k == 0)) {
+ return 1;
+ }
+ if ((k == 1) || (k == n - 1)) {
+ return n;
+ }
+ return binomialCoefficient(n - 1, k - 1) + binomialCoefficient(n - 1, k);
+ }
+
+ /**
+ * Exact direct multiplication implementation to test against
+ */
+ private long factorial(int n) {
+ long result = 1;
+ for (int i = 2; i <= n; i++) {
+ result *= i;
+ }
+ return result;
+ }
+
+ /** Verify that b(0,0) = 1 */
+ public void test0Choose0() {
+ assertEquals(MathUtils.binomialCoefficientDouble(0, 0), 1d, 0);
+ assertEquals(MathUtils.binomialCoefficientLog(0, 0), 0d, 0);
+ assertEquals(MathUtils.binomialCoefficient(0, 0), 1);
+ }
+
public void testAddAndCheck() {
int big = Integer.MAX_VALUE;
int bigNeg = Integer.MIN_VALUE;
@@ -48,130 +76,144 @@
try {
MathUtils.addAndCheck(big, 1);
fail("Expecting ArithmeticException");
- } catch (ArithmeticException ex) {}
+ } catch (ArithmeticException ex) {
+ }
try {
MathUtils.addAndCheck(bigNeg, -1);
fail("Expecting ArithmeticException");
- } catch (ArithmeticException ex) {}
- }
-
- public void testMulAndCheck() {
- int big = Integer.MAX_VALUE;
- int bigNeg = Integer.MIN_VALUE;
- assertEquals(big, MathUtils.mulAndCheck(big, 1));
- try {
- MathUtils.mulAndCheck(big, 2);
- fail("Expecting ArithmeticException");
- } catch (ArithmeticException ex) {}
- try {
- MathUtils.mulAndCheck(bigNeg, 2);
- fail("Expecting ArithmeticException");
- } catch (ArithmeticException ex) {}
+ } catch (ArithmeticException ex) {
+ }
}
-
- public void testSubAndCheck() {
- int big = Integer.MAX_VALUE;
- int bigNeg = Integer.MIN_VALUE;
- assertEquals(big, MathUtils.subAndCheck(big, 0));
- try {
- MathUtils.subAndCheck(big, -1);
- fail("Expecting ArithmeticException");
- } catch (ArithmeticException ex) {}
- try {
- MathUtils.subAndCheck(bigNeg, 1);
- fail("Expecting ArithmeticException");
- } catch (ArithmeticException ex) {}
+
+ public void testAddAndCheckLong() {
+ long max = Long.MAX_VALUE;
+ long min = Long.MIN_VALUE;
+ assertEquals(max, MathUtils.addAndCheck(max, 0L));
+ assertEquals(min, MathUtils.addAndCheck(min, 0L));
+ assertEquals(max, MathUtils.addAndCheck(0L, max));
+ assertEquals(min, MathUtils.addAndCheck(0L, min));
+ assertEquals(1, MathUtils.addAndCheck(-1L, 2L));
+ assertEquals(1, MathUtils.addAndCheck(2L, -1L));
+ testAddAndCheckLongFailure(max, 1L);
+ testAddAndCheckLongFailure(min, -1L);
+ testAddAndCheckLongFailure(1L, max);
+ testAddAndCheckLongFailure(-1L, min);
}
-
- public void testSubAndCheckErrorMessage() {
- int big = Integer.MAX_VALUE;
+
+ private void testAddAndCheckLongFailure(long a, long b) {
try {
- MathUtils.subAndCheck(big, -1);
+ MathUtils.addAndCheck(a, b);
fail("Expecting ArithmeticException");
} catch (ArithmeticException ex) {
- assertEquals("overflow: subtract", ex.getMessage());
+ // success
}
}
-
+
public void testBinomialCoefficient() {
- long[] bcoef5 = {1,5,10,10,5,1};
- long[] bcoef6 = {1,6,15,20,15,6,1};
+ long[] bcoef5 = {
+ 1,
+ 5,
+ 10,
+ 10,
+ 5,
+ 1 };
+ long[] bcoef6 = {
+ 1,
+ 6,
+ 15,
+ 20,
+ 15,
+ 6,
+ 1 };
for (int i = 0; i < 6; i++) {
- assertEquals("5 choose " + i, bcoef5[i],
- MathUtils.binomialCoefficient(5,i));
+ assertEquals("5 choose " + i, bcoef5[i], MathUtils.binomialCoefficient(5, i));
}
for (int i = 0; i < 7; i++) {
- assertEquals("6 choose " + i, bcoef6[i],
- MathUtils.binomialCoefficient(6,i));
+ assertEquals("6 choose " + i, bcoef6[i], MathUtils.binomialCoefficient(6, i));
}
-
+
for (int n = 1; n < 10; n++) {
for (int k = 0; k <= n; k++) {
- assertEquals(n + " choose " + k, binomialCoefficient(n, k),
- MathUtils.binomialCoefficient(n, k));
- assertEquals(n + " choose " + k,(double) binomialCoefficient(n, k),
- MathUtils.binomialCoefficientDouble(n, k),Double.MIN_VALUE);
- assertEquals(n + " choose " + k,
- Math.log((double) binomialCoefficient(n, k)),
- MathUtils.binomialCoefficientLog(n, k),10E-12);
+ assertEquals(n + " choose " + k, binomialCoefficient(n, k), MathUtils.binomialCoefficient(n, k));
+ assertEquals(n + " choose " + k, (double)binomialCoefficient(n, k), MathUtils.binomialCoefficientDouble(n, k), Double.MIN_VALUE);
+ assertEquals(n + " choose " + k, Math.log((double)binomialCoefficient(n, k)), MathUtils.binomialCoefficientLog(n, k), 10E-12);
}
}
-
- /*
- * Takes a long time for recursion to unwind, but succeeds
- * and yields exact value = 2,333,606,220
-
- assertEquals(MathUtils.binomialCoefficient(34,17),
- binomialCoefficient(34,17));
- */
- }
-
- /** Verify that b(0,0) = 1 */
- public void test0Choose0() {
- assertEquals(MathUtils.binomialCoefficientDouble(0, 0), 1d, 0);
- assertEquals(MathUtils.binomialCoefficientLog(0, 0), 0d, 0);
- assertEquals(MathUtils.binomialCoefficient(0, 0), 1);
+
+ /*
+ * Takes a long time for recursion to unwind, but succeeds and yields
+ * exact value = 2,333,606,220
+ * assertEquals(MathUtils.binomialCoefficient(34,17),
+ * binomialCoefficient(34,17));
+ */
}
-
+
public void testBinomialCoefficientFail() {
try {
- MathUtils.binomialCoefficient(4,5);
- fail ("expecting IllegalArgumentException");
+ MathUtils.binomialCoefficient(4, 5);
+ fail("expecting IllegalArgumentException");
} catch (IllegalArgumentException ex) {
;
}
-
+
try {
- MathUtils.binomialCoefficientDouble(4,5);
- fail ("expecting IllegalArgumentException");
+ MathUtils.binomialCoefficientDouble(4, 5);
+ fail("expecting IllegalArgumentException");
} catch (IllegalArgumentException ex) {
;
}
-
+
try {
- MathUtils.binomialCoefficientLog(4,5);
- fail ("expecting IllegalArgumentException");
+ MathUtils.binomialCoefficientLog(4, 5);
+ fail("expecting IllegalArgumentException");
} catch (IllegalArgumentException ex) {
;
}
try {
- MathUtils.binomialCoefficient(67,34);
- fail ("expecting ArithmeticException");
+ MathUtils.binomialCoefficient(67, 34);
+ fail("expecting ArithmeticException");
} catch (ArithmeticException ex) {
;
}
- double x = MathUtils.binomialCoefficientDouble(1030,515);
- assertTrue("expecting infinite binomial coefficient",
- Double.isInfinite(x));
+ double x = MathUtils.binomialCoefficientDouble(1030, 515);
+ assertTrue("expecting infinite binomial coefficient", Double.isInfinite(x));
+ }
+
+ public void testCosh() {
+ double x = 3.0;
+ double expected = 10.06766;
+ assertEquals(expected, MathUtils.cosh(x), 1.0e-5);
+ }
+
+ public void testCoshNaN() {
+ assertTrue(Double.isNaN(MathUtils.cosh(Double.NaN)));
+ }
+
+ public void testEquals() {
+ double[] testArray = {
+ Double.NaN,
+ Double.POSITIVE_INFINITY,
+ Double.NEGATIVE_INFINITY,
+ 1d,
+ 0d };
+ for (int i = 0; i < testArray.length; i++) {
+ for (int j = 0; j < testArray.length; j++) {
+ if (i == j) {
+ assertTrue(MathUtils.equals(testArray[i], testArray[j]));
+ assertTrue(MathUtils.equals(testArray[j], testArray[i]));
+ } else {
+ assertTrue(!MathUtils.equals(testArray[i], testArray[j]));
+ assertTrue(!MathUtils.equals(testArray[j], testArray[i]));
+ }
+ }
+ }
}
public void testFactorial() {
for (int i = 1; i < 10; i++) {
- assertEquals(i + "! ",factorial(i),MathUtils.factorial(i));
- assertEquals(i + "! ",(double)factorial(i),
- MathUtils.factorialDouble(i),Double.MIN_VALUE);
- assertEquals(i + "! ",Math.log((double)factorial(i)),
- MathUtils.factorialLog(i),10E-12);
+ assertEquals(i + "! ", factorial(i), MathUtils.factorial(i));
+ assertEquals(i + "! ", (double)factorial(i), MathUtils.factorialDouble(i), Double.MIN_VALUE);
+ assertEquals(i + "! ", Math.log((double)factorial(i)), MathUtils.factorialLog(i), 10E-12);
}
assertEquals("0", 1, MathUtils.factorial(0));
assertEquals("0", 1.0d, MathUtils.factorialDouble(0), 1E-14);
@@ -181,306 +223,121 @@
public void testFactorialFail() {
try {
MathUtils.factorial(-1);
- fail ("expecting IllegalArgumentException");
+ fail("expecting IllegalArgumentException");
} catch (IllegalArgumentException ex) {
;
}
try {
MathUtils.factorialDouble(-1);
- fail ("expecting IllegalArgumentException");
+ fail("expecting IllegalArgumentException");
} catch (IllegalArgumentException ex) {
;
}
try {
MathUtils.factorialLog(-1);
- fail ("expecting IllegalArgumentException");
+ fail("expecting IllegalArgumentException");
} catch (IllegalArgumentException ex) {
;
}
try {
MathUtils.factorial(21);
- fail ("expecting ArithmeticException");
+ fail("expecting ArithmeticException");
} catch (ArithmeticException ex) {
;
}
- assertTrue("expecting infinite factorial value",
- Double.isInfinite(MathUtils.factorialDouble(171)));
+ assertTrue("expecting infinite factorial value", Double.isInfinite(MathUtils.factorialDouble(171)));
}
+ public void testGcd() {
+ int a = 30;
+ int b = 50;
+ int c = 77;
- /**
- * Exact recursive implementation to test against
- */
- private long binomialCoefficient(int n, int k) {
- if ((n == k) || (k == 0)) {
- return 1;
- }
- if ((k == 1) || (k == n - 1)) {
- return n;
- }
- return binomialCoefficient(n - 1, k - 1) +
- binomialCoefficient(n - 1, k);
- }
-
- /**
- * Finds the largest values of n for which binomialCoefficient and
- * binomialCoefficientDouble will return values that fit in a long, double,
- * resp. Remove comments around test below to get this in test-report
- *
- public void testLimits() {
- findBinomialLimits();
- }
- */
+ assertEquals(0, MathUtils.gcd(0, 0));
- private void findBinomialLimits() {
- /**
- * will kick out 66 as the limit for long
- */
- boolean foundLimit = false;
- int test = 10;
- while (!foundLimit) {
- try {
- MathUtils.binomialCoefficient(test, test / 2);
- } catch (ArithmeticException ex) {
- foundLimit = true;
- System.out.println
- ("largest n for binomialCoefficient = " + (test - 1) );
- }
- test++;
- }
+ assertEquals(b, MathUtils.gcd(0, b));
+ assertEquals(a, MathUtils.gcd(a, 0));
+ assertEquals(b, MathUtils.gcd(0, -b));
+ assertEquals(a, MathUtils.gcd(-a, 0));
+
+ assertEquals(10, MathUtils.gcd(a, b));
+ assertEquals(10, MathUtils.gcd(-a, b));
+ assertEquals(10, MathUtils.gcd(a, -b));
+ assertEquals(10, MathUtils.gcd(-a, -b));
- /**
- * will kick out 1029 as the limit for double
- */
- foundLimit = false;
- test = 10;
- while (!foundLimit) {
- double x = MathUtils.binomialCoefficientDouble(test, test / 2);
- if (Double.isInfinite(x)) {
- foundLimit = true;
- System.out.println
- ("largest n for binomialCoefficientD = " + (test - 1) );
- }
- test++;
- }
+ assertEquals(1, MathUtils.gcd(a, c));
+ assertEquals(1, MathUtils.gcd(-a, c));
+ assertEquals(1, MathUtils.gcd(a, -c));
+ assertEquals(1, MathUtils.gcd(-a, -c));
}
- /**
- * Finds the largest values of n for which factiorial and
- * factorialDouble will return values that fit in a long, double,
- * resp. Remove comments around test below to get this in test-report
-
- public void testFactiorialLimits() {
- findFactorialLimits();
- }
- */
-
- private void findFactorialLimits() {
- /**
- * will kick out 20 as the limit for long
- */
- boolean foundLimit = false;
- int test = 10;
- while (!foundLimit) {
- try {
- MathUtils.factorial(test);
- } catch (ArithmeticException ex) {
- foundLimit = true;
- System.out.println
- ("largest n for factorial = " + (test - 1) );
- }
- test++;
- }
-
- /**
- * will kick out 170 as the limit for double
- */
- foundLimit = false;
- test = 10;
- while (!foundLimit) {
- double x = MathUtils.factorialDouble(test);
- if (Double.isInfinite(x)) {
- foundLimit = true;
- System.out.println
- ("largest n for factorialDouble = " + (test - 1) );
+ public void testHash() {
+ double[] testArray = {
+ Double.NaN,
+ Double.POSITIVE_INFINITY,
+ Double.NEGATIVE_INFINITY,
+ 1d,
+ 0d,
+ 1E-14,
+ (1 + 1E-14),
+ Double.MIN_VALUE,
+ Double.MAX_VALUE };
+ for (int i = 0; i < testArray.length; i++) {
+ for (int j = 0; j < testArray.length; j++) {
+ if (i == j) {
+ assertEquals(MathUtils.hash(testArray[i]), MathUtils.hash(testArray[j]));
+ assertEquals(MathUtils.hash(testArray[j]), MathUtils.hash(testArray[i]));
+ } else {
+ assertTrue(MathUtils.hash(testArray[i]) != MathUtils.hash(testArray[j]));
+ assertTrue(MathUtils.hash(testArray[j]) != MathUtils.hash(testArray[i]));
+ }
}
- test++;
- }
- }
-
-
- /**
- * Exact direct multiplication implementation to test against
- */
- private long factorial(int n) {
- long result = 1;
- for (int i = 2; i <= n; i++) {
- result *= i;
}
- return result;
}
- public void testSignDouble() {
- double delta = 0.0 ;
- assertEquals( 1.0, MathUtils.indicator( 2.0 ), delta ) ;
- assertEquals( -1.0, MathUtils.indicator( -2.0 ), delta ) ;
+ public void testIndicatorByte() {
+ assertEquals((byte)1, MathUtils.indicator((byte)2));
+ assertEquals((byte)1, MathUtils.indicator((byte)0));
+ assertEquals((byte)(-1), MathUtils.indicator((byte)(-2)));
}
- public void testSignFloat() {
- float delta = 0.0F ;
- assertEquals( 1.0F, MathUtils.indicator( 2.0F ), delta ) ;
- assertEquals( -1.0F, MathUtils.indicator( -2.0F ), delta ) ;
+ public void testIndicatorDouble() {
+ double delta = 0.0;
+ assertEquals(1.0, MathUtils.indicator(2.0), delta);
+ assertEquals(1.0, MathUtils.indicator(0.0), delta);
+ assertEquals(-1.0, MathUtils.indicator(-2.0), delta);
}
- public void testSignByte() {
- assertEquals( (byte)1, MathUtils.indicator( (byte)2 ) ) ;
- assertEquals( (byte)(-1), MathUtils.indicator( (byte)(-2) ) ) ;
+ public void testIndicatorFloat() {
+ float delta = 0.0F;
+ assertEquals(1.0F, MathUtils.indicator(2.0F), delta);
+ assertEquals(1.0F, MathUtils.indicator(0.0F), delta);
+ assertEquals(-1.0F, MathUtils.indicator(-2.0F), delta);
}
- public void testSignShort() {
- assertEquals( (short)1, MathUtils.indicator( (short)2 ) ) ;
- assertEquals( (short)(-1), MathUtils.indicator( (short)(-2) ) ) ;
+ public void testIndicatorInt() {
+ assertEquals((int)1, MathUtils.indicator((int)(2)));
+ assertEquals((int)1, MathUtils.indicator((int)(0)));
+ assertEquals((int)(-1), MathUtils.indicator((int)(-2)));
}
- public void testSignInt() {
- assertEquals( (int)1, MathUtils.indicator( (int)(2) ) ) ;
- assertEquals( (int)(-1), MathUtils.indicator( (int)(-2) ) ) ;
+ public void testIndicatorLong() {
+ assertEquals(1L, MathUtils.indicator(2L));
+ assertEquals(1L, MathUtils.indicator(0L));
+ assertEquals(-1L, MathUtils.indicator(-2L));
}
- public void testSignLong() {
- assertEquals( 1L, MathUtils.indicator( 2L ) ) ;
- assertEquals( -1L, MathUtils.indicator( -2L ) ) ;
- }
-
- public void testIndicatorDouble() {
- double delta = 0.0 ;
- assertEquals( 1.0, MathUtils.indicator( 2.0 ), delta ) ;
- assertEquals( 1.0, MathUtils.indicator( 0.0 ), delta ) ;
- assertEquals( -1.0, MathUtils.indicator( -2.0 ), delta ) ;
- }
-
- public void testIndicatorFloat() {
- float delta = 0.0F ;
- assertEquals( 1.0F, MathUtils.indicator( 2.0F ), delta ) ;
- assertEquals( 1.0F, MathUtils.indicator( 0.0F ), delta ) ;
- assertEquals( -1.0F, MathUtils.indicator( -2.0F ), delta ) ;
- }
-
- public void testIndicatorByte() {
- assertEquals( (byte)1, MathUtils.indicator( (byte)2 ) ) ;
- assertEquals( (byte)1, MathUtils.indicator( (byte)0 ) ) ;
- assertEquals( (byte)(-1), MathUtils.indicator( (byte)(-2) ) ) ;
- }
-
public void testIndicatorShort() {
- assertEquals( (short)1, MathUtils.indicator( (short)2 ) ) ;
- assertEquals( (short)1, MathUtils.indicator( (short)0 ) ) ;
- assertEquals( (short)(-1), MathUtils.indicator( (short)(-2) ) ) ;
- }
-
- public void testIndicatorInt() {
- assertEquals( (int)1, MathUtils.indicator( (int)(2) ) ) ;
- assertEquals( (int)1, MathUtils.indicator( (int)(0) ) ) ;
- assertEquals( (int)(-1), MathUtils.indicator( (int)(-2) ) ) ;
- }
-
- public void testIndicatorLong() {
- assertEquals( 1L, MathUtils.indicator( 2L ) ) ;
- assertEquals( 1L, MathUtils.indicator( 0L ) ) ;
- assertEquals( -1L, MathUtils.indicator( -2L ) ) ;
- }
-
- public void testCosh() {
- double x = 3.0;
- double expected = 10.06766;
- assertEquals(expected, MathUtils.cosh(x), 1.0e-5);
- }
-
- public void testSinh() {
- double x = 3.0;
- double expected = 10.01787;
- assertEquals(expected, MathUtils.sinh(x), 1.0e-5);
- }
-
- public void testCoshNaN() {
- assertTrue(Double.isNaN(MathUtils.cosh(Double.NaN)));
- }
-
- public void testSinhNaN() {
- assertTrue(Double.isNaN(MathUtils.sinh(Double.NaN)));
- }
-
- public void testEquals() {
- double[] testArray = {Double.NaN, Double.POSITIVE_INFINITY,
- Double.NEGATIVE_INFINITY, 1d, 0d};
- for (int i = 0; i < testArray.length; i++) {
- for (int j = 0; j < testArray.length; j ++) {
- if (i == j) {
- assertTrue(MathUtils.equals(testArray[i], testArray[j]));
- assertTrue(MathUtils.equals(testArray[j], testArray[i]));
- } else {
- assertTrue(!MathUtils.equals(testArray[i], testArray[j]));
- assertTrue(!MathUtils.equals(testArray[j], testArray[i]));
- }
- }
- }
- }
-
- public void testHash() {
- double[] testArray = {Double.NaN, Double.POSITIVE_INFINITY,
- Double.NEGATIVE_INFINITY, 1d, 0d, 1E-14, (1 + 1E-14),
- Double.MIN_VALUE, Double.MAX_VALUE};
- for (int i = 0; i < testArray.length; i++) {
- for (int j = 0; j < testArray.length; j ++) {
- if (i == j) {
- assertEquals(MathUtils.hash(testArray[i]), MathUtils.hash(testArray[j]));
- assertEquals(MathUtils.hash(testArray[j]), MathUtils.hash(testArray[i]));
- } else {
- assertTrue(MathUtils.hash(testArray[i]) != MathUtils.hash(testArray[j]));
- assertTrue(MathUtils.hash(testArray[j]) != MathUtils.hash(testArray[i]));
- }
- }
- }
+ assertEquals((short)1, MathUtils.indicator((short)2));
+ assertEquals((short)1, MathUtils.indicator((short)0));
+ assertEquals((short)(-1), MathUtils.indicator((short)(-2)));
}
-
- public void testLog() {
- assertEquals(2.0, MathUtils.log(2,4), 0);
- assertEquals(3.0, MathUtils.log(2,8), 0);
- assertTrue(Double.isNaN(MathUtils.log(-1, 1)));
- assertTrue(Double.isNaN(MathUtils.log(1, -1)));
- assertTrue(Double.isNaN(MathUtils.log(0, 0)));
- assertEquals(0, MathUtils.log(0, 10), 0);
- assertEquals(Double.NEGATIVE_INFINITY, MathUtils.log(10, 0), 0);
- }
-
- public void testGcd() {
- int a = 30;
- int b = 50;
- int c = 77;
- assertEquals(0, MathUtils.gcd(0, 0));
-
- assertEquals(b, MathUtils.gcd( 0, b));
- assertEquals(a, MathUtils.gcd( a, 0));
- assertEquals(b, MathUtils.gcd( 0, -b));
- assertEquals(a, MathUtils.gcd(-a, 0));
-
- assertEquals(10, MathUtils.gcd( a, b));
- assertEquals(10, MathUtils.gcd(-a, b));
- assertEquals(10, MathUtils.gcd( a, -b));
- assertEquals(10, MathUtils.gcd(-a, -b));
-
- assertEquals(1, MathUtils.gcd( a, c));
- assertEquals(1, MathUtils.gcd(-a, c));
- assertEquals(1, MathUtils.gcd( a, -c));
- assertEquals(1, MathUtils.gcd(-a, -c));
- }
-
public void testLcm() {
int a = 30;
int b = 50;
int c = 77;
-
+
assertEquals(0, MathUtils.lcm(0, b));
assertEquals(0, MathUtils.lcm(a, 0));
assertEquals(b, MathUtils.lcm(1, b));
@@ -489,7 +346,7 @@
assertEquals(150, MathUtils.lcm(-a, b));
assertEquals(150, MathUtils.lcm(a, -b));
assertEquals(2310, MathUtils.lcm(a, c));
-
+
try {
MathUtils.lcm(Integer.MAX_VALUE, Integer.MAX_VALUE - 1);
fail("Expecting ArithmeticException");
@@ -497,114 +354,61 @@
// expected
}
}
- public void testRoundFloat() {
- float x = 1.234567890f;
- assertEquals(1.23f, MathUtils.round(x, 2), 0.0);
- assertEquals(1.235f, MathUtils.round(x, 3), 0.0);
- assertEquals(1.2346f, MathUtils.round(x, 4), 0.0);
-
- // BZ 35904
- assertEquals(30.1f, MathUtils.round(30.095f, 2), 0.0f);
- assertEquals(30.1f, MathUtils.round(30.095f, 1), 0.0f);
- assertEquals(50.09f, MathUtils.round(50.085f, 2), 0.0f);
- assertEquals(50.19f, MathUtils.round(50.185f, 2), 0.0f);
- assertEquals(50.01f, MathUtils.round(50.005f, 2), 0.0f);
- assertEquals(30.01f, MathUtils.round(30.005f, 2), 0.0f);
- assertEquals(30.65f, MathUtils.round(30.645f, 2), 0.0f);
-
- assertEquals(1.24f, MathUtils.round(x, 2, BigDecimal.ROUND_CEILING), 0.0);
- assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_CEILING), 0.0);
- assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_CEILING), 0.0);
- assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_CEILING), 0.0);
- assertEquals(-1.234f, MathUtils.round(-x, 3, BigDecimal.ROUND_CEILING), 0.0);
- assertEquals(-1.2345f, MathUtils.round(-x, 4, BigDecimal.ROUND_CEILING), 0.0);
- assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_DOWN), 0.0);
- assertEquals(1.234f, MathUtils.round(x, 3, BigDecimal.ROUND_DOWN), 0.0);
- assertEquals(1.2345f, MathUtils.round(x, 4, BigDecimal.ROUND_DOWN), 0.0);
- assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_DOWN), 0.0);
- assertEquals(-1.234f, MathUtils.round(-x, 3, BigDecimal.ROUND_DOWN), 0.0);
- assertEquals(-1.2345f, MathUtils.round(-x, 4, BigDecimal.ROUND_DOWN), 0.0);
-
- assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_FLOOR), 0.0);
- assertEquals(1.234f, MathUtils.round(x, 3, BigDecimal.ROUND_FLOOR), 0.0);
- assertEquals(1.2345f, MathUtils.round(x, 4, BigDecimal.ROUND_FLOOR), 0.0);
- assertEquals(-1.24f, MathUtils.round(-x, 2, BigDecimal.ROUND_FLOOR), 0.0);
- assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_FLOOR), 0.0);
- assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_FLOOR), 0.0);
-
- assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_DOWN), 0.0);
- assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
- assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_DOWN), 0.0);
- assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_DOWN), 0.0);
- assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
- assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_DOWN), 0.0);
- assertEquals(1.234f, MathUtils.round(1.2345f, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
- assertEquals(-1.234f, MathUtils.round(-1.2345f, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
-
- assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_EVEN), 0.0);
- assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
- assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_EVEN), 0.0);
- assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_EVEN), 0.0);
- assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
- assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_EVEN), 0.0);
- assertEquals(1.234f, MathUtils.round(1.2345f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
- assertEquals(-1.234f, MathUtils.round(-1.2345f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
- assertEquals(1.236f, MathUtils.round(1.2355f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
- assertEquals(-1.236f, MathUtils.round(-1.2355f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
-
- assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_UP), 0.0);
- assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_UP), 0.0);
- assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_UP), 0.0);
- assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_UP), 0.0);
- assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_UP), 0.0);
- assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_UP), 0.0);
- assertEquals(1.235f, MathUtils.round(1.2345f, 3, BigDecimal.ROUND_HALF_UP), 0.0);
- assertEquals(-1.235f, MathUtils.round(-1.2345f, 3, BigDecimal.ROUND_HALF_UP), 0.0);
-
- assertEquals(-1.23f, MathUtils.round(-1.23f, 2, BigDecimal.ROUND_UNNECESSARY), 0.0);
- assertEquals(1.23f, MathUtils.round(1.23f, 2, BigDecimal.ROUND_UNNECESSARY), 0.0);
-
+ public void testLog() {
+ assertEquals(2.0, MathUtils.log(2, 4), 0);
+ assertEquals(3.0, MathUtils.log(2, 8), 0);
+ assertTrue(Double.isNaN(MathUtils.log(-1, 1)));
+ assertTrue(Double.isNaN(MathUtils.log(1, -1)));
+ assertTrue(Double.isNaN(MathUtils.log(0, 0)));
+ assertEquals(0, MathUtils.log(0, 10), 0);
+ assertEquals(Double.NEGATIVE_INFINITY, MathUtils.log(10, 0), 0);
+ }
+
+ public void testMulAndCheck() {
+ int big = Integer.MAX_VALUE;
+ int bigNeg = Integer.MIN_VALUE;
+ assertEquals(big, MathUtils.mulAndCheck(big, 1));
try {
- MathUtils.round(1.234f, 2, BigDecimal.ROUND_UNNECESSARY);
- fail();
+ MathUtils.mulAndCheck(big, 2);
+ fail("Expecting ArithmeticException");
} catch (ArithmeticException ex) {
- // success
}
-
- assertEquals(1.24f, MathUtils.round(x, 2, BigDecimal.ROUND_UP), 0.0);
- assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_UP), 0.0);
- assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_UP), 0.0);
- assertEquals(-1.24f, MathUtils.round(-x, 2, BigDecimal.ROUND_UP), 0.0);
- assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_UP), 0.0);
- assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_UP), 0.0);
-
try {
- MathUtils.round(1.234f, 2, 1923);
- fail();
- } catch (IllegalArgumentException ex) {
- // success
+ MathUtils.mulAndCheck(bigNeg, 2);
+ fail("Expecting ArithmeticException");
+ } catch (ArithmeticException ex) {
}
-
- // special values
- TestUtils.assertEquals(Float.NaN, MathUtils.round(Float.NaN, 2), 0.0f);
- assertEquals(0.0f, MathUtils.round(0.0f, 2), 0.0f);
- assertEquals(Float.POSITIVE_INFINITY, MathUtils.round(Float.POSITIVE_INFINITY, 2), 0.0f);
- assertEquals(Float.NEGATIVE_INFINITY, MathUtils.round(Float.NEGATIVE_INFINITY, 2), 0.0f);
}
-
- public void testNextAfterSpecialCases() {
- assertTrue(Double.isInfinite(MathUtils.nextAfter(Double.NEGATIVE_INFINITY, 0)));
- assertTrue(Double.isInfinite(MathUtils.nextAfter(Double.POSITIVE_INFINITY, 0)));
- assertTrue(Double.isNaN(MathUtils.nextAfter(Double.NaN, 0)));
- assertTrue(Double.isInfinite(MathUtils.nextAfter( Double.MAX_VALUE, Double.POSITIVE_INFINITY)));
- assertTrue(Double.isInfinite(MathUtils.nextAfter(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY)));
- assertEquals( Double.MIN_VALUE, MathUtils.nextAfter(0, 1), 0);
- assertEquals(-Double.MIN_VALUE, MathUtils.nextAfter(0, -1), 0);
- assertEquals(0, MathUtils.nextAfter( Double.MIN_VALUE, -1), 0);
- assertEquals(0, MathUtils.nextAfter(-Double.MIN_VALUE, 1), 0);
+
+ public void testMulAndCheckLong() {
+ long max = Long.MAX_VALUE;
+ long min = Long.MIN_VALUE;
+ assertEquals(max, MathUtils.mulAndCheck(max, 1L));
+ assertEquals(min, MathUtils.mulAndCheck(min, 1L));
+ assertEquals(0L, MathUtils.mulAndCheck(max, 0L));
+ assertEquals(0L, MathUtils.mulAndCheck(min, 0L));
+ assertEquals(max, MathUtils.mulAndCheck(1L, max));
+ assertEquals(min, MathUtils.mulAndCheck(1L, min));
+ assertEquals(0L, MathUtils.mulAndCheck(0L, max));
+ assertEquals(0L, MathUtils.mulAndCheck(0L, min));
+ testMulAndCheckLongFailure(max, 2L);
+ testMulAndCheckLongFailure(2L, max);
+ testMulAndCheckLongFailure(min, 2L);
+ testMulAndCheckLongFailure(2L, min);
+ testMulAndCheckLongFailure(min, -1L);
+ testMulAndCheckLongFailure(-1L, min);
+ }
+
+ private void testMulAndCheckLongFailure(long a, long b) {
+ try {
+ MathUtils.mulAndCheck(a, b);
+ fail("Expecting ArithmeticException");
+ } catch (ArithmeticException ex) {
+ // success
+ }
}
-
+
public void testNextAfter() {
// 0x402fffffffffffff 0x404123456789abcd -> 4030000000000000
assertEquals(16.0, MathUtils.nextAfter(15.999999999999998, 34.27555555555555), 0.0);
@@ -668,31 +472,42 @@
}
+ public void testNextAfterSpecialCases() {
+ assertTrue(Double.isInfinite(MathUtils.nextAfter(Double.NEGATIVE_INFINITY, 0)));
+ assertTrue(Double.isInfinite(MathUtils.nextAfter(Double.POSITIVE_INFINITY, 0)));
+ assertTrue(Double.isNaN(MathUtils.nextAfter(Double.NaN, 0)));
+ assertTrue(Double.isInfinite(MathUtils.nextAfter(Double.MAX_VALUE, Double.POSITIVE_INFINITY)));
+ assertTrue(Double.isInfinite(MathUtils.nextAfter(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY)));
+ assertEquals(Double.MIN_VALUE, MathUtils.nextAfter(0, 1), 0);
+ assertEquals(-Double.MIN_VALUE, MathUtils.nextAfter(0, -1), 0);
+ assertEquals(0, MathUtils.nextAfter(Double.MIN_VALUE, -1), 0);
+ assertEquals(0, MathUtils.nextAfter(-Double.MIN_VALUE, 1), 0);
+ }
+
public void testRoundDouble() {
double x = 1.234567890;
assertEquals(1.23, MathUtils.round(x, 2), 0.0);
assertEquals(1.235, MathUtils.round(x, 3), 0.0);
assertEquals(1.2346, MathUtils.round(x, 4), 0.0);
-
+
// JIRA MATH-151
- assertEquals(39.25,MathUtils.round(39.245, 2), 0.0);
- assertEquals(39.24,MathUtils.round(39.245, 2,
- BigDecimal.ROUND_DOWN), 0.0);
+ assertEquals(39.25, MathUtils.round(39.245, 2), 0.0);
+ assertEquals(39.24, MathUtils.round(39.245, 2, BigDecimal.ROUND_DOWN), 0.0);
double xx = 39.0;
- xx = xx + 245d/1000d;
- assertEquals(39.25,MathUtils.round(xx, 2), 0.0);
-
+ xx = xx + 245d / 1000d;
+ assertEquals(39.25, MathUtils.round(xx, 2), 0.0);
+
// BZ 35904
assertEquals(30.1d, MathUtils.round(30.095d, 2), 0.0d);
assertEquals(30.1d, MathUtils.round(30.095d, 1), 0.0d);
assertEquals(33.1d, MathUtils.round(33.095d, 1), 0.0d);
assertEquals(33.1d, MathUtils.round(33.095d, 2), 0.0d);
- assertEquals(50.09d, MathUtils.round(50.085d, 2), 0.0d);
- assertEquals(50.19d, MathUtils.round(50.185d, 2), 0.0d);
- assertEquals(50.01d, MathUtils.round(50.005d, 2), 0.0d);
- assertEquals(30.01d, MathUtils.round(30.005d, 2), 0.0d);
- assertEquals(30.65d, MathUtils.round(30.645d, 2), 0.0d);
-
+ assertEquals(50.09d, MathUtils.round(50.085d, 2), 0.0d);
+ assertEquals(50.19d, MathUtils.round(50.185d, 2), 0.0d);
+ assertEquals(50.01d, MathUtils.round(50.005d, 2), 0.0d);
+ assertEquals(30.01d, MathUtils.round(30.005d, 2), 0.0d);
+ assertEquals(30.65d, MathUtils.round(30.645d, 2), 0.0d);
+
assertEquals(1.24, MathUtils.round(x, 2, BigDecimal.ROUND_CEILING), 0.0);
assertEquals(1.235, MathUtils.round(x, 3, BigDecimal.ROUND_CEILING), 0.0);
assertEquals(1.2346, MathUtils.round(x, 4, BigDecimal.ROUND_CEILING), 0.0);
@@ -706,14 +521,14 @@
assertEquals(-1.23, MathUtils.round(-x, 2, BigDecimal.ROUND_DOWN), 0.0);
assertEquals(-1.234, MathUtils.round(-x, 3, BigDecimal.ROUND_DOWN), 0.0);
assertEquals(-1.2345, MathUtils.round(-x, 4, BigDecimal.ROUND_DOWN), 0.0);
-
+
assertEquals(1.23, MathUtils.round(x, 2, BigDecimal.ROUND_FLOOR), 0.0);
assertEquals(1.234, MathUtils.round(x, 3, BigDecimal.ROUND_FLOOR), 0.0);
assertEquals(1.2345, MathUtils.round(x, 4, BigDecimal.ROUND_FLOOR), 0.0);
assertEquals(-1.24, MathUtils.round(-x, 2, BigDecimal.ROUND_FLOOR), 0.0);
assertEquals(-1.235, MathUtils.round(-x, 3, BigDecimal.ROUND_FLOOR), 0.0);
assertEquals(-1.2346, MathUtils.round(-x, 4, BigDecimal.ROUND_FLOOR), 0.0);
-
+
assertEquals(1.23, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_DOWN), 0.0);
assertEquals(1.235, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
assertEquals(1.2346, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_DOWN), 0.0);
@@ -722,7 +537,7 @@
assertEquals(-1.2346, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_DOWN), 0.0);
assertEquals(1.234, MathUtils.round(1.2345, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
assertEquals(-1.234, MathUtils.round(-1.2345, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
-
+
assertEquals(1.23, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_EVEN), 0.0);
assertEquals(1.235, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
assertEquals(1.2346, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_EVEN), 0.0);
@@ -733,7 +548,7 @@
assertEquals(-1.234, MathUtils.round(-1.2345, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
assertEquals(1.236, MathUtils.round(1.2355, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
assertEquals(-1.236, MathUtils.round(-1.2355, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
-
+
assertEquals(1.23, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_UP), 0.0);
assertEquals(1.235, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_UP), 0.0);
assertEquals(1.2346, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_UP), 0.0);
@@ -742,24 +557,24 @@
assertEquals(-1.2346, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_UP), 0.0);
assertEquals(1.235, MathUtils.round(1.2345, 3, BigDecimal.ROUND_HALF_UP), 0.0);
assertEquals(-1.235, MathUtils.round(-1.2345, 3, BigDecimal.ROUND_HALF_UP), 0.0);
-
+
assertEquals(-1.23, MathUtils.round(-1.23, 2, BigDecimal.ROUND_UNNECESSARY), 0.0);
assertEquals(1.23, MathUtils.round(1.23, 2, BigDecimal.ROUND_UNNECESSARY), 0.0);
-
+
try {
MathUtils.round(1.234, 2, BigDecimal.ROUND_UNNECESSARY);
fail();
} catch (ArithmeticException ex) {
// success
}
-
+
assertEquals(1.24, MathUtils.round(x, 2, BigDecimal.ROUND_UP), 0.0);
assertEquals(1.235, MathUtils.round(x, 3, BigDecimal.ROUND_UP), 0.0);
assertEquals(1.2346, MathUtils.round(x, 4, BigDecimal.ROUND_UP), 0.0);
assertEquals(-1.24, MathUtils.round(-x, 2, BigDecimal.ROUND_UP), 0.0);
assertEquals(-1.235, MathUtils.round(-x, 3, BigDecimal.ROUND_UP), 0.0);
assertEquals(-1.2346, MathUtils.round(-x, 4, BigDecimal.ROUND_UP), 0.0);
-
+
try {
MathUtils.round(1.234, 2, 1923);
fail();
@@ -769,11 +584,196 @@
// MATH-151
assertEquals(39.25, MathUtils.round(39.245, 2, BigDecimal.ROUND_HALF_UP), 0.0);
-
+
// special values
TestUtils.assertEquals(Double.NaN, MathUtils.round(Double.NaN, 2), 0.0);
assertEquals(0.0, MathUtils.round(0.0, 2), 0.0);
assertEquals(Double.POSITIVE_INFINITY, MathUtils.round(Double.POSITIVE_INFINITY, 2), 0.0);
assertEquals(Double.NEGATIVE_INFINITY, MathUtils.round(Double.NEGATIVE_INFINITY, 2), 0.0);
+ }
+
+ public void testRoundFloat() {
+ float x = 1.234567890f;
+ assertEquals(1.23f, MathUtils.round(x, 2), 0.0);
+ assertEquals(1.235f, MathUtils.round(x, 3), 0.0);
+ assertEquals(1.2346f, MathUtils.round(x, 4), 0.0);
+
+ // BZ 35904
+ assertEquals(30.1f, MathUtils.round(30.095f, 2), 0.0f);
+ assertEquals(30.1f, MathUtils.round(30.095f, 1), 0.0f);
+ assertEquals(50.09f, MathUtils.round(50.085f, 2), 0.0f);
+ assertEquals(50.19f, MathUtils.round(50.185f, 2), 0.0f);
+ assertEquals(50.01f, MathUtils.round(50.005f, 2), 0.0f);
+ assertEquals(30.01f, MathUtils.round(30.005f, 2), 0.0f);
+ assertEquals(30.65f, MathUtils.round(30.645f, 2), 0.0f);
+
+ assertEquals(1.24f, MathUtils.round(x, 2, BigDecimal.ROUND_CEILING), 0.0);
+ assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_CEILING), 0.0);
+ assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_CEILING), 0.0);
+ assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_CEILING), 0.0);
+ assertEquals(-1.234f, MathUtils.round(-x, 3, BigDecimal.ROUND_CEILING), 0.0);
+ assertEquals(-1.2345f, MathUtils.round(-x, 4, BigDecimal.ROUND_CEILING), 0.0);
+
+ assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_DOWN), 0.0);
+ assertEquals(1.234f, MathUtils.round(x, 3, BigDecimal.ROUND_DOWN), 0.0);
+ assertEquals(1.2345f, MathUtils.round(x, 4, BigDecimal.ROUND_DOWN), 0.0);
+ assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_DOWN), 0.0);
+ assertEquals(-1.234f, MathUtils.round(-x, 3, BigDecimal.ROUND_DOWN), 0.0);
+ assertEquals(-1.2345f, MathUtils.round(-x, 4, BigDecimal.ROUND_DOWN), 0.0);
+
+ assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_FLOOR), 0.0);
+ assertEquals(1.234f, MathUtils.round(x, 3, BigDecimal.ROUND_FLOOR), 0.0);
+ assertEquals(1.2345f, MathUtils.round(x, 4, BigDecimal.ROUND_FLOOR), 0.0);
+ assertEquals(-1.24f, MathUtils.round(-x, 2, BigDecimal.ROUND_FLOOR), 0.0);
+ assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_FLOOR), 0.0);
+ assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_FLOOR), 0.0);
+
+ assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_DOWN), 0.0);
+ assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
+ assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_DOWN), 0.0);
+ assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_DOWN), 0.0);
+ assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
+ assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_DOWN), 0.0);
+ assertEquals(1.234f, MathUtils.round(1.2345f, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
+ assertEquals(-1.234f, MathUtils.round(-1.2345f, 3, BigDecimal.ROUND_HALF_DOWN), 0.0);
+
+ assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_EVEN), 0.0);
+ assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
+ assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_EVEN), 0.0);
+ assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_EVEN), 0.0);
+ assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
+ assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_EVEN), 0.0);
+ assertEquals(1.234f, MathUtils.round(1.2345f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
+ assertEquals(-1.234f, MathUtils.round(-1.2345f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
+ assertEquals(1.236f, MathUtils.round(1.2355f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
+ assertEquals(-1.236f, MathUtils.round(-1.2355f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0);
+
+ assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_UP), 0.0);
+ assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_UP), 0.0);
+ assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_UP), 0.0);
+ assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_UP), 0.0);
+ assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_UP), 0.0);
+ assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_UP), 0.0);
+ assertEquals(1.235f, MathUtils.round(1.2345f, 3, BigDecimal.ROUND_HALF_UP), 0.0);
+ assertEquals(-1.235f, MathUtils.round(-1.2345f, 3, BigDecimal.ROUND_HALF_UP), 0.0);
+
+ assertEquals(-1.23f, MathUtils.round(-1.23f, 2, BigDecimal.ROUND_UNNECESSARY), 0.0);
+ assertEquals(1.23f, MathUtils.round(1.23f, 2, BigDecimal.ROUND_UNNECESSARY), 0.0);
+
+ try {
+ MathUtils.round(1.234f, 2, BigDecimal.ROUND_UNNECESSARY);
+ fail();
+ } catch (ArithmeticException ex) {
+ // success
+ }
+
+ assertEquals(1.24f, MathUtils.round(x, 2, BigDecimal.ROUND_UP), 0.0);
+ assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_UP), 0.0);
+ assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_UP), 0.0);
+ assertEquals(-1.24f, MathUtils.round(-x, 2, BigDecimal.ROUND_UP), 0.0);
+ assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_UP), 0.0);
+ assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_UP), 0.0);
+
+ try {
+ MathUtils.round(1.234f, 2, 1923);
+ fail();
+ } catch (IllegalArgumentException ex) {
+ // success
+ }
+
+ // special values
+ TestUtils.assertEquals(Float.NaN, MathUtils.round(Float.NaN, 2), 0.0f);
+ assertEquals(0.0f, MathUtils.round(0.0f, 2), 0.0f);
+ assertEquals(Float.POSITIVE_INFINITY, MathUtils.round(Float.POSITIVE_INFINITY, 2), 0.0f);
+ assertEquals(Float.NEGATIVE_INFINITY, MathUtils.round(Float.NEGATIVE_INFINITY, 2), 0.0f);
+ }
+
+ public void testSignByte() {
+ assertEquals((byte)1, MathUtils.indicator((byte)2));
+ assertEquals((byte)(-1), MathUtils.indicator((byte)(-2)));
+ }
+
+ public void testSignDouble() {
+ double delta = 0.0;
+ assertEquals(1.0, MathUtils.indicator(2.0), delta);
+ assertEquals(-1.0, MathUtils.indicator(-2.0), delta);
+ }
+
+ public void testSignFloat() {
+ float delta = 0.0F;
+ assertEquals(1.0F, MathUtils.indicator(2.0F), delta);
+ assertEquals(-1.0F, MathUtils.indicator(-2.0F), delta);
+ }
+
+ public void testSignInt() {
+ assertEquals((int)1, MathUtils.indicator((int)(2)));
+ assertEquals((int)(-1), MathUtils.indicator((int)(-2)));
+ }
+
+ public void testSignLong() {
+ assertEquals(1L, MathUtils.indicator(2L));
+ assertEquals(-1L, MathUtils.indicator(-2L));
+ }
+
+ public void testSignShort() {
+ assertEquals((short)1, MathUtils.indicator((short)2));
+ assertEquals((short)(-1), MathUtils.indicator((short)(-2)));
+ }
+
+ public void testSinh() {
+ double x = 3.0;
+ double expected = 10.01787;
+ assertEquals(expected, MathUtils.sinh(x), 1.0e-5);
+ }
+
+ public void testSinhNaN() {
+ assertTrue(Double.isNaN(MathUtils.sinh(Double.NaN)));
+ }
+
+ public void testSubAndCheck() {
+ int big = Integer.MAX_VALUE;
+ int bigNeg = Integer.MIN_VALUE;
+ assertEquals(big, MathUtils.subAndCheck(big, 0));
+ try {
+ MathUtils.subAndCheck(big, -1);
+ fail("Expecting ArithmeticException");
+ } catch (ArithmeticException ex) {
+ }
+ try {
+ MathUtils.subAndCheck(bigNeg, 1);
+ fail("Expecting ArithmeticException");
+ } catch (ArithmeticException ex) {
+ }
+ }
+
+ public void testSubAndCheckErrorMessage() {
+ int big = Integer.MAX_VALUE;
+ try {
+ MathUtils.subAndCheck(big, -1);
+ fail("Expecting ArithmeticException");
+ } catch (ArithmeticException ex) {
+ assertEquals("overflow: subtract", ex.getMessage());
+ }
+ }
+
+ public void testSubAndCheckLong() {
+ long max = Long.MAX_VALUE;
+ long min = Long.MIN_VALUE;
+ assertEquals(max, MathUtils.subAndCheck(max, 0));
+ assertEquals(min, MathUtils.subAndCheck(min, 0));
+ assertEquals(-max, MathUtils.subAndCheck(0, max));
+ testSubAndCheckLongFailure(0L, min);
+ testSubAndCheckLongFailure(max, -1L);
+ testSubAndCheckLongFailure(min, 1L);
+ }
+
+ private void testSubAndCheckLongFailure(long a, long b) {
+ try {
+ MathUtils.subAndCheck(a, b);
+ fail("Expecting ArithmeticException");
+ } catch (ArithmeticException ex) {
+ // success
+ }
+
}
}
Modified: commons/proper/math/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/xdocs/changes.xml?rev=590577&r1=590576&r2=590577&view=diff
==============================================================================
--- commons/proper/math/trunk/xdocs/changes.xml (original)
+++ commons/proper/math/trunk/xdocs/changes.xml Wed Oct 31 00:23:01 2007
@@ -98,6 +98,10 @@
<action dev="brentworden" type="update" issue="MATH-170" due-to="David J. M. Karlsen">
Added SynchronizedDescriptiveStatistics class.
</action>
+ <action dev="brentworden" type="update" issue="MATH-154" due-to="Remi Arntzen">
+ Added addAndCheck, mulAndCheck, and subAndCheck MathUtils methods for
+ long integer arguments.
+ </action>
</release>
<release version="1.1" date="2005-12-17"
description="This is a maintenance release containing bug fixes and enhancements.