-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsolve-quartic.cc
41 lines (32 loc) · 1.64 KB
/
solve-quartic.cc
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
//////////////////////
// solve-quartic.cc //
//////////////////////
#include "solve-quartic.h"
static std::complex<double> complex_sqrt(const std::complex<double> & z)
{
return pow(z, 1. / 2.);
}
static std::complex<double> complex_cbrt(const std::complex<double> & z)
{
return pow(z, 1. / 3.);
}
void solve_quartic(const std::complex<double> coefficients[5], std::complex<double> roots[4])
{
// The algorithm below was derived by solving the quartic in Mathematica, and simplifying the resulting expression by hand.
const std::complex<double> a = coefficients[4];
const std::complex<double> b = coefficients[3] / a;
const std::complex<double> c = coefficients[2] / a;
const std::complex<double> d = coefficients[1] / a;
const std::complex<double> e = coefficients[0] / a;
const std::complex<double> Q1 = c * c - 3. * b * d + 12. * e;
const std::complex<double> Q2 = 2. * c * c * c - 9. * b * c * d + 27. * d * d + 27. * b * b * e - 72. * c * e;
const std::complex<double> Q3 = 8. * b * c - 16. * d - 2. * b * b * b;
const std::complex<double> Q4 = 3. * b * b - 8. * c;
const std::complex<double> Q5 = complex_cbrt(Q2 / 2. + complex_sqrt(Q2 * Q2 / 4. - Q1 * Q1 * Q1));
const std::complex<double> Q6 = (Q1 / Q5 + Q5) / 3.;
const std::complex<double> Q7 = 2. * complex_sqrt(Q4 / 12. + Q6);
roots[0] = (-b - Q7 - complex_sqrt(4. * Q4 / 6. - 4. * Q6 - Q3 / Q7)) / 4.;
roots[1] = (-b - Q7 + complex_sqrt(4. * Q4 / 6. - 4. * Q6 - Q3 / Q7)) / 4.;
roots[2] = (-b + Q7 - complex_sqrt(4. * Q4 / 6. - 4. * Q6 + Q3 / Q7)) / 4.;
roots[3] = (-b + Q7 + complex_sqrt(4. * Q4 / 6. - 4. * Q6 + Q3 / Q7)) / 4.;
}