[MATH-1068] Avoid overflow in Kendalls correlation for large input arrays.

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1546840 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Thomas Neidhart 2013-12-01 19:17:22 +00:00
parent aff82362cf
commit b12610d35e
3 changed files with 17 additions and 3 deletions

View File

@ -51,6 +51,9 @@ If the output is not quite correct, check for invisible trailing spaces!
</properties>
<body>
<release version="3.3" date="TBD" description="TBD">
<action dev="tn" type="fix" issue="MATH-1068" due-to="Gal Lalouche">
Avoid overflow when calculating Kendall's correlation for large arrays.
</action>
<action dev="erans" type="fix" issue="MATH-1067" due-to="Florian Erhard">
Avoid infinite recursion in "Beta.regularizedBeta" (package "o.a.c.m.special");
</action>

View File

@ -160,7 +160,7 @@ public class KendallsCorrelation {
}
final int n = xArray.length;
final int numPairs = n * (n - 1) / 2;
final long numPairs = n * (n - 1l) / 2l;
@SuppressWarnings("unchecked")
Pair<Double, Double>[] pairs = new Pair[n];
@ -254,7 +254,8 @@ public class KendallsCorrelation {
}
tiedYPairs += consecutiveYTies * (consecutiveYTies - 1) / 2;
int concordantMinusDiscordant = numPairs - tiedXPairs - tiedYPairs + tiedXYPairs - 2 * swaps;
return concordantMinusDiscordant / FastMath.sqrt((numPairs - tiedXPairs) * (numPairs - tiedYPairs));
final long concordantMinusDiscordant = numPairs - tiedXPairs - tiedYPairs + tiedXYPairs - 2 * swaps;
final double nonTiedPairsMultiplied = (numPairs - tiedXPairs) * (double) (numPairs - tiedYPairs);
return concordantMinusDiscordant / FastMath.sqrt(nonTiedPairsMultiplied);
}
}

View File

@ -16,6 +16,8 @@
*/
package org.apache.commons.math3.stat.correlation;
import java.util.Arrays;
import org.apache.commons.math3.TestUtils;
import org.apache.commons.math3.linear.BlockRealMatrix;
import org.apache.commons.math3.linear.RealMatrix;
@ -248,4 +250,12 @@ public class KendallsCorrelationTest extends PearsonsCorrelationTest {
new BlockRealMatrix(expected));
}
@Test
public void testLargeArray() {
// test integer overflow detected in MATH-1068
double[] xArray = new double[100000];
Arrays.fill(xArray, 0, 2500, 1.0);
Assert.assertEquals(1.0, correlation.correlation(xArray, xArray), 1e-6);
}
}