mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-20 22:39:50 -05:00
Add Van Wijngaarden–Dekker–Brent method for root finding, ported from Numerical Recipes in C.
This commit is contained in:
parent
29e57cc521
commit
b1e90efc9e
1 changed files with 70 additions and 7 deletions
|
@ -1,13 +1,6 @@
|
||||||
var MathUtils = new function() {
|
var MathUtils = new function() {
|
||||||
var maxDepth = 53; // MANT_DIGITS: 64 bit: 53 digits, 32 bit: 24 digits
|
var maxDepth = 53; // MANT_DIGITS: 64 bit: 53 digits, 32 bit: 24 digits
|
||||||
|
|
||||||
// Gauss-Legendre Numerical Integration, a Gauss.as port from Singularity:
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006-2007, Jim Armstrong (www.algorithmist.net)
|
|
||||||
// All Rights Reserved.
|
|
||||||
//
|
|
||||||
// Simplified and further optimised by Juerg Lehni.
|
|
||||||
|
|
||||||
var abscissa = [
|
var abscissa = [
|
||||||
-0.5773502692, 0.5773502692,
|
-0.5773502692, 0.5773502692,
|
||||||
-0.7745966692, 0.7745966692, 0,
|
-0.7745966692, 0.7745966692, 0,
|
||||||
|
@ -31,6 +24,11 @@ var MathUtils = new function() {
|
||||||
return {
|
return {
|
||||||
EPSILON: Math.pow(2, -maxDepth + 1),
|
EPSILON: Math.pow(2, -maxDepth + 1),
|
||||||
|
|
||||||
|
// Gauss-Legendre Numerical Integration, a Gauss.as port from Singularity:
|
||||||
|
//
|
||||||
|
// Copyright (c) 2006-2007, Jim Armstrong (www.algorithmist.net)
|
||||||
|
// All Rights Reserved.
|
||||||
|
|
||||||
gauss: function(f, a, b, n) {
|
gauss: function(f, a, b, n) {
|
||||||
n = Math.min(Math.max(n, 2), 8);
|
n = Math.min(Math.max(n, 2), 8);
|
||||||
|
|
||||||
|
@ -42,6 +40,71 @@ var MathUtils = new function() {
|
||||||
sum += f(ab2 + mul * abscissa[l + i]) * weight[l + i];
|
sum += f(ab2 + mul * abscissa[l + i]) * weight[l + i];
|
||||||
|
|
||||||
return mul * sum;
|
return mul * sum;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Van Wijngaarden–Dekker–Brent method for root finding
|
||||||
|
brent: function(f, a, b, tol) {
|
||||||
|
var c = b, d = 0, e = 0,
|
||||||
|
fa = f(a),
|
||||||
|
fb = f(b),
|
||||||
|
fc = fb;
|
||||||
|
|
||||||
|
for (var i = 1; i <= 16; i++) {
|
||||||
|
if ((fb > 0.0 && fc > 0.0) || (fb < 0.0 && fc < 0.0)) {
|
||||||
|
c = a;
|
||||||
|
fc = fa;
|
||||||
|
e = d = b - a;
|
||||||
|
}
|
||||||
|
if (Math.abs(fc) < Math.abs(fb)) {
|
||||||
|
a = b;
|
||||||
|
b = c;
|
||||||
|
c = a;
|
||||||
|
fa = fb;
|
||||||
|
fb = fc;
|
||||||
|
fc = fa;
|
||||||
|
}
|
||||||
|
var tol1 = 2 * MathUtils.EPSILON * Math.abs(b) + 0.5 * tol,
|
||||||
|
xm = 0.5 * (c - b);
|
||||||
|
if (Math.abs(xm) <= tol1 || fb == 0.0) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
if (Math.abs(e) >= tol1 && Math.abs(fa) > Math.abs(fb)) {
|
||||||
|
var p, q, r,
|
||||||
|
s = fb / fa;
|
||||||
|
if (a == c) {
|
||||||
|
p = 2.0 * xm * s;
|
||||||
|
q = 1.0 - s;
|
||||||
|
} else {
|
||||||
|
q = fa / fc;
|
||||||
|
r = fb / fc;
|
||||||
|
p = s * (2.0 * xm * q * (q - r) - (b - a) * (r - 1.0));
|
||||||
|
q = (q - 1.0) * (r - 1.0) * (s - 1.0);
|
||||||
|
}
|
||||||
|
if (p > 0.0)
|
||||||
|
q = -q;
|
||||||
|
p = Math.abs(p);
|
||||||
|
var min1 = 3.0 * xm * q - Math.abs(tol1 * q),
|
||||||
|
min2 = Math.abs(e * q);
|
||||||
|
if (2.0 * p < (min1 < min2 ? min1 : min2)) {
|
||||||
|
e = d;
|
||||||
|
d = p / q;
|
||||||
|
} else {
|
||||||
|
d = xm;
|
||||||
|
e = d;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
d = xm;
|
||||||
|
e = d;
|
||||||
|
}
|
||||||
|
a = b;
|
||||||
|
fa = fb;
|
||||||
|
if (Math.abs(d) > tol1)
|
||||||
|
b += d;
|
||||||
|
else
|
||||||
|
b += xm >= 0.0 ? Math.abs(tol1) : -Math.abs(tol1);
|
||||||
|
fb = f(b);
|
||||||
|
}
|
||||||
|
return b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue