-
Notifications
You must be signed in to change notification settings - Fork 1
/
cubic.js
69 lines (57 loc) · 1.76 KB
/
cubic.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// https://github.com/BaseMax/CubicEquationCalculator
'use strict'
const cubicSolve = (a, b, c, d) => {
b /= a
c /= a
d /= a
let s, t
let q = (
3.0 * c - (b * b)
) / 9.0
const r = (
-(27.0 * d) + b * (
9.0 * c - 2.0 * (b * b)
)
) / 54.0
const discrim = q * q * q + r * r
const roots = [
{real: 0, i: 0},
{real: 0, i: 0},
{real: 0, i: 0}
]
const term1 = b / 3.0
// one root real, two are complex
if (discrim > 0) {
const temp = 1.0 / 3.0
s = r + Math.sqrt(discrim)
s = ((s < 0) ? -Math.pow(-s, temp) : Math.pow(s, temp))
t = r - Math.sqrt(discrim)
t = ((t < 0) ? -Math.pow(-t, temp) : Math.pow(t, temp))
roots[0].real = -term1 + s + t
roots[2].real = roots[1].real = - (term1 + ( (s + t) / 2.0 ))
roots[1].i = Math.sqrt(3.0) * (-t + s) / 2
roots[2].i = - roots[1].i
return roots
}
// The remaining options are all real
// All roots real, at least two are equal.
else if(discrim === 0) {
if(r < 0) {
const r13 = -Math.pow(-r, (1.0/3.0))
} else {
const r13 = Math.pow(r, (1.0/3.0))
}
roots[0].real = -term1 + 2.0 * r13
roots[2].real = roots[1].real = -(r13 + term1)
return roots
}
// Only option left is that all roots are real and unequal (to get here, q < 0)
else {
const dum1 = Math.acos(r / Math.sqrt(-q * -q * -q))
const temp = -term1 + 2.0 * Math.sqrt(-q)
roots[0].real = temp * Math.cos(dum1 / 3.0)
roots[1].real = temp * Math.cos((dum1 + 2.0 * Math.PI) / 3.0)
roots[2].real = temp * Math.cos((dum1 + 4.0 * Math.PI) / 3.0)
return roots
}
}