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-numbers.git
The following commit(s) were added to refs/heads/master by this push:
new f5d0de68 NUMBERS-214: Lower default iterations
f5d0de68 is described below
commit f5d0de6892bc701bd75beff80e6d9c374190fc09
Author: Alex Herbert <[email protected]>
AuthorDate: Fri Aug 21 10:05:26 2026 +0100
NUMBERS-214: Lower default iterations
---
.../fraction/GeneralizedContinuedFraction.java | 12 ++++++++--
.../fraction/GeneralizedContinuedFractionTest.java | 26 ++++++++++++++++++++++
src/changes/changes.xml | 5 +++++
3 files changed, 41 insertions(+), 2 deletions(-)
diff --git
a/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/GeneralizedContinuedFraction.java
b/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/GeneralizedContinuedFraction.java
index 0b5a0882..c3c3ee36 100644
---
a/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/GeneralizedContinuedFraction.java
+++
b/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/GeneralizedContinuedFraction.java
@@ -61,8 +61,16 @@ public final class GeneralizedContinuedFraction {
* eps * |b_n|, e.g., 1e-50".
*/
static final double SMALL = 1e-50;
- /** Default maximum number of iterations. */
- static final int DEFAULT_ITERATIONS = Integer.MAX_VALUE;
+ /**
+ * Default maximum number of iterations.
+ *
+ * <p>This bounds the cost of evaluating a fraction that neither converges
nor
+ * diverges when using the methods that do not accept a {@code
maxIterations}
+ * argument. The default is sufficient to converge typical fractions to
+ * {@code double} precision. Slowly converging fractions may be evaluated
using
+ * the methods that accept a {@code maxIterations} argument to raise the
limit.
+ */
+ static final int DEFAULT_ITERATIONS = 1_000_000;
/**
* Minimum relative error epsilon. Equal to 1 - Math.nextDown(1.0), or
2^-53.
*
diff --git
a/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/GeneralizedContinuedFractionTest.java
b/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/GeneralizedContinuedFractionTest.java
index 7eb68237..d503b32c 100644
---
a/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/GeneralizedContinuedFractionTest.java
+++
b/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/GeneralizedContinuedFractionTest.java
@@ -240,6 +240,32 @@ class GeneralizedContinuedFractionTest {
assertExceptionMessageContains(t, "max");
}
+ /**
+ * Evaluate a fraction that neither converges nor diverges using the
default
+ * iteration limit. The divergent form K(1/0) oscillates: the update deltaN
+ * alternates between approximately 1e50 and 1e-50 so the evaluation never
+ * meets the convergence, divergence or zero-update exit conditions. The
+ * default iteration limit must bound the work performed before the maximum
+ * iterations exception is raised.
+ */
+ @Test
+ void testDefaultIterationsBoundsNonConvergingFraction() {
+ final int[] calls = {0};
+ final Supplier<Coefficient> gen = () -> {
+ calls[0]++;
+ // The first term provides b0 to seed the evaluation (a is
discarded).
+ // All subsequent terms (a=1, b=0) create a non-converging
oscillation.
+ return Coefficient.of(1, calls[0] == 1 ? 1 : 0);
+ };
+ final Throwable t = Assertions.assertThrows(ArithmeticException.class,
+ () -> GeneralizedContinuedFraction.value(gen));
+ assertExceptionMessageContains(t, "max");
+ // 1 call to seed b0 + 1 call per iteration
+ Assertions.assertTrue(GeneralizedContinuedFraction.DEFAULT_ITERATIONS
<= 1_000_000,
+ "Default iterations should bound worst-case evaluation cost");
+ Assertions.assertEquals(1 +
GeneralizedContinuedFraction.DEFAULT_ITERATIONS, calls[0]);
+ }
+
@Test
void testNaNThrowsA() {
// Create a NaN during the iteration
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 4aabcfc4..f30c55f8 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -56,6 +56,11 @@ If the output is not quite correct, check for invisible
trailing spaces!
<release version="1.4" date="TBD" description="
New features, updates and bug fixes.
">
+ <action dev="aherbert" type="update" due-to="Security scan, Alex
Herbert" issue="NUMBERS-214">
+ "GeneralizedContinuedFraction": Lower the defaut iterations to
1_000_000. This
+ introduces a behavioural change for slowly converging fractions that
may now
+ raise an ArithemticException due to non-convergence within the
iteration limit.
+ </action>
<action dev="aherbert" type="add" due-to="Alex Herbert"
issue="NUMBERS-217">
"BigFraction": Allow conversion to BigDecimal using a MathContext.
</action>