Last active
November 19, 2022 10:22
-
-
Save jgphilpott/e483b5fbe52a7233c292f35737e5a682 to your computer and use it in GitHub Desktop.
A collection of functions for finding the roots of polynomials in JavaScript.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
findRoots = (y = 0, coefficients = []) -> | |
switch coefficients.length | |
when 0 | |
return null | |
when 1 | |
return uniFormula y, coefficients | |
when 2 | |
return linierFormula y, coefficients | |
when 3 | |
return quadraticFormula y, coefficients | |
when 4 | |
return cubicFormula y, coefficients | |
when 5 | |
return polyFormula y, coefficients | |
else | |
# Credit: https://math.stackexchange.com/a/200622/880755 | |
return "No general formula exists for polynomials of degree ≥ 5, see Abel–Ruffini theorem: https://en.wikipedia.org/wiki/Abel%E2%80%93Ruffini_theorem" | |
uniFormula = (y = 0, coefficients = []) -> | |
if y == coefficients[0] | |
return Infinity | |
else | |
return null | |
linierFormula = (y = 0, coefficients = []) -> | |
return [(y - coefficients[0]) / coefficients[1]] | |
# Credit: https://stackoverflow.com/a/33454565/1544937 | |
quadraticFormula = (y = 0, coefficients = []) -> | |
roots = [] | |
a = coefficients[2] | |
b = coefficients[1] | |
c = coefficients[0] - y | |
positiveRoot = (-b + Math.sqrt(Math.pow(b, 2) - (4 * a * c))) / (2 * a) | |
negativeRoot = (-b - Math.sqrt(Math.pow(b, 2) - (4 * a * c))) / (2 * a) | |
if not isNaN positiveRoot then roots.push positiveRoot | |
if not isNaN negativeRoot then if negativeRoot != positiveRoot then roots.push negativeRoot | |
return roots | |
# Credit: https://stackoverflow.com/a/27176424/1544937 | |
cubicFormula = (y = 0, coefficients = []) -> | |
roots = null | |
a = coefficients[3] | |
b = coefficients[2] | |
c = coefficients[1] | |
d = coefficients[0] - y | |
cuberoot = (x) -> | |
y = Math.pow(Math.abs(x), 1/3) | |
return if x < 0 then -y else y | |
if Math.abs(a) < 1e-8 # Quadratic case, ax^2 + bx + c = 0 | |
a = b | |
b = c | |
c = d | |
if Math.abs(a) < 1e-8 # Linear case, ax + b = 0 | |
a = b | |
b = c | |
if Math.abs(a) < 1e-8 # Degenerate case | |
return [] | |
return [-b / a] | |
D = (b * b) - (4 * a * c) | |
if Math.abs(D) < 1e-8 | |
return [-b / (2 * a)] | |
else if (D > 0) | |
return [(-b + Math.sqrt(D)) / (2 * a), (-b - Math.sqrt(D)) / (2 * a)] | |
return [] | |
p = (3*a*c - b*b) / (3*a*a) | |
q = (2*b*b*b - 9*a*b*c + 27*a*a*d) / (27*a*a*a) | |
if Math.abs(p) < 1e-8 | |
roots = [cuberoot(-q)] | |
else if Math.abs(q) < 1e-8 | |
roots = [0].concat(if p < 0 then [Math.sqrt(-p), -Math.sqrt(-p)] else []) | |
else | |
D = q*q/4 + p*p*p/27 | |
if Math.abs(D) < 1e-8 | |
roots = [-1.5*q/p, 3*q/p] | |
else if D > 0 | |
u = cuberoot(-q/2 - Math.sqrt(D)) | |
roots = [u - p / (3*u)] | |
else | |
u = 2 * Math.sqrt(-p / 3) | |
t = Math.acos(3*q/p/u) / 3 | |
k = 2 * Math.PI / 3 | |
roots = [u * Math.cos(t), u * Math.cos(t-k), u * Math.cos(t-2*k)] | |
for root in roots | |
root -= b / (3*a) | |
return roots | |
# Credit: https://stackoverflow.com/q/27217113/1544937 | |
polyFormula = (y = 0, coefficients = []) -> | |
return "https://en.wikipedia.org/wiki/Quartic_function" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Generated by CoffeeScript 2.7.0 | |
var cubicFormula, findRoots, linierFormula, polyFormula, quadraticFormula, uniFormula; | |
findRoots = function(y = 0, coefficients = []) { | |
switch (coefficients.length) { | |
case 0: | |
return null; | |
case 1: | |
return uniFormula(y, coefficients); | |
case 2: | |
return linierFormula(y, coefficients); | |
case 3: | |
return quadraticFormula(y, coefficients); | |
case 4: | |
return cubicFormula(y, coefficients); | |
case 5: | |
return polyFormula(y, coefficients); | |
default: | |
// Credit: https://math.stackexchange.com/a/200622/880755 | |
return "No general formula exists for polynomials of degree ≥ 5, see Abel–Ruffini theorem: https://en.wikipedia.org/wiki/Abel%E2%80%93Ruffini_theorem"; | |
} | |
}; | |
uniFormula = function(y = 0, coefficients = []) { | |
if (y === coefficients[0]) { | |
return 2e308; | |
} else { | |
return null; | |
} | |
}; | |
linierFormula = function(y = 0, coefficients = []) { | |
return [(y - coefficients[0]) / coefficients[1]]; | |
}; | |
// Credit: https://stackoverflow.com/a/33454565/1544937 | |
quadraticFormula = function(y = 0, coefficients = []) { | |
var a, b, c, negativeRoot, positiveRoot, roots; | |
roots = []; | |
a = coefficients[2]; | |
b = coefficients[1]; | |
c = coefficients[0] - y; | |
positiveRoot = (-b + Math.sqrt(Math.pow(b, 2) - (4 * a * c))) / (2 * a); | |
negativeRoot = (-b - Math.sqrt(Math.pow(b, 2) - (4 * a * c))) / (2 * a); | |
if (!isNaN(positiveRoot)) { | |
roots.push(positiveRoot); | |
} | |
if (!isNaN(negativeRoot)) { | |
if (negativeRoot !== positiveRoot) { | |
roots.push(negativeRoot); | |
} | |
} | |
return roots; | |
}; | |
// Credit: https://stackoverflow.com/a/27176424/1544937 | |
cubicFormula = function(y = 0, coefficients = []) { | |
var D, a, b, c, cuberoot, d, i, k, len, p, q, root, roots, t, u; | |
roots = null; | |
a = coefficients[3]; | |
b = coefficients[2]; | |
c = coefficients[1]; | |
d = coefficients[0] - y; | |
cuberoot = function(x) { | |
y = Math.pow(Math.abs(x), 1 / 3); | |
if (x < 0) { | |
return -y; | |
} else { | |
return y; | |
} | |
}; | |
if (Math.abs(a) < 1e-8) { // Quadratic case, ax^2 + bx + c = 0 | |
a = b; | |
b = c; | |
c = d; | |
if (Math.abs(a) < 1e-8) { // Linear case, ax + b = 0 | |
a = b; | |
b = c; | |
if (Math.abs(a) < 1e-8) { // Degenerate case | |
return []; | |
} | |
return [-b / a]; | |
} | |
D = (b * b) - (4 * a * c); | |
if (Math.abs(D) < 1e-8) { | |
return [-b / (2 * a)]; | |
} else if (D > 0) { | |
return [(-b + Math.sqrt(D)) / (2 * a), (-b - Math.sqrt(D)) / (2 * a)]; | |
} | |
return []; | |
} | |
p = (3 * a * c - b * b) / (3 * a * a); | |
q = (2 * b * b * b - 9 * a * b * c + 27 * a * a * d) / (27 * a * a * a); | |
if (Math.abs(p) < 1e-8) { | |
roots = [cuberoot(-q)]; | |
} else if (Math.abs(q) < 1e-8) { | |
roots = [0].concat(p < 0 ? [Math.sqrt(-p), -Math.sqrt(-p)] : []); | |
} else { | |
D = q * q / 4 + p * p * p / 27; | |
if (Math.abs(D) < 1e-8) { | |
roots = [-1.5 * q / p, 3 * q / p]; | |
} else if (D > 0) { | |
u = cuberoot(-q / 2 - Math.sqrt(D)); | |
roots = [u - p / (3 * u)]; | |
} else { | |
u = 2 * Math.sqrt(-p / 3); | |
t = Math.acos(3 * q / p / u) / 3; | |
k = 2 * Math.PI / 3; | |
roots = [u * Math.cos(t), u * Math.cos(t - k), u * Math.cos(t - 2 * k)]; | |
} | |
} | |
for (i = 0, len = roots.length; i < len; i++) { | |
root = roots[i]; | |
root -= b / (3 * a); | |
} | |
return roots; | |
}; | |
// Credit: https://stackoverflow.com/q/27217113/1544937 | |
polyFormula = function(y = 0, coefficients = []) { | |
return "https://en.wikipedia.org/wiki/Quartic_function"; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment