1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 package org.apache.commons.numbers.examples.jmh.gamma;
26
27 import java.util.Arrays;
28 import java.util.concurrent.TimeUnit;
29 import java.util.function.DoubleBinaryOperator;
30 import java.util.function.Supplier;
31 import org.apache.commons.numbers.fraction.GeneralizedContinuedFraction;
32 import org.apache.commons.numbers.fraction.GeneralizedContinuedFraction.Coefficient;
33 import org.openjdk.jmh.annotations.Benchmark;
34 import org.openjdk.jmh.annotations.BenchmarkMode;
35 import org.openjdk.jmh.annotations.Fork;
36 import org.openjdk.jmh.annotations.Measurement;
37 import org.openjdk.jmh.annotations.Mode;
38 import org.openjdk.jmh.annotations.OutputTimeUnit;
39 import org.openjdk.jmh.annotations.Param;
40 import org.openjdk.jmh.annotations.Scope;
41 import org.openjdk.jmh.annotations.Setup;
42 import org.openjdk.jmh.annotations.State;
43 import org.openjdk.jmh.annotations.Warmup;
44 import org.openjdk.jmh.infra.Blackhole;
45
46
47
48
49
50 @BenchmarkMode(Mode.AverageTime)
51 @OutputTimeUnit(TimeUnit.NANOSECONDS)
52 @Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
53 @Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
54 @State(Scope.Benchmark)
55 @Fork(value = 1, jvmArgs = {"-server", "-Xms512M", "-Xmx512M"})
56 public class GammaContinuedFractionPerformance {
57
58
59 static final String IMP_NUMBERS_1_0 = "Numbers 1.0";
60
61 static final String IMP_NUMBERS_EXT_A = "Numbers Extended A";
62
63
64 static final String IMP_NUMBERS_EXT_A1 = "Numbers Extended A1";
65
66 static final String IMP_ITERATOR = "Iterator";
67
68 static final String IMP_NUMBERS_1_1 = "Numbers 1.1";
69
70 static final String IMP_NUMBERS_1_1_INC = "Numbers 1.1 Inc";
71
72
73
74
75
76
77
78 private static final double SMALL = 1e-50;
79
80
81
82
83 private static final double EPSILON = 0x1.0p-52;
84
85 private static final int MAX_ITERATIONS = 100000;
86
87
88
89
90
91
92
93
94
95
96 private static final double[][] A_Z = {
97 {32.5, 65.0},
98 {33.0, 66.0},
99 {36.5, 73.0},
100 {37.0, 74.0},
101 {1.6504575484077577E-12, 100.0},
102 {2.0654589150126412E-12, 100.0},
103 {6.93323176648164E-12, 100.0},
104 {1.335143107183967E-11, 100.0},
105 {1.6399770430552962E-11, 100.0},
106 {5.730160790307082E-11, 100.0},
107 {1.113731329382972E-10, 100.0},
108 {1.4214707189097453E-10, 100.0},
109 {3.800633141537446E-10, 100.0},
110 {6.09162720266454E-10, 100.0},
111 {1.0221641311147778E-9, 100.0},
112 {2.8819229225263143E-9, 100.0},
113 {4.7627768395841485E-9, 100.0},
114 {8.854135202795987E-9, 100.0},
115 {2.305032964500242E-8, 100.0},
116 {5.9392490925347374E-8, 100.0},
117 {1.1667650312574551E-7, 100.0},
118 {2.3799674409019644E-7, 100.0},
119 {4.684659415943315E-7, 100.0},
120 {9.382700909554842E-7, 100.0},
121 {1.1039858236472355E-6, 100.0},
122 {3.2917764656303916E-6, 100.0},
123 {7.517214726249222E-6, 100.0},
124 {1.5114666894078255E-5, 100.0},
125 {2.986399704241194E-5, 100.0},
126 {3.387029209989123E-5, 100.0},
127 {9.06601344468072E-5, 100.0},
128 {2.194953412981704E-4, 100.0},
129 {4.395215946715325E-4, 100.0},
130 {6.333151832222939E-4, 100.0},
131 {0.0011151233920827508, 100.0},
132 {0.001962467795237899, 100.0},
133 {0.005553754977881908, 100.0},
134 {0.00869112927466631, 100.0},
135 {0.029933366924524307, 100.0},
136 {0.05124260485172272, 100.0},
137 {0.9759566783905029, 1.9519133567810059},
138 {0.9759566783905029, 100.0},
139 {3.667367935180664, 4.034104824066162},
140 {3.667367935180664, 7.334735870361328},
141 {3.667367935180664, 366.7367858886719},
142 {3.927384853363037, 4.320123195648193},
143 {3.927384853363037, 7.854769706726074},
144 {3.927384853363037, 392.7384948730469},
145 {4.053312301635742, 4.458643436431885},
146 {4.053312301635742, 8.106624603271484},
147 {4.053312301635742, 405.33123779296875},
148 {4.125904560089111, 4.538495063781738},
149 {4.125904560089111, 8.251809120178223},
150 {4.125904560089111, 412.5904541015625},
151 {5.094053268432617, 5.603458404541016},
152 {5.094053268432617, 10.188106536865234},
153 {5.094053268432617, 509.40533447265625},
154 {5.596034526824951, 6.155638217926025},
155 {5.596034526824951, 11.192069053649902},
156 {5.596034526824951, 559.6034545898438},
157 {10.16461181640625, 11.181073188781738},
158 {10.16461181640625, 20.3292236328125},
159 {10.205269813537598, 11.225796699523926},
160 {10.205269813537598, 20.410539627075195},
161 {11.431244850158691, 12.574369430541992},
162 {11.431244850158691, 22.862489700317383},
163 {11.69021987915039, 12.859241485595703},
164 {11.69021987915039, 23.38043975830078},
165 {12.955684661865234, 14.251253128051758},
166 {12.955684661865234, 25.91136932373047},
167 {13.026715278625488, 14.329386711120605},
168 {13.026715278625488, 26.053430557250977},
169 {13.135188102722168, 14.44870662689209},
170 {13.135188102722168, 26.270376205444336},
171 {13.979962348937988, 15.377958297729492},
172 {13.979962348937988, 27.959924697875977},
173 {14.617691040039062, 16.07946014404297},
174 {14.617691040039062, 29.235382080078125},
175 {15.336841583251953, 16.870525360107422},
176 {15.336841583251953, 30.673683166503906},
177 {16.18250274658203, 17.800752639770508},
178 {16.18250274658203, 32.36500549316406},
179 {17.5330753326416, 19.2863826751709},
180 {17.5330753326416, 35.0661506652832},
181 {17.799583435058594, 19.57954216003418},
182 {17.799583435058594, 35.59916687011719},
183 {19.09382438659668, 21.003206253051758},
184 {19.09382438659668, 38.18764877319336},
185 {19.24400520324707, 21.168405532836914},
186 {19.24400520324707, 38.48801040649414},
187 {21.415802001953125, 42.83160400390625},
188 {21.586471557617188, 43.172943115234375},
189 {22.492887496948242, 44.985774993896484},
190 {28.053834915161133, 56.107669830322266},
191 {28.210573196411133, 56.421146392822266},
192 {30.054428100585938, 60.108856201171875},
193 {30.540353775024414, 61.08070755004883},
194 {31.162620544433594, 62.32524108886719},
195 {31.996768951416016, 63.99353790283203},
196 {32.05139923095703, 64.10279846191406},
197 {36.448753356933594, 72.89750671386719},
198 {38.465065002441406, 76.93013000488281},
199 {39.526588439941406, 79.05317687988281},
200 {40.17448425292969, 80.34896850585938},
201 {41.16875076293945, 82.3375015258789},
202 {42.465248107910156, 84.93049621582031},
203 {42.49772262573242, 84.99544525146484},
204 {44.15506362915039, 88.31012725830078},
205 {44.8358268737793, 89.6716537475586},
206 {46.06991958618164, 92.13983917236328},
207 {47.738487243652344, 95.47697448730469},
208 {48.79487609863281, 97.58975219726562},
209 {49.01310729980469, 98.02621459960938},
210 {49.2315559387207, 98.4631118774414},
211 {49.3136100769043, 98.6272201538086},
212 {50.61444091796875, 101.2288818359375},
213 {54.91470718383789, 109.82941436767578},
214 {54.948448181152344, 109.89689636230469},
215 {63.41974639892578, 126.83949279785156},
216 {64.15645599365234, 128.3129119873047},
217 {64.80814361572266, 129.6162872314453},
218 {65.72004699707031, 131.44009399414062},
219 {65.74620056152344, 131.49240112304688},
220 {66.52874755859375, 133.0574951171875},
221 {68.03414916992188, 136.06829833984375},
222 {68.29527282714844, 136.59054565429688},
223 {69.63545227050781, 139.27090454101562},
224 {70.7515869140625, 141.503173828125},
225 {71.08180236816406, 142.16360473632812},
226 {72.72097778320312, 145.44195556640625},
227 {74.19440460205078, 148.38880920410156},
228 {74.44168090820312, 148.88336181640625},
229 {75.59132385253906, 151.18264770507812},
230 {75.8951416015625, 151.790283203125},
231 {76.49312591552734, 152.9862518310547},
232 {76.6689224243164, 153.3378448486328},
233 {79.32462310791016, 158.6492462158203},
234 {79.5005111694336, 159.0010223388672},
235 {79.62239074707031, 159.24478149414062},
236 {79.829345703125, 159.65869140625},
237 {79.8938980102539, 159.7877960205078},
238 {79.91152954101562, 159.82305908203125},
239 {80.1279067993164, 160.2558135986328},
240 {80.84933471679688, 161.69866943359375},
241 {81.56500244140625, 163.1300048828125},
242 {82.27938079833984, 164.5587615966797},
243 {82.43405151367188, 164.86810302734375},
244 {83.5833511352539, 167.1667022705078},
245 {84.98836517333984, 169.9767303466797},
246 {87.30667114257812, 174.61334228515625},
247 {87.90385437011719, 175.80770874023438},
248 {90.62629699707031, 181.25259399414062},
249 {91.38089752197266, 182.7617950439453},
250 {91.61568450927734, 183.2313690185547},
251 {92.12703704833984, 184.2540740966797},
252 {93.43232727050781, 186.86465454101562},
253 {95.0470962524414, 190.0941925048828},
254 {95.73811340332031, 191.47622680664062},
255 {95.77192687988281, 191.54385375976562},
256 {95.96949768066406, 191.93899536132812},
257 {96.50640869140625, 193.0128173828125},
258 {96.78564453125, 193.5712890625},
259 {96.90234375, 193.8046875},
260 {97.07398223876953, 194.14796447753906},
261 {98.12041473388672, 196.24082946777344},
262 {99.29168701171875, 198.5833740234375},
263 {99.4098129272461, 198.8196258544922},
264 {99.64790344238281, 199.29580688476562},
265 {1.7306554127571872E-6, 100.0},
266 {2.1657506295014173E-6, 100.0},
267 {7.2700195232755505E-6, 100.0},
268 {1.4000004739500582E-5, 100.0},
269 {1.71964547917014E-5, 100.0},
270 {6.008507625665516E-5, 100.0},
271 {1.1678319424390793E-4, 100.0},
272 {1.490520080551505E-4, 100.0},
273 {3.98525211494416E-4, 100.0},
274 {6.387534085661173E-4, 100.0},
275 {0.0010718167759478092, 100.0},
276 {0.0030219152104109526, 100.0},
277 {0.004994133487343788, 100.0},
278 {0.009284233674407005, 100.0},
279 {0.02417002245783806, 100.0},
280 {0.06227754056453705, 100.0},
281 {0.12234418094158173, 100.0},
282 {0.24955767393112183, 100.0},
283 {0.4912221431732178, 100.0},
284 {0.9838474988937378, 1.9676949977874756},
285 {0.9838474988937378, 100.0},
286 {1.1576130390167236, 2.3152260780334473},
287 {1.1576130390167236, 115.76130676269531},
288 {3.4516777992248535, 3.7968456745147705},
289 {3.4516777992248535, 6.903355598449707},
290 {3.4516777992248535, 345.16778564453125},
291 {7.882370948791504, 8.670608520507812},
292 {7.882370948791504, 15.764741897583008},
293 {15.848876953125, 17.433765411376953},
294 {15.848876953125, 31.69775390625},
295 {31.31467056274414, 62.62934112548828},
296 {35.51557540893555, 71.0311508178711},
297 {95.06404113769531, 190.12808227539062},
298 {230.1575469970703, 460.3150939941406},
299 {460.8717956542969, 921.7435913085938},
300 {0.75, 708.0},
301 {0.75, 708.5},
302 {0.75, 707.5},
303 {32.5, 34.5},
304 {33.0, 35.0},
305 {36.5, 38.5},
306 {37.0, 39.0},
307 {21.415802001953125, 23.415802001953125},
308 {21.586471557617188, 23.586471557617188},
309 {22.492887496948242, 24.492887496948242},
310 {28.053834915161133, 30.053834915161133},
311 {28.210573196411133, 30.210573196411133},
312 {30.054428100585938, 32.05442810058594},
313 {30.540353775024414, 32.54035186767578},
314 {31.162620544433594, 33.162620544433594},
315 {31.996768951416016, 33.996768951416016},
316 {32.05139923095703, 34.05139923095703},
317 {36.448753356933594, 38.448753356933594},
318 {38.465065002441406, 40.465065002441406},
319 {39.526588439941406, 41.526588439941406},
320 {40.17448425292969, 42.17448425292969},
321 {41.16875076293945, 43.16875076293945},
322 {42.465248107910156, 44.465248107910156},
323 {42.49772262573242, 44.49772262573242},
324 {44.15506362915039, 46.15506362915039},
325 {44.8358268737793, 46.8358268737793},
326 {46.06991958618164, 48.06991958618164},
327 {47.738487243652344, 49.738487243652344},
328 {48.79487609863281, 50.79487609863281},
329 {49.01310729980469, 51.01310729980469},
330 {49.2315559387207, 51.2315559387207},
331 {49.3136100769043, 51.3136100769043},
332 {50.61444091796875, 52.61444091796875},
333 {54.91470718383789, 56.91470718383789},
334 {54.948448181152344, 56.948448181152344},
335 {63.41974639892578, 65.41974639892578},
336 {64.15645599365234, 66.15645599365234},
337 {64.80814361572266, 66.80814361572266},
338 {65.72004699707031, 67.72004699707031},
339 {65.74620056152344, 67.74620056152344},
340 {66.52874755859375, 68.52874755859375},
341 {68.03414916992188, 70.03414916992188},
342 {68.29527282714844, 70.29527282714844},
343 {69.63545227050781, 71.63545227050781},
344 {70.7515869140625, 72.7515869140625},
345 {71.08180236816406, 73.08180236816406},
346 {72.72097778320312, 74.72097778320312},
347 {74.19440460205078, 76.19440460205078},
348 {74.44168090820312, 76.44168090820312},
349 {75.59132385253906, 77.59132385253906},
350 {75.8951416015625, 77.8951416015625},
351 {76.49312591552734, 78.49312591552734},
352 {76.6689224243164, 78.6689224243164},
353 {79.32462310791016, 81.32462310791016},
354 {79.5005111694336, 81.5005111694336},
355 {79.62239074707031, 81.62239074707031},
356 {79.829345703125, 81.829345703125},
357 {79.8938980102539, 81.8938980102539},
358 {79.91152954101562, 81.91152954101562},
359 {80.1279067993164, 82.1279067993164},
360 {80.84933471679688, 82.84933471679688},
361 {81.56500244140625, 83.56500244140625},
362 {82.27938079833984, 84.27938079833984},
363 {82.43405151367188, 84.43405151367188},
364 {83.5833511352539, 85.5833511352539},
365 {84.98836517333984, 86.98836517333984},
366 {87.30667114257812, 89.30667114257812},
367 {87.90385437011719, 89.90385437011719},
368 {90.62629699707031, 92.62629699707031},
369 {91.38089752197266, 93.38089752197266},
370 {91.61568450927734, 93.61568450927734},
371 {92.12703704833984, 94.12703704833984},
372 {93.43232727050781, 95.43232727050781},
373 {95.0470962524414, 97.0470962524414},
374 {95.73811340332031, 97.73811340332031},
375 {95.77192687988281, 97.77192687988281},
376 {95.96949768066406, 97.96949768066406},
377 {96.50640869140625, 98.50640869140625},
378 {96.78564453125, 98.78564453125},
379 {96.90234375, 98.90234375},
380 {97.07398223876953, 99.07398223876953},
381 {98.12041473388672, 100.12041473388672},
382 {99.29168701171875, 101.29168701171875},
383 {99.4098129272461, 101.4098129272461},
384 {99.64790344238281, 101.64790344238281},
385 {7.882370948791504, 788.2371215820312},
386 {31.31467056274414, 33.31467056274414},
387 {35.51557540893555, 37.51557540893555},
388 {95.06404113769531, 97.06404113769531},
389 {230.1575469970703, 23015.75390625},
390 {460.8717956542969, 46087.1796875},
391 {664.0791015625, 66407.90625},
392 {1169.2916259765625, 116929.1640625},
393 {2057.796630859375, 205779.65625},
394 {5823.5341796875, 582353.4375},
395 {9113.3095703125, 911330.9375},
396 {31387.41015625, 3138741.0},
397 {53731.765625, 5373176.5},
398 {117454.09375, 1.1745409E7},
399 {246209.65625, 2.4620966E7},
400 {513669.1875, 5.136692E7},
401 {788352.3125, 7.8835232E7},
402 {1736170.0, 1.73616992E8},
403 {170.0, 1000.0},
404 {185.0, 1500.0},
405 };
406
407
408
409
410 @State(Scope.Benchmark)
411 public static class BaseData {
412
413 private static final String MSG_DIVERGED = "Continued fraction diverged to %s for value %s";
414
415 private static final String MSG_MAX_ITERATIONS = "Maximum iterations exceeded: ";
416
417
418 @Param({IMP_NUMBERS_1_0, IMP_NUMBERS_EXT_A, IMP_NUMBERS_EXT_A1,
419 IMP_ITERATOR, IMP_NUMBERS_1_1, IMP_NUMBERS_1_1_INC})
420 private String implementation;
421
422
423 private DoubleBinaryOperator function;
424
425
426
427
428
429
430 public DoubleBinaryOperator getFunction() {
431 return function;
432 }
433
434
435
436
437 @Setup
438 public void setup() {
439 function = createFunction(implementation);
440 }
441
442
443
444
445
446
447
448
449 static DoubleBinaryOperator createFunction(String implementation) {
450 if (IMP_NUMBERS_1_0.equals(implementation)) {
451
452 return (a, z) -> {
453 final ContinuedFraction cf = new ContinuedFraction() {
454
455 @Override
456 protected double getA(int n, double x) {
457 return n * (a - n);
458 }
459
460
461 @Override
462 protected double getB(int n, double x) {
463 return ((2 * n) + 1) - a + x;
464 }
465 };
466
467 return 1 / cf.evaluate(z, EPSILON, MAX_ITERATIONS);
468 };
469 } else if (IMP_NUMBERS_EXT_A.equals(implementation)) {
470
471
472 return (a, z) -> {
473 final ContinuedFractionA cf = new ContinuedFractionA() {
474 @Override
475 protected double getA(int n, double x) {
476 n++;
477 return n * (a - n);
478 }
479
480 @Override
481 protected double getB(int n, double x) {
482 n++;
483 return ((2 * n) + 1) - a + x;
484 }
485 };
486
487 return 1 / (z - a + 1 + cf.evaluate(z, EPSILON, MAX_ITERATIONS));
488 };
489 } else if (IMP_NUMBERS_EXT_A1.equals(implementation)) {
490
491 return (a, z) -> {
492 final ContinuedFractionA1 cf = new ContinuedFractionA1() {
493 @Override
494 protected double getA(int n, double x) {
495 return n * (a - n);
496 }
497
498 @Override
499 protected double getB(int n, double x) {
500 return ((2 * n) + 1) - a + x;
501 }
502 };
503
504 return 1 / (z - a + 1 + cf.evaluate(z, EPSILON, MAX_ITERATIONS));
505 };
506 } else if (IMP_ITERATOR.equals(implementation)) {
507
508 return (a, z) -> {
509 final ContinuedFractionIterator cf = new ContinuedFractionIterator() {
510
511 private double x = z - a + 1;
512
513 private int k;
514
515 @Override
516 void next() {
517 ++k;
518 x += 2;
519 setCoefficients(k * (a - k), x);
520 }
521 };
522
523 return 1 / (z - a + 1 + cf.evaluate(EPSILON, MAX_ITERATIONS));
524 };
525 } else if (IMP_NUMBERS_1_1.equals(implementation)) {
526
527
528 return (a, z) -> {
529 final double zma1 = z - a + 1;
530
531 final Supplier<Coefficient> gen = new Supplier<>() {
532
533 private int k;
534
535 @Override
536 public Coefficient get() {
537 ++k;
538 return Coefficient.of(k * (a - k), zma1 + 2.0 * k);
539 }
540 };
541
542 return 1 / GeneralizedContinuedFraction.value(zma1, gen, EPSILON, MAX_ITERATIONS);
543 };
544 } else if (IMP_NUMBERS_1_1_INC.equals(implementation)) {
545
546
547 return (a, z) -> {
548
549 final Supplier<Coefficient> gen = new Supplier<>() {
550
551 private int k;
552
553 private double b = z - a + 1;
554
555 @Override
556 public Coefficient get() {
557 ++k;
558 b += 2;
559 return Coefficient.of(k * (a - k), b);
560 }
561 };
562
563 return 1 / GeneralizedContinuedFraction.value(z - a + 1, gen, EPSILON, MAX_ITERATIONS);
564 };
565 } else {
566 throw new IllegalStateException("unknown: " + implementation);
567 }
568 }
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596 abstract static class ContinuedFraction {
597
598
599
600
601
602
603
604
605 protected abstract double getA(int n, double x);
606
607
608
609
610
611
612
613
614
615 protected abstract double getB(int n, double x);
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642 public double evaluate(double x, double epsilon, int maxIterations) {
643
644
645 final double eps = epsilon > EPSILON ? epsilon : EPSILON;
646
647 double hPrev = updateIfCloseToZero(getB(0, x));
648
649 int n = 1;
650 double dPrev = 0.0;
651 double cPrev = hPrev;
652 double hN;
653
654 while (n <= maxIterations) {
655 final double a = getA(n, x);
656 final double b = getB(n, x);
657
658 double dN = updateIfCloseToZero(b + a * dPrev);
659 final double cN = updateIfCloseToZero(b + a / cPrev);
660
661 dN = 1 / dN;
662 final double deltaN = cN * dN;
663 hN = hPrev * deltaN;
664
665 if (!Double.isFinite(hN)) {
666 throw new ArithmeticException(String.format(
667 MSG_DIVERGED, hN, x));
668 }
669
670
671 if (deltaN == 0) {
672 throw new ArithmeticException();
673 }
674
675 if (Math.abs(deltaN - 1) < eps) {
676 return hN;
677 }
678
679 dPrev = dN;
680 cPrev = cN;
681 hPrev = hN;
682 ++n;
683 }
684
685 throw new ArithmeticException(MSG_MAX_ITERATIONS + maxIterations);
686 }
687 }
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703 abstract static class ContinuedFractionA extends ContinuedFraction {
704 @Override
705 public double evaluate(double x, double epsilon, int maxIterations) {
706
707
708 final double eps = epsilon > EPSILON ? epsilon : EPSILON;
709
710 final double a0 = getA(0, x);
711
712 double hPrev = updateIfCloseToZero(getB(0, x));
713
714 int n = 1;
715 double dPrev = 0.0;
716 double cPrev = hPrev;
717 double hN;
718
719 while (n <= maxIterations) {
720 final double a = getA(n, x);
721 final double b = getB(n, x);
722
723 double dN = updateIfCloseToZero(b + a * dPrev);
724 final double cN = updateIfCloseToZero(b + a / cPrev);
725
726 dN = 1 / dN;
727 final double deltaN = cN * dN;
728 hN = hPrev * deltaN;
729
730 if (!Double.isFinite(hN)) {
731 throw new ArithmeticException(String.format(
732 MSG_DIVERGED, hN, x));
733 }
734
735 if (deltaN == 0) {
736 throw new ArithmeticException();
737 }
738
739 if (Math.abs(deltaN - 1) < eps) {
740
741 return a0 / hN;
742 }
743
744 dPrev = dN;
745 cPrev = cN;
746 hPrev = hN;
747 ++n;
748 }
749
750 throw new ArithmeticException(MSG_MAX_ITERATIONS + maxIterations);
751 }
752 }
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768 abstract static class ContinuedFractionA1 extends ContinuedFraction {
769 @Override
770 public double evaluate(double x, double epsilon, int maxIterations) {
771
772
773 final double eps = epsilon > EPSILON ? epsilon : EPSILON;
774
775 final double a0 = getA(1, x);
776
777 double hPrev = updateIfCloseToZero(getB(1, x));
778
779 int n = 2;
780 double dPrev = 0.0;
781 double cPrev = hPrev;
782 double hN;
783
784 while (n <= maxIterations) {
785 final double a = getA(n, x);
786 final double b = getB(n, x);
787
788 double dN = updateIfCloseToZero(b + a * dPrev);
789 final double cN = updateIfCloseToZero(b + a / cPrev);
790
791 dN = 1 / dN;
792 final double deltaN = cN * dN;
793 hN = hPrev * deltaN;
794
795 if (!Double.isFinite(hN)) {
796 throw new ArithmeticException(String.format(
797 MSG_DIVERGED, hN, x));
798 }
799
800 if (deltaN == 0) {
801 throw new ArithmeticException();
802 }
803
804 if (Math.abs(deltaN - 1) < eps) {
805
806 return a0 / hN;
807 }
808
809 dPrev = dN;
810 cPrev = cN;
811 hPrev = hN;
812 ++n;
813 }
814
815 throw new ArithmeticException(MSG_MAX_ITERATIONS + maxIterations);
816 }
817 }
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832 abstract static class ContinuedFractionIterator {
833
834 private double a = 1;
835
836 private double b = 1;
837
838
839
840
841
842 protected void setCoefficients(double ca, double cb) {
843 this.a = ca;
844 this.b = cb;
845 }
846
847
848
849
850 abstract void next();
851
852
853
854
855
856
857
858
859 public double evaluate(double epsilon, int maxIterations) {
860
861
862 final double eps = epsilon > EPSILON ? epsilon : EPSILON;
863
864 next();
865 final double a0 = a;
866
867 double hPrev = updateIfCloseToZero(b);
868
869 int n = 2;
870 double dPrev = 0.0;
871 double cPrev = hPrev;
872 double hN;
873
874 while (n <= maxIterations) {
875 next();
876
877 double dN = updateIfCloseToZero(b + a * dPrev);
878 final double cN = updateIfCloseToZero(b + a / cPrev);
879
880 dN = 1 / dN;
881 final double deltaN = cN * dN;
882 hN = hPrev * deltaN;
883
884 if (!Double.isFinite(hN)) {
885 throw new ArithmeticException("Continued fraction diverged to: " + hN);
886 }
887
888 if (deltaN == 0) {
889 throw new ArithmeticException();
890 }
891
892
893
894
895 if (Math.abs(deltaN - 1) <= eps) {
896
897 return a0 / hN;
898 }
899
900 dPrev = dN;
901 cPrev = cN;
902 hPrev = hN;
903 ++n;
904 }
905
906 throw new ArithmeticException(MSG_MAX_ITERATIONS + maxIterations);
907 }
908 }
909
910
911
912
913
914
915
916
917
918
919 private static double updateIfCloseToZero(double value) {
920 return Math.abs(value) < SMALL ? Math.copySign(SMALL, value) : value;
921 }
922 }
923
924
925
926
927
928
929 static double[][] getData() {
930 return Arrays.stream(A_Z).map(d -> d.clone()).toArray(double[][]::new);
931 }
932
933
934
935
936
937
938
939 private static void apply(DoubleBinaryOperator fun, Blackhole bh) {
940 for (int i = 0; i < A_Z.length; i++) {
941 final double[] az = A_Z[i];
942 bh.consume(fun.applyAsDouble(az[0], az[1]));
943 }
944 }
945
946
947
948
949
950
951
952
953
954
955 @Benchmark
956 public void evaluate(BaseData data, Blackhole bh) {
957 apply(data.getFunction(), bh);
958 }
959 }