This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-statistics.git


The following commit(s) were added to refs/heads/master by this push:
     new c0a84684 Optimise harmonic sum
c0a84684 is described below

commit c0a84684234f8b8019a437e18483ca315f6b994d
Author: Alex Herbert <[email protected]>
AuthorDate: Mon Aug 31 08:58:25 2026 +0100

    Optimise harmonic sum
---
 .../statistics/distribution/ZipfDistribution.java  | 45 ++++++++++++++++++----
 1 file changed, 37 insertions(+), 8 deletions(-)

diff --git 
a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/ZipfDistribution.java
 
b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/ZipfDistribution.java
index 49d0ae0f..315e76c8 100644
--- 
a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/ZipfDistribution.java
+++ 
b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/ZipfDistribution.java
@@ -72,7 +72,7 @@ public final class ZipfDistribution extends 
AbstractDiscreteDistribution {
                              double exponent) {
         this.numberOfElements = numberOfElements;
         this.exponent = exponent;
-        this.nthHarmonic = generalizedHarmonic(1, numberOfElements, exponent);
+        this.nthHarmonic = generalizedHarmonic(numberOfElements, exponent);
         logNthHarmonic = Math.log(nthHarmonic);
     }
 
@@ -151,7 +151,7 @@ public final class ZipfDistribution extends 
AbstractDiscreteDistribution {
             return 1;
         }
 
-        return generalizedHarmonic(1, x, exponent) / nthHarmonic;
+        return generalizedHarmonic(x, exponent) / nthHarmonic;
     }
 
     /** {@inheritDoc} */
@@ -239,6 +239,31 @@ public final class ZipfDistribution extends 
AbstractDiscreteDistribution {
         return h;
     }
 
+    /**
+     * Calculates the {@code n}-th generalized harmonic number.
+     *
+     * <pre>
+     *          1
+     *   sum  -----  for k in [1, n]
+     *         k^m
+     * </pre>
+     *
+     * <p>Assumes {@code exponent > 0} to arrange the terms to sum from small 
to large.
+     *
+     * @param n Last term in the series to calculate.
+     * @param m Exponent (special case {@code m = 1} is the harmonic series).
+     * @return the sum
+     */
+    private static double generalizedHarmonic(final int n, final double m) {
+        double value = 0;
+        // Sum small to large
+        for (int k = n; k >= 2; k--) {
+            value += Math.pow(k, -m);
+        }
+        // 1^-m = 1
+        return value + 1.0;
+    }
+
     /**
      * Calculates the sum of terms of the
      * <a href="https://mathworld.wolfram.com/HarmonicSeries.html";>Harmonic
@@ -269,7 +294,7 @@ public final class ZipfDistribution extends 
AbstractDiscreteDistribution {
     }
 
     /**
-     * Calculates the Nth generalized harmonic number.
+     * Calculates the {@code n}-th generalized harmonic number.
      *
      * <p>Checks the value of the {@code exponent} to arrange the terms to sum 
from from small to large.
      *
@@ -278,17 +303,21 @@ public final class ZipfDistribution extends 
AbstractDiscreteDistribution {
      * @return the n<sup>th</sup> generalized harmonic number.
      */
     private static double generalizedHarmonicAscendingSum(final int n, final 
double m) {
-        double value = 0;
-        // Sum small to large
-        // If m < 0 then sum ascending, otherwise descending
+        double value;
+        // Sum small to large.
+        // If m < 0 then sum ascending, otherwise descending.
+        // Note: 1^-m = 1
         if (m < 0) {
-            for (int k = 1; k <= n; k++) {
+            value = 1.0;
+            for (int k = 2; k <= n; k++) {
                 value += Math.pow(k, -m);
             }
         } else {
-            for (int k = n; k >= 1; k--) {
+            value = 0;
+            for (int k = n; k >= 2; k--) {
                 value += Math.pow(k, -m);
             }
+            value += 1.0;
         }
         return value;
     }

Reply via email to