MATH-154. Added addAndCheck, mulAndCheck, and subAndCheck MathUtils methods for long integer arguments.
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@590577 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
828b70de30
commit
06da34fabc
|
@ -68,6 +68,66 @@ public final class MathUtils {
|
|||
return (int)s;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -118,25 +178,6 @@ public final class MathUtils {
|
|||
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
|
||||
|
@ -475,6 +516,25 @@ public final class MathUtils {
|
|||
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.
|
||||
*
|
||||
|
@ -493,6 +553,61 @@ public final class MathUtils {
|
|||
return (int)m;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
@ -824,4 +939,30 @@ public final class MathUtils {
|
|||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
@ -41,89 +38,28 @@ public final class MathUtilsTest extends TestCase {
|
|||
return suite;
|
||||
}
|
||||
|
||||
public void testAddAndCheck() {
|
||||
int big = Integer.MAX_VALUE;
|
||||
int bigNeg = Integer.MIN_VALUE;
|
||||
assertEquals(big, MathUtils.addAndCheck(big, 0));
|
||||
try {
|
||||
MathUtils.addAndCheck(big, 1);
|
||||
fail("Expecting ArithmeticException");
|
||||
} 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) {}
|
||||
}
|
||||
|
||||
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 testBinomialCoefficient() {
|
||||
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));
|
||||
}
|
||||
for (int i = 0; i < 7; 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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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));
|
||||
/**
|
||||
* 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 */
|
||||
|
@ -133,6 +69,85 @@ public final class MathUtilsTest extends TestCase {
|
|||
assertEquals(MathUtils.binomialCoefficient(0, 0), 1);
|
||||
}
|
||||
|
||||
public void testAddAndCheck() {
|
||||
int big = Integer.MAX_VALUE;
|
||||
int bigNeg = Integer.MIN_VALUE;
|
||||
assertEquals(big, MathUtils.addAndCheck(big, 0));
|
||||
try {
|
||||
MathUtils.addAndCheck(big, 1);
|
||||
fail("Expecting ArithmeticException");
|
||||
} catch (ArithmeticException ex) {
|
||||
}
|
||||
try {
|
||||
MathUtils.addAndCheck(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);
|
||||
}
|
||||
|
||||
private void testAddAndCheckLongFailure(long a, long b) {
|
||||
try {
|
||||
MathUtils.addAndCheck(a, b);
|
||||
fail("Expecting ArithmeticException");
|
||||
} catch (ArithmeticException ex) {
|
||||
// success
|
||||
}
|
||||
}
|
||||
|
||||
public void testBinomialCoefficient() {
|
||||
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));
|
||||
}
|
||||
for (int i = 0; i < 7; 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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
@ -161,17 +176,44 @@ public final class MathUtilsTest extends TestCase {
|
|||
;
|
||||
}
|
||||
double x = MathUtils.binomialCoefficientDouble(1030, 515);
|
||||
assertTrue("expecting infinite binomial coefficient",
|
||||
Double.isInfinite(x));
|
||||
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 + "! ", (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);
|
||||
|
@ -203,254 +245,7 @@ public final class MathUtilsTest extends TestCase {
|
|||
} catch (ArithmeticException ex) {
|
||||
;
|
||||
}
|
||||
assertTrue("expecting infinite factorial value",
|
||||
Double.isInfinite(MathUtils.factorialDouble(171)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
*/
|
||||
|
||||
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++;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) );
|
||||
}
|
||||
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 testSignFloat() {
|
||||
float delta = 0.0F ;
|
||||
assertEquals( 1.0F, MathUtils.indicator( 2.0F ), delta ) ;
|
||||
assertEquals( -1.0F, MathUtils.indicator( -2.0F ), delta ) ;
|
||||
}
|
||||
|
||||
public void testSignByte() {
|
||||
assertEquals( (byte)1, MathUtils.indicator( (byte)2 ) ) ;
|
||||
assertEquals( (byte)(-1), MathUtils.indicator( (byte)(-2) ) ) ;
|
||||
}
|
||||
|
||||
public void testSignShort() {
|
||||
assertEquals( (short)1, MathUtils.indicator( (short)2 ) ) ;
|
||||
assertEquals( (short)(-1), MathUtils.indicator( (short)(-2) ) ) ;
|
||||
}
|
||||
|
||||
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 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]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
assertTrue("expecting infinite factorial value", Double.isInfinite(MathUtils.factorialDouble(171)));
|
||||
}
|
||||
|
||||
public void testGcd() {
|
||||
|
@ -476,6 +271,68 @@ public final class MathUtilsTest extends TestCase {
|
|||
assertEquals(1, MathUtils.gcd(-a, -c));
|
||||
}
|
||||
|
||||
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]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 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 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 testIndicatorShort() {
|
||||
assertEquals((short)1, MathUtils.indicator((short)2));
|
||||
assertEquals((short)1, MathUtils.indicator((short)0));
|
||||
assertEquals((short)(-1), MathUtils.indicator((short)(-2)));
|
||||
}
|
||||
|
||||
public void testLcm() {
|
||||
int a = 30;
|
||||
int b = 50;
|
||||
|
@ -497,112 +354,59 @@ public final class MathUtilsTest extends TestCase {
|
|||
// 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) {
|
||||
}
|
||||
try {
|
||||
MathUtils.mulAndCheck(bigNeg, 2);
|
||||
fail("Expecting ArithmeticException");
|
||||
} catch (ArithmeticException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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 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 testNextAfter() {
|
||||
|
@ -668,6 +472,18 @@ public final class MathUtilsTest extends TestCase {
|
|||
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -676,8 +492,7 @@ public final class MathUtilsTest extends TestCase {
|
|||
|
||||
// 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.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);
|
||||
|
@ -776,4 +591,189 @@ public final class MathUtilsTest extends TestCase {
|
|||
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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -98,6 +98,10 @@ Commons Math Release Notes</title>
|
|||
<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.
|
||||
|
|
Loading…
Reference in New Issue