114 lines
2.8 KiB
JavaScript
114 lines
2.8 KiB
JavaScript
'use strict';
|
|
|
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
|
/**
|
|
* @copyright 2013 Sonia Keys
|
|
* @copyright 2016 commenthol
|
|
* @license MIT
|
|
* @module iterate
|
|
*/
|
|
/**
|
|
* Iterate: Chapter 5, Iteration.
|
|
*
|
|
* This package is best considered illustrative. While the functions are
|
|
* usable, they are minimal in showing the points of the chapter text. More
|
|
* robust functions would handle more cases of overflow, loss of precision,
|
|
* and divergence.
|
|
*/
|
|
|
|
/**
|
|
* decimalPlaces iterates to a fixed number of decimal places.
|
|
*
|
|
* Inputs are an improvement function, a starting value, the number of
|
|
* decimal places desired in the result, and an iteration limit.
|
|
*
|
|
* @throws Error
|
|
* @param {Function} better
|
|
* @param {Number} start - (float)
|
|
* @param {Number} places - (int)
|
|
* @param {Number} maxIterations - (int)
|
|
* @returns {Number}
|
|
*/
|
|
function decimalPlaces (better, start, places, maxIterations) {
|
|
const d = Math.pow(10, -places);
|
|
for (let i = 0; i < maxIterations; i++) {
|
|
const n = better(start);
|
|
if (Math.abs(n - start) < d) {
|
|
return n
|
|
}
|
|
start = n;
|
|
}
|
|
throw new Error('Maximum iterations reached')
|
|
}
|
|
|
|
/**
|
|
* fullPrecison iterates to (nearly) the full precision of a float64.
|
|
*
|
|
* To allow for a little bit of floating point jitter, FullPrecision iterates
|
|
* to 15 significant figures, which is the maximum number of full significant
|
|
* figures representable in a float64, but still a couple of bits shy of the
|
|
* full representable precision.
|
|
*
|
|
* @throws Error
|
|
* @param {Function} better
|
|
* @param {Number} start - (float)
|
|
* @param {Number} maxIterations - (int)
|
|
* @returns {Number}
|
|
*/
|
|
function fullPrecision (better, start, maxIterations) {
|
|
for (let i = 0; i < maxIterations; i++) {
|
|
const n = better(start);
|
|
if (Math.abs((n - start) / n) < 1e-15) {
|
|
return n
|
|
}
|
|
start = n;
|
|
}
|
|
throw new Error('Maximum iterations reached')
|
|
}
|
|
|
|
/**
|
|
* binaryRoot finds a root between given bounds by binary search.
|
|
*
|
|
* Inputs are a function on x and the bounds on x. A root must exist between
|
|
* the given bounds, otherwise the result is not meaningful.
|
|
*
|
|
* @param {Function} f - root function
|
|
* @param {Number} lower - (float)
|
|
* @param {Number} upper - (float)
|
|
* @returns {Number}
|
|
*/
|
|
function binaryRoot (f, lower, upper) {
|
|
let yLower = f(lower);
|
|
let mid = 0;
|
|
for (let j = 0; j < 52; j++) {
|
|
mid = (lower + upper) / 2;
|
|
const yMid = f(mid);
|
|
if (yMid === 0) {
|
|
break
|
|
}
|
|
if (signbit(yLower) === signbit(yMid)) {
|
|
lower = mid;
|
|
yLower = yMid;
|
|
} else {
|
|
upper = mid;
|
|
}
|
|
}
|
|
return mid
|
|
}
|
|
|
|
function signbit (v) {
|
|
return (v < 0)
|
|
}
|
|
|
|
var iterate = {
|
|
decimalPlaces,
|
|
fullPrecision,
|
|
binaryRoot
|
|
};
|
|
|
|
exports.binaryRoot = binaryRoot;
|
|
exports.decimalPlaces = decimalPlaces;
|
|
exports["default"] = iterate;
|
|
exports.fullPrecision = fullPrecision;
|