1 | /**
|
2 | * @copyright 2013 Sonia Keys
|
3 | * @copyright 2016 commenthol
|
4 | * @license MIT
|
5 | * @module iterate
|
6 | */
|
7 | /**
|
8 | * Iterate: Chapter 5, Iteration.
|
9 | *
|
10 | * This package is best considered illustrative. While the functions are
|
11 | * usable, they are minimal in showing the points of the chapter text. More
|
12 | * robust functions would handle more cases of overflow, loss of precision,
|
13 | * and divergence.
|
14 | */
|
15 |
|
16 | /**
|
17 | * decimalPlaces iterates to a fixed number of decimal places.
|
18 | *
|
19 | * Inputs are an improvement function, a starting value, the number of
|
20 | * decimal places desired in the result, and an iteration limit.
|
21 | *
|
22 | * @throws Error
|
23 | * @param {Function} better
|
24 | * @param {Number} start - (float)
|
25 | * @param {Number} places - (int)
|
26 | * @param {Number} maxIterations - (int)
|
27 | * @returns {Number}
|
28 | */
|
29 | export function decimalPlaces(better, start, places, maxIterations) {
|
30 | var d = Math.pow(10, -places);
|
31 | for (var i = 0; i < maxIterations; i++) {
|
32 | var n = better(start);
|
33 | if (Math.abs(n - start) < d) {
|
34 | return n;
|
35 | }
|
36 | start = n;
|
37 | }
|
38 | throw new Error('Maximum iterations reached');
|
39 | }
|
40 |
|
41 | /**
|
42 | * fullPrecison iterates to (nearly) the full precision of a float64.
|
43 | *
|
44 | * To allow for a little bit of floating point jitter, FullPrecision iterates
|
45 | * to 15 significant figures, which is the maximum number of full significant
|
46 | * figures representable in a float64, but still a couple of bits shy of the
|
47 | * full representable precision.
|
48 | *
|
49 | * @throws Error
|
50 | * @param {Function} better
|
51 | * @param {Number} start - (float)
|
52 | * @param {Number} maxIterations - (int)
|
53 | * @returns {Number}
|
54 | */
|
55 | export function fullPrecision(better, start, maxIterations) {
|
56 | for (var i = 0; i < maxIterations; i++) {
|
57 | var n = better(start);
|
58 | if (Math.abs((n - start) / n) < 1e-15) {
|
59 | return n;
|
60 | }
|
61 | start = n;
|
62 | }
|
63 | throw new Error('Maximum iterations reached');
|
64 | }
|
65 |
|
66 | /**
|
67 | * binaryRoot finds a root between given bounds by binary search.
|
68 | *
|
69 | * Inputs are a function on x and the bounds on x. A root must exist between
|
70 | * the given bounds, otherwise the result is not meaningful.
|
71 | *
|
72 | * @param {Function} f - root function
|
73 | * @param {Number} lower - (float)
|
74 | * @param {Number} upper - (float)
|
75 | * @returns {Number}
|
76 | */
|
77 | export function binaryRoot(f, lower, upper) {
|
78 | var yLower = f(lower);
|
79 | var mid = 0;
|
80 | for (var j = 0; j < 52; j++) {
|
81 | mid = (lower + upper) / 2;
|
82 | var yMid = f(mid);
|
83 | if (yMid === 0) {
|
84 | break;
|
85 | }
|
86 | if (signbit(yLower) === signbit(yMid)) {
|
87 | lower = mid;
|
88 | yLower = yMid;
|
89 | } else {
|
90 | upper = mid;
|
91 | }
|
92 | }
|
93 | return mid;
|
94 | }
|
95 |
|
96 | function signbit(v) {
|
97 | return v < 0;
|
98 | }
|
99 |
|
100 | export default {
|
101 | decimalPlaces: decimalPlaces,
|
102 | fullPrecision: fullPrecision,
|
103 | binaryRoot: binaryRoot
|
104 | }; |
\ | No newline at end of file |