You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ah...@apache.org on 2023/12/30 08:32:09 UTC
(commons-statistics) 05/06: STATISTICS-83: Benchmark handling of non-finite values in mean/sum
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-statistics.git
commit 7d553b2b7eaf8ee6300a11bfbb689e4f346348d7
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Fri Dec 29 23:39:49 2023 +0000
STATISTICS-83: Benchmark handling of non-finite values in mean/sum
---
.../jmh/descriptive/MomentPerformance.java | 133 ++++++++++++++++++++-
1 file changed, 132 insertions(+), 1 deletion(-)
diff --git a/commons-statistics-examples/examples-jmh/src/main/java/org/apache/commons/statistics/examples/jmh/descriptive/MomentPerformance.java b/commons-statistics-examples/examples-jmh/src/main/java/org/apache/commons/statistics/examples/jmh/descriptive/MomentPerformance.java
index a071083..ae4ba27 100644
--- a/commons-statistics-examples/examples-jmh/src/main/java/org/apache/commons/statistics/examples/jmh/descriptive/MomentPerformance.java
+++ b/commons-statistics-examples/examples-jmh/src/main/java/org/apache/commons/statistics/examples/jmh/descriptive/MomentPerformance.java
@@ -56,12 +56,20 @@ public class MomentPerformance {
private static final String SUM_MEAN = "SumMean";
/** Extended precision summation mean implementation. */
private static final String EXTENDED_SUM_MEAN = "ExtendedSumMean";
+ /** Extended precision summation (using Numbers Sum). */
+ private static final String NUMBERS_SUM = "NumbersSum";
+ /** Extended precision summation (using Numbers Sum) with computation of non-finite value. */
+ private static final String NUMBERS_SUM2 = "NumbersSum2";
/** Rolling mean implementation. */
private static final String ROLLING_MEAN = "RollingMean";
/** Safe rolling mean implementation. */
private static final String SAFE_ROLLING_MEAN = "SafeRollingMean";
/** Safe rolling mean implementation. */
private static final String SCALED_ROLLING_MEAN = "ScaledRollingMean";
+ /** Safe rolling mean implementation with computation of non-finite value. */
+ private static final String SCALED_ROLLING_MEAN2 = "ScaledRollingMean2";
+ /** Safe rolling mean implementation with computation of non-finite value. */
+ private static final String SCALED_ROLLING_MEAN3 = "ScaledRollingMean3";
/** Inline rolling mean implementation for array-based creation. */
private static final String INLINE_ROLLING_MEAN = "InlineRollingMean";
/** Inline safe rolling mean implementation for array-based creation. */
@@ -104,7 +112,8 @@ public class MomentPerformance {
@State(Scope.Benchmark)
public static class ActionSource {
/** Name of the source. */
- @Param({MEAN, ROLLING_MEAN, SAFE_ROLLING_MEAN, SCALED_ROLLING_MEAN, SUM_MEAN, EXTENDED_SUM_MEAN})
+ @Param({MEAN, ROLLING_MEAN, SAFE_ROLLING_MEAN, SCALED_ROLLING_MEAN, SUM_MEAN, EXTENDED_SUM_MEAN,
+ SCALED_ROLLING_MEAN2, SCALED_ROLLING_MEAN3, NUMBERS_SUM, NUMBERS_SUM2})
private String name;
/** The action. */
@@ -130,10 +139,18 @@ public class MomentPerformance {
action = SafeRollingFirstMoment::new;
} else if (SCALED_ROLLING_MEAN.equals(name)) {
action = ScaledRollingFirstMoment::new;
+ } else if (SCALED_ROLLING_MEAN2.equals(name)) {
+ action = ScaledRollingFirstMoment2::new;
+ } else if (SCALED_ROLLING_MEAN3.equals(name)) {
+ action = ScaledRollingFirstMoment3::new;
} else if (SUM_MEAN.equals(name)) {
action = SumFirstMoment::new;
} else if (EXTENDED_SUM_MEAN.equals(name)) {
action = ExtendedSumFirstMoment::new;
+ } else if (NUMBERS_SUM.equals(name)) {
+ action = NumbersSum::new;
+ } else if (NUMBERS_SUM2.equals(name)) {
+ action = NumbersSum2::new;
} else {
throw new IllegalStateException("Unknown action: " + name);
}
@@ -275,6 +292,72 @@ public class MomentPerformance {
}
}
+ /**
+ * A rolling first raw moment of {@code double} data safe to overflow of any finite
+ * values (e.g. [MAX_VALUE, -MAX_VALUE]). This includes computation of the correct
+ * non-finite value.
+ */
+ static class ScaledRollingFirstMoment2 implements DoubleConsumer, DoubleSupplier {
+ /** Count of values that have been added. */
+ private long n;
+
+ /** First moment of values that have been added. */
+ private double m1;
+
+ /** Non-finite result. This is the sum of non-finite values. */
+ private double nonFiniteValue;
+
+ @Override
+ public void accept(double value) {
+ if (!Double.isFinite(value)) {
+ nonFiniteValue += value;
+ }
+ m1 += (value * 0.5 - m1) / ++n;
+ }
+
+ @Override
+ public double getAsDouble() {
+ final double m = m1 * 2;
+ if (Double.isFinite(m)) {
+ return n == 0 ? Double.NaN : m;
+ }
+ // Non-finite value encountered
+ return nonFiniteValue;
+ }
+ }
+
+ /**
+ * A rolling first raw moment of {@code double} data safe to overflow of any finite
+ * values (e.g. [MAX_VALUE, -MAX_VALUE]). This includes computation of the correct
+ * non-finite value.
+ */
+ static class ScaledRollingFirstMoment3 implements DoubleConsumer, DoubleSupplier {
+ /** Count of values that have been added. */
+ private long n;
+
+ /** First moment of values that have been added. */
+ private double m1;
+
+ /** Non-finite result. This is the sum of non-finite values. */
+ private double nonFiniteValue;
+
+ @Override
+ public void accept(double value) {
+ nonFiniteValue += value * Double.MIN_NORMAL;
+ m1 += (value * 0.5 - m1) / ++n;
+ }
+
+ @Override
+ public double getAsDouble() {
+ final double m = m1 * 2;
+ if (Double.isFinite(m)) {
+ return n == 0 ? Double.NaN : m;
+ }
+ // Non-finite value encountered
+ return nonFiniteValue;
+ }
+ }
+
/**
* A mean using a sum.
*/
@@ -331,6 +414,54 @@ public class MomentPerformance {
}
}
+ /**
+ * A sum using an Commons Numbers {@link Sum}.
+ */
+ static class NumbersSum implements DoubleConsumer, DoubleSupplier {
+ /** Sum of values that have been added. */
+ private Sum sum = Sum.create();
+
+ @Override
+ public void accept(double value) {
+ sum.add(value);
+ }
+
+ @Override
+ public double getAsDouble() {
+ return sum.getAsDouble();
+ }
+ }
+
+ /**
+ * A sum using an Commons Numbers {@link Sum} with computation of the correct
+ * non-finite value.
+ */
+ static class NumbersSum2 implements DoubleConsumer, DoubleSupplier {
+ /** Sum of values that have been added. */
+ private Sum sum = Sum.create();
+
+ /** Non-finite result. This is the sum of non-finite values. */
+ private double nonFiniteValue;
+
+ @Override
+ public void accept(double value) {
+ if (!Double.isFinite(value)) {
+ nonFiniteValue += value;
+ }
+ sum.add(value);
+ }
+
+ @Override
+ public double getAsDouble() {
+ final double s = sum.getAsDouble();
+ if (Double.isFinite(s)) {
+ return s;
+ }
+ // Non-finite value encountered
+ return nonFiniteValue;
+ }
+ }
+
/**
* Apply the action to each value.
*