Partially fixing MATH-370 (full resolution is delayed to a major release).

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@952949 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Gilles Sadowski 2010-06-09 10:41:26 +00:00
parent 6f54422e96
commit 4039a14460
8 changed files with 237 additions and 65 deletions

View File

@ -165,8 +165,8 @@ public abstract class AbstractStorelessUnivariateStatistic
return false; return false;
} }
AbstractStorelessUnivariateStatistic stat = (AbstractStorelessUnivariateStatistic) object; AbstractStorelessUnivariateStatistic stat = (AbstractStorelessUnivariateStatistic) object;
return MathUtils.equals(stat.getResult(), this.getResult()) && return MathUtils.equalsIncludingNaN(stat.getResult(), this.getResult()) &&
MathUtils.equals(stat.getN(), this.getN()); MathUtils.equalsIncludingNaN(stat.getN(), this.getN());
} }
/** /**

View File

@ -369,14 +369,14 @@ public class MultivariateSummaryStatistics
return false; return false;
} }
MultivariateSummaryStatistics stat = (MultivariateSummaryStatistics) object; MultivariateSummaryStatistics stat = (MultivariateSummaryStatistics) object;
return MathUtils.equals(stat.getGeometricMean(), getGeometricMean()) && return MathUtils.equalsIncludingNaN(stat.getGeometricMean(), getGeometricMean()) &&
MathUtils.equals(stat.getMax(), getMax()) && MathUtils.equalsIncludingNaN(stat.getMax(), getMax()) &&
MathUtils.equals(stat.getMean(), getMean()) && MathUtils.equalsIncludingNaN(stat.getMean(), getMean()) &&
MathUtils.equals(stat.getMin(), getMin()) && MathUtils.equalsIncludingNaN(stat.getMin(), getMin()) &&
MathUtils.equals(stat.getN(), getN()) && MathUtils.equalsIncludingNaN(stat.getN(), getN()) &&
MathUtils.equals(stat.getSum(), getSum()) && MathUtils.equalsIncludingNaN(stat.getSum(), getSum()) &&
MathUtils.equals(stat.getSumSq(), getSumSq()) && MathUtils.equalsIncludingNaN(stat.getSumSq(), getSumSq()) &&
MathUtils.equals(stat.getSumLog(), getSumLog()) && MathUtils.equalsIncludingNaN(stat.getSumLog(), getSumLog()) &&
stat.getCovariance().equals( getCovariance()); stat.getCovariance().equals( getCovariance());
} }

View File

@ -135,12 +135,12 @@ public class StatisticalSummaryValues implements Serializable,
return false; return false;
} }
StatisticalSummaryValues stat = (StatisticalSummaryValues) object; StatisticalSummaryValues stat = (StatisticalSummaryValues) object;
return MathUtils.equals(stat.getMax(), getMax()) && return MathUtils.equalsIncludingNaN(stat.getMax(), getMax()) &&
MathUtils.equals(stat.getMean(), getMean()) && MathUtils.equalsIncludingNaN(stat.getMean(), getMean()) &&
MathUtils.equals(stat.getMin(), getMin()) && MathUtils.equalsIncludingNaN(stat.getMin(), getMin()) &&
MathUtils.equals(stat.getN(), getN()) && MathUtils.equalsIncludingNaN(stat.getN(), getN()) &&
MathUtils.equals(stat.getSum(), getSum()) && MathUtils.equalsIncludingNaN(stat.getSum(), getSum()) &&
MathUtils.equals(stat.getVariance(), getVariance()); MathUtils.equalsIncludingNaN(stat.getVariance(), getVariance());
} }
/** /**

View File

@ -360,14 +360,14 @@ public class SummaryStatistics implements StatisticalSummary, Serializable {
return false; return false;
} }
SummaryStatistics stat = (SummaryStatistics)object; SummaryStatistics stat = (SummaryStatistics)object;
return MathUtils.equals(stat.getGeometricMean(), getGeometricMean()) && return MathUtils.equalsIncludingNaN(stat.getGeometricMean(), getGeometricMean()) &&
MathUtils.equals(stat.getMax(), getMax()) && MathUtils.equalsIncludingNaN(stat.getMax(), getMax()) &&
MathUtils.equals(stat.getMean(), getMean()) && MathUtils.equalsIncludingNaN(stat.getMean(), getMean()) &&
MathUtils.equals(stat.getMin(), getMin()) && MathUtils.equalsIncludingNaN(stat.getMin(), getMin()) &&
MathUtils.equals(stat.getN(), getN()) && MathUtils.equalsIncludingNaN(stat.getN(), getN()) &&
MathUtils.equals(stat.getSum(), getSum()) && MathUtils.equalsIncludingNaN(stat.getSum(), getSum()) &&
MathUtils.equals(stat.getSumsq(), getSumsq()) && MathUtils.equalsIncludingNaN(stat.getSumsq(), getSumsq()) &&
MathUtils.equals(stat.getVariance(), getVariance()); MathUtils.equalsIncludingNaN(stat.getVariance(), getVariance());
} }
/** /**

View File

@ -403,36 +403,68 @@ public final class MathUtils {
} }
/** /**
* Returns true iff both arguments are NaN or neither is NaN and they are * Returns true iff they are equal as defined by
* equal * {@link #equals(double,double,int) this method}.
* *
* @param x first value * @param x first value
* @param y second value * @param y second value
* @return true if the values are equal or both are NaN * @return {@code true} if the values are equal.
* @deprecated This method considers that {@code NaN == NaN}. In release
* 3.0, the semantics will change in order to comply with IEEE754 where it
* is specified that {@code NaN != NaN}.
* New methods have been added for those cases wher the old semantics is
* useful (see e.g. {@link equalsIncludingNaN(double,double)
* equalsIncludingNaN}.
*/ */
public static boolean equals(double x, double y) { public static boolean equals(double x, double y) {
return (Double.isNaN(x) && Double.isNaN(y)) || x == y; return (Double.isNaN(x) && Double.isNaN(y)) || x == y;
} }
/** /**
* Returns true iff both arguments are equal or within the range of allowed * Returns true if both arguments are NaN or neither is NaN and they are
* error (inclusive). * equal as defined by {@link #equals(double,double) this method}.
* <p>
* Two NaNs are considered equals, as are two infinities with same sign.
* </p>
* *
* @param x first value * @param x first value
* @param y second value * @param y second value
* @param eps the amount of absolute error to allow * @return {@code true} if the values are equal or both are NaN.
* @return true if the values are equal or within range of each other
*/ */
public static boolean equals(double x, double y, double eps) { public static boolean equalsIncludingNaN(double x, double y) {
return equals(x, y) || (Math.abs(y - x) <= eps); return (Double.isNaN(x) && Double.isNaN(y)) || equals(x, y, 1);
} }
/** /**
* Returns true iff both arguments are equal or within the range of allowed * Returns true if both arguments are equal or within the range of allowed
* error (inclusive). * error (inclusive).
*
* @param x first value
* @param y second value
* @param eps the amount of absolute error to allow.
* @return {@code true} if the values are equal or within range of each other.
*/
public static boolean equals(double x, double y, double eps) {
return equals(x, y, 1) || Math.abs(y - x) <= eps;
}
/**
* Returns true if both arguments are NaN or are equal or within the range
* of allowed error (inclusive).
*
* @param x first value
* @param y second value
* @param eps the amount of absolute error to allow.
* @return {@code true} if the values are equal or within range of each other,
* or both are NaN.
*/
public static boolean equalsIncludingNaN(double x, double y, double eps) {
return equalsIncludingNaN(x, y) || (Math.abs(y - x) <= eps);
}
/**
* Returns true if both arguments are equal or within the range of allowed
* error (inclusive).
* Two float numbers are considered equal if there are {@code (maxUlps - 1)}
* (or less) floating point numbers between them (i.e. two adjacent floating
* point numbers are considered equal.
* Adapted from <a * Adapted from <a
* href="http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm"> * href="http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm">
* Bruce Dawson</a> * Bruce Dawson</a>
@ -442,11 +474,11 @@ public final class MathUtils {
* @param maxUlps {@code (maxUlps - 1)} is the number of floating point * @param maxUlps {@code (maxUlps - 1)} is the number of floating point
* values between {@code x} and {@code y}. * values between {@code x} and {@code y}.
* @return {@code true} if there are less than {@code maxUlps} floating * @return {@code true} if there are less than {@code maxUlps} floating
* point values between {@code x} and {@code y} * point values between {@code x} and {@code y}.
*/ */
public static boolean equals(double x, double y, int maxUlps) { public static boolean equals(double x, double y, int maxUlps) {
// Check that "maxUlps" is non-negative and small enough so that the // Check that "maxUlps" is non-negative and small enough so that
// default NAN won't compare as equal to anything. // NaN won't compare as equal to anything (except another NaN).
assert maxUlps > 0 && maxUlps < NAN_GAP; assert maxUlps > 0 && maxUlps < NAN_GAP;
long xInt = Double.doubleToLongBits(x); long xInt = Double.doubleToLongBits(x);
@ -460,18 +492,41 @@ public final class MathUtils {
yInt = SGN_MASK - yInt; yInt = SGN_MASK - yInt;
} }
return Math.abs(xInt - yInt) <= maxUlps; final boolean isEqual = (Math.abs(xInt - yInt) <= maxUlps);
return isEqual && !Double.isNaN(x) && !Double.isNaN(y);
} }
/** /**
* Returns true iff both arguments are null or have same dimensions * Returns true if both arguments are NaN or if they are equal as defined
* and all their elements are {@link #equals(double,double) equals} * by {@link #equals(double,double,int) this method}.
*
* @param x first value
* @param y second value
* @param maxUlps {@code (maxUlps - 1)} is the number of floating point
* values between {@code x} and {@code y}.
* @return {@code true} if both arguments are NaN or if there are less than
* {@code maxUlps} floating point values between {@code x} and {@code y}.
*/
public static boolean equalsIncludingNaN(double x, double y, int maxUlps) {
return (Double.isNaN(x) && Double.isNaN(y)) || equals(x, y, maxUlps);
}
/**
* Returns true iff both arguments are null or have same dimensions and all
* their elements are equal as defined by
* {@link #equals(double,double) this method}.
* *
* @param x first array * @param x first array
* @param y second array * @param y second array
* @return true if the values are both null or have same dimension * @return true if the values are both null or have same dimension
* and equal elements * and equal elements.
* @since 1.2 * @deprecated This method considers that {@code NaN == NaN}. In release
* 3.0, the semantics will change in order to comply with IEEE754 where it
* is specified that {@code NaN != NaN}.
* New methods have been added for those cases wher the old semantics is
* useful (see e.g. {@link equalsIncludingNaN(double[],double[])
* equalsIncludingNaN}.
*/ */
public static boolean equals(double[] x, double[] y) { public static boolean equals(double[] x, double[] y) {
if ((x == null) || (y == null)) { if ((x == null) || (y == null)) {
@ -488,6 +543,31 @@ public final class MathUtils {
return true; return true;
} }
/**
* Returns true iff both arguments are null or have same dimensions and all
* their elements are equal as defined by
* {@link #equalsIncludingNaN(double,double) this method}.
*
* @param x first array
* @param y second array
* @return true if the values are both null or have same dimension and
* equal elements
*/
public static boolean equalsIncludingNaN(double[] x, double[] y) {
if ((x == null) || (y == null)) {
return !((x == null) ^ (y == null));
}
if (x.length != y.length) {
return false;
}
for (int i = 0; i < x.length; ++i) {
if (!equalsIncludingNaN(x[i], y[i])) {
return false;
}
}
return true;
}
/** /**
* Returns n!. Shorthand for <code>n</code> <a * Returns n!. Shorthand for <code>n</code> <a
* href="http://mathworld.wolfram.com/Factorial.html"> Factorial</a>, the * href="http://mathworld.wolfram.com/Factorial.html"> Factorial</a>, the

View File

@ -52,6 +52,11 @@ The <action> type attribute can be add,update,fix,remove.
If the output is not quite correct, check for invisible trailing spaces! If the output is not quite correct, check for invisible trailing spaces!
--> -->
<release version="2.2" date="TBD" description="TBD"> <release version="2.2" date="TBD" description="TBD">
<action dev="erans" type="update" issue="MATH-370">
Added new "equalsIncludingNaN" methods that have the same semantics as the old "equals" methods.
These are deprecated, and their semantics will be modified (in the next major release) such that
NaNs are not considered equal (to be more compliant with IEEE754).
</action>
<action dev="luc" type="fix" issue="MATH-352" > <action dev="luc" type="fix" issue="MATH-352" >
Added a setQRRankingThreshold method to Levenberg-Marquardt optimizer to improve robustness Added a setQRRankingThreshold method to Levenberg-Marquardt optimizer to improve robustness
of rank determination. of rank determination.

View File

@ -210,11 +210,11 @@ public class DescriptiveStatisticsTest extends TestCase {
dstat.addValue(i); dstat.addValue(i);
} }
assertTrue(MathUtils.equals(mean1, dstat.getMean())); assertTrue(MathUtils.equalsIncludingNaN(mean1, dstat.getMean()));
dstat.replaceMostRecentValue(0); dstat.replaceMostRecentValue(0);
assertTrue(MathUtils.equals(mean2, dstat.getMean())); assertTrue(MathUtils.equalsIncludingNaN(mean2, dstat.getMean()));
dstat.removeMostRecentValue(); dstat.removeMostRecentValue();
assertTrue(MathUtils.equals(mean3, dstat.getMean())); assertTrue(MathUtils.equalsIncludingNaN(mean3, dstat.getMean()));
} }

View File

@ -314,7 +314,7 @@ public final class MathUtilsTest extends TestCase {
assertTrue(Double.isNaN(MathUtils.cosh(Double.NaN))); assertTrue(Double.isNaN(MathUtils.cosh(Double.NaN)));
} }
public void testEquals() { public void testEqualsIncludingNaN() {
double[] testArray = { double[] testArray = {
Double.NaN, Double.NaN,
Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY,
@ -324,11 +324,11 @@ public final class MathUtilsTest extends TestCase {
for (int i = 0; i < testArray.length; i++) { for (int i = 0; i < testArray.length; i++) {
for (int j = 0; j < testArray.length; j++) { for (int j = 0; j < testArray.length; j++) {
if (i == j) { if (i == j) {
assertTrue(MathUtils.equals(testArray[i], testArray[j])); assertTrue(MathUtils.equalsIncludingNaN(testArray[i], testArray[j]));
assertTrue(MathUtils.equals(testArray[j], testArray[i])); assertTrue(MathUtils.equalsIncludingNaN(testArray[j], testArray[i]));
} else { } else {
assertTrue(!MathUtils.equals(testArray[i], testArray[j])); assertTrue(!MathUtils.equalsIncludingNaN(testArray[i], testArray[j]));
assertTrue(!MathUtils.equals(testArray[j], testArray[i])); assertTrue(!MathUtils.equalsIncludingNaN(testArray[j], testArray[i]));
} }
} }
} }
@ -338,7 +338,7 @@ public final class MathUtilsTest extends TestCase {
assertTrue(MathUtils.equals(153.0000, 153.0000, .0625)); assertTrue(MathUtils.equals(153.0000, 153.0000, .0625));
assertTrue(MathUtils.equals(153.0000, 153.0625, .0625)); assertTrue(MathUtils.equals(153.0000, 153.0625, .0625));
assertTrue(MathUtils.equals(152.9375, 153.0000, .0625)); assertTrue(MathUtils.equals(152.9375, 153.0000, .0625));
assertTrue(MathUtils.equals(Double.NaN, Double.NaN, 1.0)); assertFalse(MathUtils.equals(Double.NaN, Double.NaN, 1.0));
assertTrue(MathUtils.equals(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0)); assertTrue(MathUtils.equals(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0));
assertTrue(MathUtils.equals(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1.0)); assertTrue(MathUtils.equals(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1.0));
assertFalse(MathUtils.equals(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0)); assertFalse(MathUtils.equals(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0));
@ -346,18 +346,44 @@ public final class MathUtilsTest extends TestCase {
assertFalse(MathUtils.equals(152.9374, 153.0000, .0625)); assertFalse(MathUtils.equals(152.9374, 153.0000, .0625));
} }
public void testEqualsWithAllowedUlps() { public void testEqualsIncludingNaNWithAllowedDelta() {
assertTrue(MathUtils.equals(153, 153, 1)); assertTrue(MathUtils.equalsIncludingNaN(153.0000, 153.0000, .0625));
assertTrue(MathUtils.equalsIncludingNaN(153.0000, 153.0625, .0625));
assertTrue(MathUtils.equalsIncludingNaN(152.9375, 153.0000, .0625));
assertTrue(MathUtils.equalsIncludingNaN(Double.NaN, Double.NaN, 1.0));
assertTrue(MathUtils.equalsIncludingNaN(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0));
assertTrue(MathUtils.equalsIncludingNaN(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1.0));
assertFalse(MathUtils.equalsIncludingNaN(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0));
assertFalse(MathUtils.equalsIncludingNaN(153.0000, 153.0625, .0624));
assertFalse(MathUtils.equalsIncludingNaN(152.9374, 153.0000, .0625));
}
assertTrue(MathUtils.equals(153, 153.00000000000003, 1)); public void testEqualsWithAllowedUlps() {
assertFalse(MathUtils.equals(153, 153.00000000000006, 1)); assertTrue(MathUtils.equals(0.0, -0.0, 1));
assertTrue(MathUtils.equals(153, 152.99999999999997, 1));
assertTrue(MathUtils.equals(1.0, 1 + Math.ulp(1d), 1));
assertFalse(MathUtils.equals(1.0, 1 + 2 * Math.ulp(1d), 1));
final double nUp1 = Math.nextUp(1d);
final double nnUp1 = Math.nextUp(nUp1);
assertTrue(MathUtils.equals(1.0, nUp1, 1));
assertTrue(MathUtils.equals(nUp1, nnUp1, 1));
assertFalse(MathUtils.equals(1.0, nnUp1, 1));
assertTrue(MathUtils.equals(0.0, Math.ulp(0d), 1));
assertTrue(MathUtils.equals(0.0, -Math.ulp(0d), 1));
assertTrue(MathUtils.equals(153.0, 153.0, 1));
assertTrue(MathUtils.equals(153.0, 153.00000000000003, 1));
assertFalse(MathUtils.equals(153.0, 153.00000000000006, 1));
assertTrue(MathUtils.equals(153.0, 152.99999999999997, 1));
assertFalse(MathUtils.equals(153, 152.99999999999994, 1)); assertFalse(MathUtils.equals(153, 152.99999999999994, 1));
assertTrue(MathUtils.equals(-128, -127.99999999999999, 1)); assertTrue(MathUtils.equals(-128.0, -127.99999999999999, 1));
assertFalse(MathUtils.equals(-128, -127.99999999999997, 1)); assertFalse(MathUtils.equals(-128.0, -127.99999999999997, 1));
assertTrue(MathUtils.equals(-128, -128.00000000000003, 1)); assertTrue(MathUtils.equals(-128.0, -128.00000000000003, 1));
assertFalse(MathUtils.equals(-128, -128.00000000000006, 1)); assertFalse(MathUtils.equals(-128.0, -128.00000000000006, 1));
assertTrue(MathUtils.equals(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1)); assertTrue(MathUtils.equals(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1));
assertTrue(MathUtils.equals(Double.MAX_VALUE, Double.POSITIVE_INFINITY, 1)); assertTrue(MathUtils.equals(Double.MAX_VALUE, Double.POSITIVE_INFINITY, 1));
@ -365,12 +391,53 @@ public final class MathUtilsTest extends TestCase {
assertTrue(MathUtils.equals(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1)); assertTrue(MathUtils.equals(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1));
assertTrue(MathUtils.equals(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY, 1)); assertTrue(MathUtils.equals(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY, 1));
assertFalse(MathUtils.equals(Double.NaN, Double.NaN, 1));
assertTrue(MathUtils.equals(Double.NaN, Double.NaN, 1));
assertFalse(MathUtils.equals(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 100000)); assertFalse(MathUtils.equals(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 100000));
} }
public void testEqualsIncludingNaNWithAllowedUlps() {
assertTrue(MathUtils.equalsIncludingNaN(0.0, -0.0, 1));
assertTrue(MathUtils.equalsIncludingNaN(1.0, 1 + Math.ulp(1d), 1));
assertFalse(MathUtils.equalsIncludingNaN(1.0, 1 + 2 * Math.ulp(1d), 1));
final double nUp1 = Math.nextUp(1d);
final double nnUp1 = Math.nextUp(nUp1);
assertTrue(MathUtils.equalsIncludingNaN(1.0, nUp1, 1));
assertTrue(MathUtils.equalsIncludingNaN(nUp1, nnUp1, 1));
assertFalse(MathUtils.equalsIncludingNaN(1.0, nnUp1, 1));
assertTrue(MathUtils.equalsIncludingNaN(0.0, Math.ulp(0d), 1));
assertTrue(MathUtils.equalsIncludingNaN(0.0, -Math.ulp(0d), 1));
assertTrue(MathUtils.equalsIncludingNaN(153.0, 153.0, 1));
assertTrue(MathUtils.equalsIncludingNaN(153.0, 153.00000000000003, 1));
assertFalse(MathUtils.equalsIncludingNaN(153.0, 153.00000000000006, 1));
assertTrue(MathUtils.equalsIncludingNaN(153.0, 152.99999999999997, 1));
assertFalse(MathUtils.equalsIncludingNaN(153, 152.99999999999994, 1));
assertTrue(MathUtils.equalsIncludingNaN(-128.0, -127.99999999999999, 1));
assertFalse(MathUtils.equalsIncludingNaN(-128.0, -127.99999999999997, 1));
assertTrue(MathUtils.equalsIncludingNaN(-128.0, -128.00000000000003, 1));
assertFalse(MathUtils.equalsIncludingNaN(-128.0, -128.00000000000006, 1));
assertTrue(MathUtils.equalsIncludingNaN(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1));
assertTrue(MathUtils.equalsIncludingNaN(Double.MAX_VALUE, Double.POSITIVE_INFINITY, 1));
assertTrue(MathUtils.equalsIncludingNaN(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1));
assertTrue(MathUtils.equalsIncludingNaN(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY, 1));
assertTrue(MathUtils.equalsIncludingNaN(Double.NaN, Double.NaN, 1));
assertFalse(MathUtils.equalsIncludingNaN(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 100000));
}
/**
* @deprecated To be removed in release 3.0 (replaced by {@link
* #testArrayEqualsIncludingNaN()}.
*/
public void testArrayEquals() { public void testArrayEquals() {
assertFalse(MathUtils.equals(new double[] { 1d }, null)); assertFalse(MathUtils.equals(new double[] { 1d }, null));
assertFalse(MathUtils.equals(null, new double[] { 1d })); assertFalse(MathUtils.equals(null, new double[] { 1d }));
@ -392,6 +459,26 @@ public final class MathUtilsTest extends TestCase {
} }
public void testArrayEqualsIncludingNaN() {
assertFalse(MathUtils.equalsIncludingNaN(new double[] { 1d }, null));
assertFalse(MathUtils.equalsIncludingNaN(null, new double[] { 1d }));
assertTrue(MathUtils.equalsIncludingNaN((double[]) null, (double[]) null));
assertFalse(MathUtils.equalsIncludingNaN(new double[] { 1d }, new double[0]));
assertTrue(MathUtils.equalsIncludingNaN(new double[] { 1d }, new double[] { 1d }));
assertTrue(MathUtils.equalsIncludingNaN(new double[] {
Double.NaN, Double.POSITIVE_INFINITY,
Double.NEGATIVE_INFINITY, 1d, 0d
}, new double[] {
Double.NaN, Double.POSITIVE_INFINITY,
Double.NEGATIVE_INFINITY, 1d, 0d
}));
assertFalse(MathUtils.equalsIncludingNaN(new double[] { Double.POSITIVE_INFINITY },
new double[] { Double.NEGATIVE_INFINITY }));
assertFalse(MathUtils.equalsIncludingNaN(new double[] { 1d },
new double[] { MathUtils.nextAfter(MathUtils.nextAfter(1d, 2d), 2d) }));
}
public void testFactorial() { public void testFactorial() {
for (int i = 1; i < 21; i++) { for (int i = 1; i < 21; i++) {
assertEquals(i + "! ", factorial(i), MathUtils.factorial(i)); assertEquals(i + "! ", factorial(i), MathUtils.factorial(i));