You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by lu...@apache.org on 2014/07/21 18:38:45 UTC
svn commit: r1612346 - in /commons/proper/math/trunk/src:
main/java/org/apache/commons/math3/stat/descriptive/rank/Percentile.java
test/java/org/apache/commons/math3/stat/descriptive/rank/PercentileTest.java
Author: luc
Date: Mon Jul 21 16:38:45 2014
New Revision: 1612346
URL: http://svn.apache.org/r1612346
Log:
Refactored removeAndSlice, replaceAndSlice.
Thansk to Venkatesha Murthy TS for the patch.
JIRA: MATH-1120
Modified:
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/stat/descriptive/rank/Percentile.java
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/stat/descriptive/rank/PercentileTest.java
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/stat/descriptive/rank/Percentile.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/stat/descriptive/rank/Percentile.java?rev=1612346&r1=1612345&r2=1612346&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/stat/descriptive/rank/Percentile.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/stat/descriptive/rank/Percentile.java Mon Jul 21 16:38:45 2014
@@ -17,9 +17,8 @@
package org.apache.commons.math3.stat.descriptive.rank;
import java.io.Serializable;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.List;
+import java.util.BitSet;
import org.apache.commons.math3.exception.MathIllegalArgumentException;
import org.apache.commons.math3.exception.MathUnsupportedOperationException;
@@ -34,6 +33,7 @@ import org.apache.commons.math3.util.Mat
import org.apache.commons.math3.util.MathUtils;
import org.apache.commons.math3.util.MedianOf3PivotingStrategy;
import org.apache.commons.math3.util.PivotingStrategyInterface;
+import org.apache.commons.math3.util.Precision;
/**
* Provides percentile computation.
@@ -492,13 +492,12 @@ public class Percentile extends Abstract
*/
private static double[] replaceAndSlice(final double[] values,
final int begin, final int length,
- final double original, final double replacement) {
+ final double original,
+ final double replacement) {
final double[] temp = copyOf(values, begin, length);
for(int i = 0; i < length; i++) {
- //First a quick check on if both are NaN
- final boolean areBothNaNs = Double.isNaN(original) &&
- Double.isNaN(values[i]);
- temp[i] = (areBothNaNs || Double.compare(original, temp[i]) == 0) ? replacement : temp[i];
+ temp[i] = Precision.equalsIncludingNaN(original, temp[i]) ?
+ replacement : temp[i];
}
return temp;
}
@@ -516,38 +515,34 @@ public class Percentile extends Abstract
final int begin, final int length,
final double removedValue) {
MathArrays.verifyValues(values, begin, length);
-
- final double [] temp;
- final List<Integer> occurencesToRemove = new ArrayList<Integer>();
-
- //First register for all occurrences of removable value
- for (int i= begin; i < begin + length; i++) {
- //Do a quick check on if both are NaN
- final boolean areBothNaNs = Double.isNaN(removedValue) && Double.isNaN(values[i]);
- if (areBothNaNs || Double.compare(values[i], removedValue) == 0) {
- occurencesToRemove.add(i);
+ final double[] temp;
+ //BitSet(length) to indicate where the removedValue is located
+ final BitSet bits = new BitSet(length);
+ for (int i = begin; i < begin+length; i++) {
+ if (Precision.equalsIncludingNaN(removedValue, values[i])) {
+ bits.set(i - begin);
}
}
-
- //Next, get the slice of array with removable peeled off.
- if (occurencesToRemove.isEmpty()) {
- temp = copyOf(values,begin,length); //just do a copy
- } else if (occurencesToRemove.size() == length) {
- temp = new double[0]; //all were NaNs; so return a zero length
- } else /*if(occurancesToRemove.size()>0)*/ {
- temp = new double[length - occurencesToRemove.size()];
- int start = begin;
- int destStart = 0;
- // copy off the retained ones in steps
- for (final int current: occurencesToRemove) {
- final int numsToMove = current - start;
- System.arraycopy(values, start, temp, destStart, numsToMove);
- destStart += numsToMove;
- start = current + 1;
+ //Check if empty then create a new copy
+ if (bits.isEmpty()) {
+ temp = copyOf(values, begin, length); // Nothing removed, just copy
+ } else if(bits.cardinality() == length){
+ temp = new double[0]; // All removed, just empty
+ }else { // Some removable, so new
+ temp = new double[length - bits.cardinality()];
+ int start = begin; //start index from source array (i.e values)
+ int dest = 0; //dest index in destination array(i.e temp)
+ int nextOne = -1; //nextOne is the index of bit set of next one
+ int bitSetPtr = 0; //bitSetPtr is start index pointer of bitset
+ while ((nextOne = bits.nextSetBit(bitSetPtr)) != -1) {
+ final int lengthToCopy = nextOne - bitSetPtr;
+ System.arraycopy(values, start, temp, dest, lengthToCopy);
+ dest += lengthToCopy;
+ start = begin + (bitSetPtr = bits.nextClearBit(nextOne));
}
- //Copy any residue past start index till length
- if (start < length) {
- System.arraycopy(values,start,temp,destStart,length-start);
+ //Copy any residue past start index till begin+length
+ if (start < begin + length) {
+ System.arraycopy(values,start,temp,dest,begin + length - start);
}
}
return temp;
Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/stat/descriptive/rank/PercentileTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/stat/descriptive/rank/PercentileTest.java?rev=1612346&r1=1612345&r2=1612346&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/stat/descriptive/rank/PercentileTest.java (original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/stat/descriptive/rank/PercentileTest.java Mon Jul 21 16:38:45 2014
@@ -786,6 +786,18 @@ public class PercentileTest extends Univ
Assert.assertEquals(2d,new Percentile(50d).withEstimationType(Percentile.EstimationType.R_1).withNaNStrategy(NaNStrategy.REMOVED).evaluate(specialValues),0d);
Assert.assertEquals(Double.NaN,new Percentile(50d).withEstimationType(Percentile.EstimationType.R_5).withNaNStrategy(NaNStrategy.REMOVED).evaluate(new double[] {Double.NaN,Double.NaN,Double.NaN}),0d);
Assert.assertEquals(50d,new Percentile(50d).withEstimationType(Percentile.EstimationType.R_7).withNaNStrategy(NaNStrategy.MINIMAL).evaluate(new double[] {50d,50d,50d},1,2),0d);
+
+ specialValues = new double[] { 0d, 1d, 2d, 3d, 4d, Double.NaN, Double.NaN };
+ Assert.assertEquals(3.5,new Percentile().evaluate(specialValues, 3, 4),0d);
+ Assert.assertEquals(4d,new Percentile().evaluate(specialValues, 4, 3),0d);
+ Assert.assertTrue(Double.isNaN(new Percentile().evaluate(specialValues, 5, 2)));
+
+ specialValues = new double[] { 0d, 1d, 2d, 3d, 4d, Double.NaN, Double.NaN, 5d, 6d };
+ Assert.assertEquals(4.5,new Percentile().evaluate(specialValues, 3, 6),0d);
+ Assert.assertEquals(5d,new Percentile().evaluate(specialValues, 4, 5),0d);
+ Assert.assertTrue(Double.isNaN(new Percentile().evaluate(specialValues, 5, 2)));
+ Assert.assertTrue(Double.isNaN(new Percentile().evaluate(specialValues, 5, 1)));
+ Assert.assertEquals(5.5,new Percentile().evaluate(specialValues, 5, 4),0d);
}
// Some NaNStrategy specific testing
@@ -796,7 +808,7 @@ public class PercentileTest extends Univ
new Percentile(50d).
withEstimationType(Percentile.EstimationType.R_9).
withNaNStrategy(NaNStrategy.FAILED).
- evaluate(specialValues, 3, 3);
+ evaluate(specialValues);
}
@Test