31#include <gsl/gsl_math.h>
32#include <gsl/gsl_complex.h>
33#include <gsl/gsl_complex_math.h>
34#include <gsl/gsl_poly.h>
36#define SWAP(a,b) do { gsl_complex tmp = b ; b = a ; a = tmp ; } while(0)
40 gsl_complex * z0, gsl_complex * z1,
41 gsl_complex * z2, gsl_complex * z3)
44 static constexpr double ZeroTolerance = 1
e-15;
46 gsl_complex i, zarr[4], w1, w2, w3;
47 double r4 = 1.0 / 4.0;
48 double q2 = 1.0 / 2.0, q4 = 1.0 / 4.0, q8 = 1.0 / 8.0;
49 double q1 = 3.0 / 8.0, q3 = 3.0 / 16.0;
50 double u[3],
v[3],
v1,
v2, disc, disc_tol;
51 double aa, pp, qq, rr, rc, sc, tc,
q,
h;
52 int k1 = 0, k2 = 0, mt;
54 GSL_SET_COMPLEX (&i, 0.0, 1.0);
55 GSL_SET_COMPLEX (&zarr[0], 0.0, 0.0);
56 GSL_SET_COMPLEX (&zarr[1], 0.0, 0.0);
57 GSL_SET_COMPLEX (&zarr[2], 0.0, 0.0);
58 GSL_SET_COMPLEX (&zarr[3], 0.0, 0.0);
59 GSL_SET_COMPLEX (&w1, 0.0, 0.0);
60 GSL_SET_COMPLEX (&w2, 0.0, 0.0);
61 GSL_SET_COMPLEX (&w3, 0.0, 0.0);
71 GSL_SET_COMPLEX (z0, -
a, 0.0);
72 GSL_SET_COMPLEX (z1, 0.0, 0.0);
73 GSL_SET_COMPLEX (z2, 0.0, 0.0);
74 GSL_SET_COMPLEX (z3, 0.0, 0.0);
78 GSL_SET_COMPLEX (z0, 0.0, 0.0);
79 GSL_SET_COMPLEX (z1, 0.0, 0.0);
80 GSL_SET_COMPLEX (z2, 0.0, 0.0);
81 GSL_SET_COMPLEX (z3, -
a, 0.0);
89 double sqrt_d = sqrt (
d);
90 gsl_complex i_sqrt_d = gsl_complex_mul_real (i, sqrt_d);
91 gsl_complex minus_i = gsl_complex_conjugate (i);
92 *z3 = gsl_complex_sqrt (i_sqrt_d);
93 *z2 = gsl_complex_mul (minus_i, *z3);
94 *z1 = gsl_complex_negative (*z2);
95 *z0 = gsl_complex_negative (*z3);
99 double sqrt_abs_d = sqrt (-
d);
100 *z3 = gsl_complex_sqrt_real (sqrt_abs_d);
101 *z2 = gsl_complex_mul (i, *z3);
102 *z1 = gsl_complex_negative (*z2);
103 *z0 = gsl_complex_negative (*z3);
109 if (0.0 ==
c && 0.0 ==
d)
111 disc = (
a *
a - 4.0 *
b);
122 gsl_poly_complex_solve_quadratic (1.0,
a,
b, z2, z3);
130 qq =
c - q2 *
a * (
b - q4 * aa);
131 rr =
d - q4 * (
a *
c - q4 * aa * (
b - q3 * aa));
133 sc = q4 * (q4 * pp * pp - rr);
134 tc = -(q8 * qq * q8 * qq);
145 double qcub = (rc * rc - 3 * sc);
146 double rcub = (2 * rc * rc * rc - 9 * rc * sc + 27 * tc);
149 double R = rcub / 54;
151 double Q3 = Q * Q * Q;
155 disc_tol = std::max(ZeroTolerance, ZeroTolerance * (fabs(
R2) + fabs(Q3)));
158 if (0 ==
R && 0 == Q)
164 else if (fabs(disc) < disc_tol)
167 double sqrtQ = sqrt (Q);
170 u[0] = -2 * sqrtQ - rc / 3;
171 u[1] = sqrtQ - rc / 3;
172 u[2] = sqrtQ - rc / 3;
176 u[0] = -sqrtQ - rc / 3;
177 u[1] = -sqrtQ - rc / 3;
178 u[2] = 2 * sqrtQ - rc / 3;
183 double sqrtQ = sqrt (Q);
184 double sqrtQ3 = sqrtQ * sqrtQ * sqrtQ;
185 double ctheta =
R / sqrtQ3;
188 if ( fabs(ctheta) < 1.0 )
189 theta = acos( ctheta);
190 else if ( ctheta <= -1.0)
193 double norm = -2 * sqrtQ;
195 u[0] = norm * cos (theta / 3) - rc / 3;
196 u[1] = norm * cos ((theta + 2.0 *
M_PI) / 3) - rc / 3;
197 u[2] = norm * cos ((theta - 2.0 *
M_PI) / 3) - rc / 3;
201 double sgnR = (
R >= 0 ? 1 : -1);
202 double modR = fabs (
R);
203 double sqrt_disc = sqrt (disc);
204 double A = -sgnR * pow (modR + sqrt_disc, 1.0 / 3.0);
207 double mod_diffAB = fabs (A - B);
208 u[0] = A + B - rc / 3;
209 u[1] = -0.5 * (A + B) - rc / 3;
210 u[2] = -(sqrt (3.0) / 2.0) * mod_diffAB;
223 if (disc_tol >= disc)
259 w1 = gsl_complex_sqrt_real (u[k1]);
260 w2 = gsl_complex_sqrt_real (u[k2]);
265 GSL_SET_COMPLEX (&w1, u[1], u[2]);
266 GSL_SET_COMPLEX (&w2, u[1], -u[2]);
267 w1 = gsl_complex_sqrt (w1);
268 w2 = gsl_complex_sqrt (w2);
273 gsl_complex prod_w = gsl_complex_mul (w1, w2);
278 double mod_prod_w = gsl_complex_abs (prod_w);
279 if (0.0 != mod_prod_w)
281 gsl_complex inv_prod_w = gsl_complex_inverse (prod_w);
282 w3 = gsl_complex_mul_real (inv_prod_w, -
q / 8.0);
286 gsl_complex sum_w12 = gsl_complex_add (w1, w2);
287 gsl_complex neg_sum_w12 = gsl_complex_negative (sum_w12);
288 gsl_complex sum_w123 = gsl_complex_add (sum_w12, w3);
289 gsl_complex neg_sum_w123 = gsl_complex_add (neg_sum_w12, w3);
291 gsl_complex diff_w12 = gsl_complex_sub (w2, w1);
292 gsl_complex neg_diff_w12 = gsl_complex_negative (diff_w12);
293 gsl_complex diff_w123 = gsl_complex_sub (diff_w12, w3);
294 gsl_complex neg_diff_w123 = gsl_complex_sub (neg_diff_w12, w3);
296 zarr[0] = gsl_complex_add_real (sum_w123, -
h);
297 zarr[1] = gsl_complex_add_real (neg_sum_w123, -
h);
298 zarr[2] = gsl_complex_add_real (diff_w123, -
h);
299 zarr[3] = gsl_complex_add_real (neg_diff_w123, -
h);
304 if (u[k1] >= 0 && u[k2] >= 0)
307 GSL_SET_COMPLEX (z0, GSL_REAL (zarr[0]), 0.0);
308 GSL_SET_COMPLEX (z1, GSL_REAL (zarr[1]), 0.0);
309 GSL_SET_COMPLEX (z2, GSL_REAL (zarr[2]), 0.0);
310 GSL_SET_COMPLEX (z3, GSL_REAL (zarr[3]), 0.0);
312 else if (u[k1] >= 0 && u[k2] < 0)
319 else if (u[k1] < 0 && u[k2] >= 0)
326 else if (u[k1] < 0 && u[k2] < 0)
336 GSL_SET_COMPLEX (z0, GSL_REAL (zarr[0]), 0.0);
337 GSL_SET_COMPLEX (z1, GSL_REAL (zarr[1]), 0.0);
351 if (GSL_REAL (*z0) > GSL_REAL (*z1))
SWAP (*z0, *z1);
352 if (GSL_REAL (*z0) > GSL_REAL (*z2))
SWAP (*z0, *z2);
353 if (GSL_REAL (*z0) > GSL_REAL (*z3))
SWAP (*z0, *z3);
355 if (GSL_REAL (*z1) > GSL_REAL (*z2))
SWAP (*z1, *z2);
356 if (GSL_REAL (*z2) > GSL_REAL (*z3))
359 if (GSL_REAL (*z1) > GSL_REAL (*z2))
SWAP (*z1, *z2);
366 if (GSL_REAL (*z0) > GSL_REAL (*z2))
372 if (GSL_IMAG (*z0) > GSL_IMAG (*z1))
SWAP (*z0, *z1);
373 if (GSL_IMAG (*z2) > GSL_IMAG (*z3))
SWAP (*z2, *z3);
380 if (GSL_IMAG (*z2) > GSL_IMAG (*z3))
SWAP (*z2, *z3);
383 if (GSL_REAL (*z0) > GSL_REAL (*z1))
SWAP (*z0, *z1);
384 if (GSL_REAL (*z1) > GSL_REAL (*z2))
386 if (GSL_REAL (*z0) > GSL_REAL (*z2))
#define R(a, b, c, d, e, f, g, h, i)
int gsl_poly_complex_solve_quartic(double a, double b, double c, double d, gsl_complex *z0, gsl_complex *z1, gsl_complex *z2, gsl_complex *z3)
#define R2(v, w, x, y, z, i)