Skip to content

Commit

Permalink
Change Quantiles' compute() methods for multiple indexes to return a …
Browse files Browse the repository at this point in the history
…map with entries in the order in which the indexes were provided in the call to indexes().

Fixes #2989

RELNOTES=`math`: `Quantiles` `compute()` methods which return a `Map` now return a map with entries in the same order in which the indexes were provided.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=272459623
  • Loading branch information
hshankar authored and cpovirk committed Oct 2, 2019
1 parent 188a218 commit 786c3d8
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 26 deletions.
12 changes: 12 additions & 0 deletions android/guava-tests/test/com/google/common/math/QuantilesTest.java
Expand Up @@ -290,6 +290,18 @@ public void testScale_indexes_varargs_compute_integerCollection() {
8, SIXTEEN_SQUARES_DECILE_8);
}

public void testScale_indexes_varargs_compute_indexOrderIsMaintained() {
assertThat(Quantiles.scale(10).indexes(0, 10, 5, 1, 8, 1).compute(SIXTEEN_SQUARES_INTEGERS))
.comparingValuesUsing(QUANTILE_CORRESPONDENCE)
.containsExactly(
0, SIXTEEN_SQUARES_MIN,
10, SIXTEEN_SQUARES_MAX,
5, SIXTEEN_SQUARES_MEDIAN,
1, SIXTEEN_SQUARES_DECILE_1,
8, SIXTEEN_SQUARES_DECILE_8)
.inOrder();
}

public void testScale_indexes_varargs_compute_doubleVarargs() {
double[] dataset = Doubles.toArray(SIXTEEN_SQUARES_DOUBLES);
assertThat(Quantiles.scale(10).indexes(0, 10, 5, 1, 8, 1).compute(dataset))
Expand Down
36 changes: 23 additions & 13 deletions android/guava/src/com/google/common/math/Quantiles.java
Expand Up @@ -27,7 +27,7 @@
import com.google.common.primitives.Ints;
import java.math.RoundingMode;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
Expand Down Expand Up @@ -331,8 +331,10 @@ private ScaleAndIndexes(int scale, int[] indexes) {
* @param dataset the dataset to do the calculation on, which must be non-empty, which will be
* cast to doubles (with any associated lost of precision), and which will not be mutated by
* this call (it is copied instead)
* @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
* the values the corresponding quantile values
* @return an unmodifiable, ordered map of results: the keys will be the specified quantile
* indexes, and the values the corresponding quantile values. When iterating, entries in the
* map are ordered by quantile index in the same order they were passed to the {@code
* indexes} method.
*/
public Map<Integer, Double> compute(Collection<? extends Number> dataset) {
return computeInPlace(Doubles.toArray(dataset));
Expand All @@ -343,8 +345,10 @@ public Map<Integer, Double> compute(Collection<? extends Number> dataset) {
*
* @param dataset the dataset to do the calculation on, which must be non-empty, which will not
* be mutated by this call (it is copied instead)
* @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
* the values the corresponding quantile values
* @return an unmodifiable, ordered map of results: the keys will be the specified quantile
* indexes, and the values the corresponding quantile values. When iterating, entries in the
* map are ordered by quantile index in the same order they were passed to the {@code
* indexes} method.
*/
public Map<Integer, Double> compute(double... dataset) {
return computeInPlace(dataset.clone());
Expand All @@ -356,8 +360,10 @@ public Map<Integer, Double> compute(double... dataset) {
* @param dataset the dataset to do the calculation on, which must be non-empty, which will be
* cast to doubles (with any associated lost of precision), and which will not be mutated by
* this call (it is copied instead)
* @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
* the values the corresponding quantile values
* @return an unmodifiable, ordered map of results: the keys will be the specified quantile
* indexes, and the values the corresponding quantile values. When iterating, entries in the
* map are ordered by quantile index in the same order they were passed to the {@code
* indexes} method.
*/
public Map<Integer, Double> compute(long... dataset) {
return computeInPlace(longsToDoubles(dataset));
Expand All @@ -368,8 +374,10 @@ public Map<Integer, Double> compute(long... dataset) {
*
* @param dataset the dataset to do the calculation on, which must be non-empty, which will be
* cast to doubles, and which will not be mutated by this call (it is copied instead)
* @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
* the values the corresponding quantile values
* @return an unmodifiable, ordered map of results: the keys will be the specified quantile
* indexes, and the values the corresponding quantile values. When iterating, entries in the
* map are ordered by quantile index in the same order they were passed to the {@code
* indexes} method.
*/
public Map<Integer, Double> compute(int... dataset) {
return computeInPlace(intsToDoubles(dataset));
Expand All @@ -380,13 +388,15 @@ public Map<Integer, Double> compute(int... dataset) {
*
* @param dataset the dataset to do the calculation on, which must be non-empty, and which will
* be arbitrarily reordered by this method call
* @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
* the values the corresponding quantile values
* @return an unmodifiable, ordered map of results: the keys will be the specified quantile
* indexes, and the values the corresponding quantile values. When iterating, entries in the
* map are ordered by quantile index in the same order that the indexes were passed to the
* {@code indexes} method.
*/
public Map<Integer, Double> computeInPlace(double... dataset) {
checkArgument(dataset.length > 0, "Cannot calculate quantiles of an empty dataset");
if (containsNaN(dataset)) {
Map<Integer, Double> nanMap = new HashMap<>();
Map<Integer, Double> nanMap = new LinkedHashMap<>();
for (int index : indexes) {
nanMap.put(index, NaN);
}
Expand Down Expand Up @@ -425,7 +435,7 @@ public Map<Integer, Double> computeInPlace(double... dataset) {
sort(requiredSelections, 0, requiredSelectionsCount);
selectAllInPlace(
requiredSelections, 0, requiredSelectionsCount - 1, dataset, 0, dataset.length - 1);
Map<Integer, Double> ret = new HashMap<>();
Map<Integer, Double> ret = new LinkedHashMap<>();
for (int i = 0; i < indexes.length; i++) {
int quotient = quotients[i];
int remainder = remainders[i];
Expand Down
12 changes: 12 additions & 0 deletions guava-tests/test/com/google/common/math/QuantilesTest.java
Expand Up @@ -290,6 +290,18 @@ public void testScale_indexes_varargs_compute_integerCollection() {
8, SIXTEEN_SQUARES_DECILE_8);
}

public void testScale_indexes_varargs_compute_indexOrderIsMaintained() {
assertThat(Quantiles.scale(10).indexes(0, 10, 5, 1, 8, 1).compute(SIXTEEN_SQUARES_INTEGERS))
.comparingValuesUsing(QUANTILE_CORRESPONDENCE)
.containsExactly(
0, SIXTEEN_SQUARES_MIN,
10, SIXTEEN_SQUARES_MAX,
5, SIXTEEN_SQUARES_MEDIAN,
1, SIXTEEN_SQUARES_DECILE_1,
8, SIXTEEN_SQUARES_DECILE_8)
.inOrder();
}

public void testScale_indexes_varargs_compute_doubleVarargs() {
double[] dataset = Doubles.toArray(SIXTEEN_SQUARES_DOUBLES);
assertThat(Quantiles.scale(10).indexes(0, 10, 5, 1, 8, 1).compute(dataset))
Expand Down
36 changes: 23 additions & 13 deletions guava/src/com/google/common/math/Quantiles.java
Expand Up @@ -27,7 +27,7 @@
import com.google.common.primitives.Ints;
import java.math.RoundingMode;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
Expand Down Expand Up @@ -331,8 +331,10 @@ private ScaleAndIndexes(int scale, int[] indexes) {
* @param dataset the dataset to do the calculation on, which must be non-empty, which will be
* cast to doubles (with any associated lost of precision), and which will not be mutated by
* this call (it is copied instead)
* @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
* the values the corresponding quantile values
* @return an unmodifiable, ordered map of results: the keys will be the specified quantile
* indexes, and the values the corresponding quantile values. When iterating, entries in the
* map are ordered by quantile index in the same order they were passed to the {@code
* indexes} method.
*/
public Map<Integer, Double> compute(Collection<? extends Number> dataset) {
return computeInPlace(Doubles.toArray(dataset));
Expand All @@ -343,8 +345,10 @@ public Map<Integer, Double> compute(Collection<? extends Number> dataset) {
*
* @param dataset the dataset to do the calculation on, which must be non-empty, which will not
* be mutated by this call (it is copied instead)
* @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
* the values the corresponding quantile values
* @return an unmodifiable, ordered map of results: the keys will be the specified quantile
* indexes, and the values the corresponding quantile values. When iterating, entries in the
* map are ordered by quantile index in the same order they were passed to the {@code
* indexes} method.
*/
public Map<Integer, Double> compute(double... dataset) {
return computeInPlace(dataset.clone());
Expand All @@ -356,8 +360,10 @@ public Map<Integer, Double> compute(double... dataset) {
* @param dataset the dataset to do the calculation on, which must be non-empty, which will be
* cast to doubles (with any associated lost of precision), and which will not be mutated by
* this call (it is copied instead)
* @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
* the values the corresponding quantile values
* @return an unmodifiable, ordered map of results: the keys will be the specified quantile
* indexes, and the values the corresponding quantile values. When iterating, entries in the
* map are ordered by quantile index in the same order they were passed to the {@code
* indexes} method.
*/
public Map<Integer, Double> compute(long... dataset) {
return computeInPlace(longsToDoubles(dataset));
Expand All @@ -368,8 +374,10 @@ public Map<Integer, Double> compute(long... dataset) {
*
* @param dataset the dataset to do the calculation on, which must be non-empty, which will be
* cast to doubles, and which will not be mutated by this call (it is copied instead)
* @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
* the values the corresponding quantile values
* @return an unmodifiable, ordered map of results: the keys will be the specified quantile
* indexes, and the values the corresponding quantile values. When iterating, entries in the
* map are ordered by quantile index in the same order they were passed to the {@code
* indexes} method.
*/
public Map<Integer, Double> compute(int... dataset) {
return computeInPlace(intsToDoubles(dataset));
Expand All @@ -380,13 +388,15 @@ public Map<Integer, Double> compute(int... dataset) {
*
* @param dataset the dataset to do the calculation on, which must be non-empty, and which will
* be arbitrarily reordered by this method call
* @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
* the values the corresponding quantile values
* @return an unmodifiable, ordered map of results: the keys will be the specified quantile
* indexes, and the values the corresponding quantile values. When iterating, entries in the
* map are ordered by quantile index in the same order that the indexes were passed to the
* {@code indexes} method.
*/
public Map<Integer, Double> computeInPlace(double... dataset) {
checkArgument(dataset.length > 0, "Cannot calculate quantiles of an empty dataset");
if (containsNaN(dataset)) {
Map<Integer, Double> nanMap = new HashMap<>();
Map<Integer, Double> nanMap = new LinkedHashMap<>();
for (int index : indexes) {
nanMap.put(index, NaN);
}
Expand Down Expand Up @@ -425,7 +435,7 @@ public Map<Integer, Double> computeInPlace(double... dataset) {
sort(requiredSelections, 0, requiredSelectionsCount);
selectAllInPlace(
requiredSelections, 0, requiredSelectionsCount - 1, dataset, 0, dataset.length - 1);
Map<Integer, Double> ret = new HashMap<>();
Map<Integer, Double> ret = new LinkedHashMap<>();
for (int i = 0; i < indexes.length; i++) {
int quotient = quotients[i];
int remainder = remainders[i];
Expand Down

0 comments on commit 786c3d8

Please sign in to comment.