UNPKG

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