diff --git a/src/main/java/org/apache/commons/math/util/MathUtils.java b/src/main/java/org/apache/commons/math/util/MathUtils.java
index 46368dc9f..ad77a56eb 100644
--- a/src/main/java/org/apache/commons/math/util/MathUtils.java
+++ b/src/main/java/org/apache/commons/math/util/MathUtils.java
@@ -1621,9 +1621,9 @@ public final class MathUtils {
* @return the L2 distance between the two points
*/
public static double distance(int[] p1, int[] p2) {
- int sum = 0;
+ double sum = 0;
for (int i = 0; i < p1.length; i++) {
- final int dp = p1[i] - p2[i];
+ final double dp = p1[i] - p2[i];
sum += dp * dp;
}
return Math.sqrt(sum);
diff --git a/src/site/xdoc/changes.xml b/src/site/xdoc/changes.xml
index 3c94d22e9..bd1f4d344 100644
--- a/src/site/xdoc/changes.xml
+++ b/src/site/xdoc/changes.xml
@@ -39,6 +39,11 @@ The type attribute can be add,update,fix,remove.
+
+ Fixed an overflow error in MathUtils.distance that was causing KMeansPlusPlusClusterer
+ to fail with a NullPointerException when component distances between points
+ exceeded Integer.MAXVALUE.
+
Added generationsEvolved property to GeneticAlgorithm to track the number of generations
evolved by the evolve() method before reaching the StoppingCondition.
diff --git a/src/test/java/org/apache/commons/math/stat/clustering/KMeansPlusPlusClustererTest.java b/src/test/java/org/apache/commons/math/stat/clustering/KMeansPlusPlusClustererTest.java
index da1d8a93d..dfe89adef 100644
--- a/src/test/java/org/apache/commons/math/stat/clustering/KMeansPlusPlusClustererTest.java
+++ b/src/test/java/org/apache/commons/math/stat/clustering/KMeansPlusPlusClustererTest.java
@@ -93,5 +93,27 @@ public class KMeansPlusPlusClustererTest {
assertTrue(cluster3Found);
}
+
+ /**
+ * JIRA: MATH-305
+ *
+ * Two points, one cluster, one iteration
+ */
+ @Test
+ public void testPerformClusterAnalysisDegenerate() {
+ KMeansPlusPlusClusterer transformer = new KMeansPlusPlusClusterer(
+ new Random(1746432956321l));
+ EuclideanIntegerPoint[] points = new EuclideanIntegerPoint[] {
+ new EuclideanIntegerPoint(new int[] { 1959, 325100 }),
+ new EuclideanIntegerPoint(new int[] { 1960, 373200 }), };
+ List> clusters = transformer.cluster(Arrays.asList(points), 1, 1);
+ assertEquals(1, clusters.size());
+ assertEquals(2, (clusters.get(0).getPoints().size()));
+ EuclideanIntegerPoint pt1 = new EuclideanIntegerPoint(new int[] { 1959, 325100 });
+ EuclideanIntegerPoint pt2 = new EuclideanIntegerPoint(new int[] { 1960, 373200 });
+ assertTrue(clusters.get(0).getPoints().contains(pt1));
+ assertTrue(clusters.get(0).getPoints().contains(pt2));
+
+ }
}