UNPKG

@tubular/math

Version:
121 lines 3.71 kB
import { abs } from './math'; const CGOLD = 0.381966011250105; // (3 - sqrt(5)) / 2 const ZEPS = 1.0E-20; export class MinMaxFinder { constructor(minMaxSeekingFunction, tolerance, maxIterations, ax, bx, cx) { this.minMaxSeekingFunction = minMaxSeekingFunction; this.tolerance = tolerance; this.maxIterations = maxIterations; this.ax = ax; this.bx = bx; this.cx = cx; this._iterationCount = 0; this.isMin = true; } getXAtMinMax() { let a; let b; let d = 0.0; let etemp; let fu; let fv; let fw; let p; let q; let r; let tol1; let tol2; let u; let v; let w; let x; let xm; let e = 0.0; let sign = 1.0; a = (this.ax < this.cx ? this.ax : this.cx); b = (this.ax > this.cx ? this.ax : this.cx); x = w = v = this.bx; this.fx = this.minMaxSeekingFunction(x); // Reverse the sign of the evaluated function if we're searching for a max rather than a min. if (this.fx > this.minMaxSeekingFunction(this.ax)) { this.isMin = false; this.fx *= -1; sign = -1.0; } else this.isMin = true; fw = fv = this.fx; this._iterationCount = 0; while (++this._iterationCount <= this.maxIterations) { xm = 0.5 * (a + b); tol1 = this.tolerance * abs(x) + ZEPS; tol2 = 2.0 * tol1; if (abs(x - xm) <= tol2 - 0.5 * (b - a)) { this.fx *= sign; return x; } if (abs(e) > tol1) { r = (x - w) * (this.fx - fv); q = (x - v) * (this.fx - fw); p = (x - v) * q - (x - w) * r; q = 2.0 * (q - r); if (q > 0.0) p = -p; q = abs(q); etemp = e; e = d; if (abs(p) >= abs(0.5 * q * etemp) || p <= q * (a - x) || p >= q * (b - x)) { e = (x >= xm ? a - x : b - x); d = CGOLD * e; } else { d = p / q; u = x + d; if (u - a < tol2 || b - u < tol2) d = Math.sign(xm - x) * tol1; } } else { e = (x >= xm ? a - x : b - x); d = CGOLD * e; } u = (abs(d) >= tol1 ? x + d : x + Math.sign(d) * tol1); fu = sign * this.minMaxSeekingFunction(u); if (fu <= this.fx) { if (u >= x) a = x; else b = x; v = w; w = x; x = u; fv = fw; fw = this.fx; this.fx = fu; } else { if (u < x) a = u; else b = u; if (fu <= fw || w === x) { v = w; w = u; fv = fw; fw = fu; } else if (fu <= fv || v === x || v === w) { v = u; fv = fu; } } } this.fx *= sign; return x; } get foundMaximum() { return !this.isMin; } get foundMinimum() { return this.isMin; } get lastY() { return this.fx; } get iterationCount() { return this._iterationCount; } } //# sourceMappingURL=min-max-finder.js.map