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 2021/11/02 10:55:40 UTC
[commons-numbers] 02/02: Reuse the golden ratio continued fraction
implementation.
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-numbers.git
commit 924099e0c03ad21dce3cff85086142ae6d273f27
Author: aherbert <ah...@apache.org>
AuthorDate: Tue Nov 2 10:54:32 2021 +0000
Reuse the golden ratio continued fraction implementation.
---
.../numbers/fraction/ContinuedFractionTest.java | 154 ++++++++++-----------
1 file changed, 72 insertions(+), 82 deletions(-)
diff --git a/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/ContinuedFractionTest.java b/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/ContinuedFractionTest.java
index 79bf890..b9c21e0 100644
--- a/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/ContinuedFractionTest.java
+++ b/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/ContinuedFractionTest.java
@@ -29,47 +29,67 @@ class ContinuedFractionTest {
/** Golden ratio constant. */
private static final double GOLDEN_RATIO = 1.618033988749894848204586834365638117720309;
+ /**
+ * Evaluates the golden ratio.
+ *
+ * <pre>
+ * 1 + 1
+ * ----------------
+ * 1 + 1
+ * ------------
+ * 1 + 1
+ * -------
+ * 1 + ...
+ * </pre>
+ *
+ * <p>This is used to test various conditions for the {@link ContinuedFraction}.
+ *
+ * @see <a href="https://mathworld.wolfram.com/GoldenRatio.html">MathWorld Golden
+ * Ratio equation 17</a>
+ */
+ private static class GoldenRatio extends ContinuedFraction {
+ private static final GoldenRatio INSTANCE = new GoldenRatio();
+
+ /**
+ * @return single instance of GoldenRatio
+ */
+ static GoldenRatio getInstance() {
+ return INSTANCE;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double getA(int n, double x) {
+ return 1;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double getB(int n, double x) {
+ return 1;
+ }
+ }
+
@Test
void testGoldenRatio() throws Exception {
- ContinuedFraction cf = new ContinuedFraction() {
- @Override
- public double getA(int n, double x) {
- return 1;
- }
-
- @Override
- public double getB(int n, double x) {
- return 1;
- }
- };
-
final double eps = 1e-8;
- double gr = cf.evaluate(0, eps);
- Assertions.assertEquals(1.61803399, gr, eps);
+ final double gr = GoldenRatio.getInstance().evaluate(0, eps);
+ Assertions.assertEquals(GOLDEN_RATIO, gr, GOLDEN_RATIO * eps);
}
/**
* Test an invalid epsilon (zero, negative or NaN).
* See NUMBERS-173.
*
- * @param epsilon the epsilon
+ * @param epsilon Epsilon
*/
@ParameterizedTest
@ValueSource(doubles = {0, -1, Double.NaN})
void testGoldenRatioEpsilonZero(double epsilon) {
- ContinuedFraction cf = new ContinuedFraction() {
- @Override
- public double getA(int n, double x) {
- return 1;
- }
-
- @Override
- public double getB(int n, double x) {
- return 1;
- }
- };
-
- Assertions.assertEquals(GOLDEN_RATIO, cf.evaluate(0, epsilon), Math.ulp(GOLDEN_RATIO));
+ // An invalid epsilon is set to the minimum epsilon.
+ // It should converge to 1 ULP.
+ final double tolerance = Math.ulp(GOLDEN_RATIO);
+ Assertions.assertEquals(GOLDEN_RATIO, GoldenRatio.getInstance().evaluate(0, epsilon), tolerance);
}
@Test
@@ -84,7 +104,7 @@ class ContinuedFractionTest {
// 7
// = [4; 2, 6, 7]
- ContinuedFraction cf = new ContinuedFraction() {
+ final ContinuedFraction cf = new ContinuedFraction() {
@Override
public double getA(int n, double x) {
return n <= 3 ? 1 : 0;
@@ -93,45 +113,39 @@ class ContinuedFractionTest {
@Override
public double getB(int n, double x) {
switch (n) {
- case 0: return 4;
- case 1: return 2;
- case 2: return 6;
- case 3: return 7;
- default: return 1;
+ case 0:
+ return 4;
+ case 1:
+ return 2;
+ case 2:
+ return 6;
+ case 3:
+ return 7;
+ default:
+ return 1;
}
}
};
final double eps = 1e-8;
- double gr = cf.evaluate(0, eps, 5);
+ final double gr = cf.evaluate(0, eps, 5);
Assertions.assertEquals(415.0 / 93.0, gr, eps);
}
@Test
void testMaxIterationsThrows() throws Exception {
- ContinuedFraction cf = new ContinuedFraction() {
- @Override
- public double getA(int n, double x) {
- return 1;
- }
-
- @Override
- public double getB(int n, double x) {
- return 1;
- }
- };
+ final ContinuedFraction cf = GoldenRatio.getInstance();
final double eps = 1e-8;
final int maxIterations = 3;
- final Throwable t = Assertions.assertThrows(FractionException.class,
- () -> cf.evaluate(0, eps, maxIterations));
+ final Throwable t = Assertions.assertThrows(FractionException.class, () -> cf.evaluate(0, eps, maxIterations));
assertExceptionMessageContains(t, "max");
}
@Test
void testNaNThrows() throws Exception {
// Create a NaN during the iteration
- ContinuedFraction cf = new ContinuedFraction() {
+ final ContinuedFraction cf = new ContinuedFraction() {
@Override
public double getA(int n, double x) {
return 1;
@@ -144,16 +158,15 @@ class ContinuedFractionTest {
};
final double eps = 1e-8;
- final Throwable t = Assertions.assertThrows(FractionException.class,
- () -> cf.evaluate(0, eps, 5));
+ final Throwable t = Assertions.assertThrows(FractionException.class, () -> cf.evaluate(0, eps, 5));
assertExceptionMessageContains(t, "nan");
}
@Test
void testInfThrows() throws Exception {
// Create an infinity during the iteration:
- // a / cPrev => a_1 / b_0 => Double.MAX_VALUE / 0.5
- ContinuedFraction cf = new ContinuedFraction() {
+ // a / cPrev => a_1 / b_0 => Double.MAX_VALUE / 0.5
+ final ContinuedFraction cf = new ContinuedFraction() {
@Override
public double getA(int n, double x) {
return n == 0 ? 1 : Double.MAX_VALUE;
@@ -166,8 +179,7 @@ class ContinuedFractionTest {
};
final double eps = 1e-8;
- final Throwable t = Assertions.assertThrows(FractionException.class,
- () -> cf.evaluate(0, eps, 5));
+ final Throwable t = Assertions.assertThrows(FractionException.class, () -> cf.evaluate(0, eps, 5));
assertExceptionMessageContains(t, "infinity");
}
@@ -179,40 +191,18 @@ class ContinuedFractionTest {
// NUMBERS-46
@Test
void testOneIteration() {
- ContinuedFraction cf = new ContinuedFraction() {
- @Override
- public double getA(int n, double x) {
- return 1;
- }
-
- @Override
- public double getB(int n, double x) {
- return 1;
- }
- };
-
final double eps = 10;
- double gr = cf.evaluate(0, eps, 1);
- Assertions.assertEquals(1.61, gr, eps);
+ final double gr = GoldenRatio.getInstance().evaluate(0, eps, 1);
+ // Expected: 1 + 1 / 1
+ Assertions.assertEquals(2.0, gr);
}
// NUMBERS-46
@Test
void testTwoIterations() {
- ContinuedFraction cf = new ContinuedFraction() {
- @Override
- public double getA(int n, double x) {
- return 1;
- }
-
- @Override
- public double getB(int n, double x) {
- return 1;
- }
- };
-
final double eps = 0.5;
- double gr = cf.evaluate(0, eps, 2);
+ final double gr = GoldenRatio.getInstance().evaluate(0, eps, 2);
+ // Expected: 1 + 1 / (1 + 1 / 1)
Assertions.assertEquals(1.5, gr);
}
}