1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.numbers.fraction;
18
19 import java.util.Locale;
20 import org.junit.jupiter.api.Assertions;
21 import org.junit.jupiter.api.Test;
22 import org.junit.jupiter.params.ParameterizedTest;
23 import org.junit.jupiter.params.provider.ValueSource;
24
25
26
27
28 class ContinuedFractionTest {
29
30 private static final double GOLDEN_RATIO = 1.618033988749894848204586834365638117720309;
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 private static final class GoldenRatio extends ContinuedFraction {
51 private static final GoldenRatio INSTANCE = new GoldenRatio();
52
53
54
55
56 static GoldenRatio getInstance() {
57 return INSTANCE;
58 }
59
60
61 @Override
62 public double getA(int n, double x) {
63 return 1;
64 }
65
66
67 @Override
68 public double getB(int n, double x) {
69 return 1;
70 }
71 }
72
73 @Test
74 void testGoldenRatio() {
75 final double eps = 1e-8;
76 final double gr = GoldenRatio.getInstance().evaluate(0, eps);
77 Assertions.assertEquals(GOLDEN_RATIO, gr, GOLDEN_RATIO * eps);
78 }
79
80
81
82
83
84 @Test
85 void testGoldenRatioReciprocal() {
86 final double eps = 1e-8;
87 final ContinuedFraction cf = new ContinuedFraction() {
88 @Override
89 public double getA(int n, double x) {
90
91 Assertions.assertNotEquals(0, n, "a0 should never require evaluation");
92 return 1;
93 }
94
95 @Override
96 public double getB(int n, double x) {
97
98 return n == 0 ? 0 : 1;
99 }
100 };
101 final double gr = cf.evaluate(0, eps);
102 Assertions.assertEquals(1 / GOLDEN_RATIO, gr, eps / GOLDEN_RATIO);
103 }
104
105
106
107
108
109
110
111 @ParameterizedTest
112 @ValueSource(doubles = {0, -1, Double.NaN})
113 void testGoldenRatioEpsilonZero(double epsilon) {
114
115
116 final double tolerance = Math.ulp(GOLDEN_RATIO);
117 Assertions.assertEquals(GOLDEN_RATIO, GoldenRatio.getInstance().evaluate(0, epsilon), tolerance);
118 }
119
120 @Test
121 void test415Over93() {
122
123
124
125
126
127
128
129
130
131
132 final ContinuedFraction cf = new ContinuedFraction() {
133 @Override
134 public double getA(int n, double x) {
135 return n <= 3 ? 1 : 0;
136 }
137
138 @Override
139 public double getB(int n, double x) {
140 switch (n) {
141 case 0:
142 return 4;
143 case 1:
144 return 2;
145 case 2:
146 return 6;
147 case 3:
148 return 7;
149 default:
150 return 1;
151 }
152 }
153 };
154
155 final double eps = 1e-8;
156 final double gr = cf.evaluate(0, eps, 5);
157 Assertions.assertEquals(415.0 / 93.0, gr, eps);
158 }
159
160 @Test
161 void testMaxIterationsThrows() {
162 final ContinuedFraction cf = GoldenRatio.getInstance();
163
164 final double eps = 1e-8;
165 final int maxIterations = 3;
166 final Throwable t = Assertions.assertThrows(FractionException.class, () -> cf.evaluate(0, eps, maxIterations));
167 assertExceptionMessageContains(t, "max");
168 }
169
170 @Test
171 void testNaNThrows() {
172
173 final ContinuedFraction cf = new ContinuedFraction() {
174 @Override
175 public double getA(int n, double x) {
176 return 1;
177 }
178
179 @Override
180 public double getB(int n, double x) {
181 return n == 0 ? 1 : Double.NaN;
182 }
183 };
184
185 final double eps = 1e-8;
186 final Throwable t = Assertions.assertThrows(FractionException.class, () -> cf.evaluate(0, eps, 5));
187 assertExceptionMessageContains(t, "nan");
188 }
189
190 @Test
191 void testInfThrows() {
192
193
194 final ContinuedFraction cf = new ContinuedFraction() {
195 @Override
196 public double getA(int n, double x) {
197 return n == 0 ? 1 : Double.MAX_VALUE;
198 }
199
200 @Override
201 public double getB(int n, double x) {
202 return 0.5;
203 }
204 };
205
206 final double eps = 1e-8;
207 final Throwable t = Assertions.assertThrows(FractionException.class, () -> cf.evaluate(0, eps, 5));
208 assertExceptionMessageContains(t, "infinity");
209 }
210
211 private static void assertExceptionMessageContains(Throwable t, String text) {
212 Assertions.assertTrue(t.getMessage().toLowerCase(Locale.ROOT).contains(text),
213 () -> "Missing '" + text + "' from exception message: " + t.getMessage());
214 }
215
216
217 @Test
218 void testOneIteration() {
219 final double eps = 0.5;
220 final double gr = GoldenRatio.getInstance().evaluate(0, eps, 1);
221
222 Assertions.assertEquals(2.0, gr);
223 }
224
225
226 @Test
227 void testTwoIterations() {
228 final double eps = 0.25;
229 final double gr = GoldenRatio.getInstance().evaluate(0, eps, 2);
230
231 Assertions.assertEquals(1.5, gr);
232 }
233 }