#include <stdio.h>
#include <stdlib.h>
#include <complex.h>
#include <tgmath.h>
/*
* Configuration
*/
#define DR double
typedef complex DR D;
// Enable this to let you select which of the 3 complex cube roots to use
// #define TEST_CUBEROOT
/*
* Output
*/
#define DUMP(var) dump(#var, var)
void dumpreal(char const *name, DR var)
{
printf("%s = %f\n", name
, var
); }
void dump(char const *name, D var)
{
dumpreal
(name
, creal(var
)); else
}
/*
* Cube root calculation
*/
#ifdef TEST_CUBEROOT
void ccbrt(D var, D roots[static 3])
{
//DUMP(var); DUMP(mod); DUMP(exp);
//dump("pow result", pow(var, 1./3));
// atan2 computes in interval [-pi, pi]; convert to [0, 2pi]
//DUMP(exp);
// Three cube roots
for (int r = 0; r < 3; ++r)
{
DR cr_mod = cbrt(mod);
DR cr_exp
= (exp + r
*2*pi
) / 3;
roots
[r
] = cr_mod
* (cos(cr_exp
) + I
*sin(cr_exp
));
//DUMP(cr_mod);
//DUMP(cr_exp);
//DUMP(roots[r]);
}
//exit(0);
}
#endif
/*
* Quartic solver using Wikipedia algorithm
*/
int main()
{
// Inputs from http://m...content-available-to-author-only...e.com/questions/1796015/need-help-solving-x4-3x3-11x23x10-0/
D a = 1, b = -3, c = -11, d = 3, e = 10;
// Solve
D p = (8*a*c - 3*b*b) / (8*a*a);
D q = (b*b*b - 4*a*b*c + 8*a*a*d) / (8*a*a*a);
D d0 = c*c - 3*b*d + 12*a*e;
D d1 = 2*c*c*c - 9*b*c*d + 27*b*b*e + 27*a*d*d - 72*a*c*e;
D disc = d1*d1 - 4*d0*d0*d0;
D discsq
= sqrt(disc
); // can negate this
D Q3 = (d1 + discsq) / 2;
#ifdef TEST_CUBEROOT
D Qx[3];
ccbrt(Q3, Qx);
Q = Qx[1]; // Choose 0,1,2 here to taste
#endif
D S2 = -p*2/3 + (Q + d0/Q) / (3*a);
D qdp = -4*S*S - 2*p + q/S;
D qdn = -4*S*S - 2*p - q/S;
D x1 = -b/(4*a) - S + qdpsq/2;
D x2 = -b/(4*a) - S - qdpsq/2;
D x3 = -b/(4*a) + S + qdnsq/2;
D x4 = -b/(4*a) + S - qdnsq/2;
DUMP(p);
DUMP(q);
DUMP(d0);
DUMP(d1);
DUMP(disc);
DUMP(discsq);
DUMP(Q3);
DUMP(Q);
#ifdef TEST_CUBEROOT
DUMP(Qx[0]);
DUMP(Qx[1]);
DUMP(Qx[2]);
#endif
DUMP(S2);
DUMP(S);
DUMP(qdp);
DUMP(qdn);
DUMP(x1);
DUMP(x2);
DUMP(x3);
DUMP(x4);
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPGNvbXBsZXguaD4KI2luY2x1ZGUgPHRnbWF0aC5oPgoKLyoKICogQ29uZmlndXJhdGlvbgogKi8KI2RlZmluZSBEUiBkb3VibGUKdHlwZWRlZiBjb21wbGV4IERSIEQ7CgovLyBFbmFibGUgdGhpcyB0byBsZXQgeW91IHNlbGVjdCB3aGljaCBvZiB0aGUgMyBjb21wbGV4IGN1YmUgcm9vdHMgdG8gdXNlCi8vICNkZWZpbmUgVEVTVF9DVUJFUk9PVAoKLyoKICogT3V0cHV0CiAqLwojZGVmaW5lIERVTVAodmFyKSBkdW1wKCN2YXIsIHZhcikKCnZvaWQgZHVtcHJlYWwoY2hhciBjb25zdCAqbmFtZSwgRFIgdmFyKQp7CglwcmludGYoIiVzID0gJWZcbiIsIG5hbWUsIHZhcik7Cn0KCnZvaWQgZHVtcChjaGFyIGNvbnN0ICpuYW1lLCBEIHZhcikKewoJaWYgKCBjYWJzKGNpbWFnKHZhcikpIDwgMC4wMDAwMDAwMSApCgkJZHVtcHJlYWwobmFtZSwgY3JlYWwodmFyKSk7CgllbHNlCgkJcHJpbnRmKCIlcyA9ICglZiwlZilcbiIsIG5hbWUsIGNyZWFsKHZhciksIGNpbWFnKHZhcikpOwp9CgovKgogKiBDdWJlIHJvb3QgY2FsY3VsYXRpb24KICovCiNpZmRlZiBURVNUX0NVQkVST09UCnZvaWQgY2NicnQoRCB2YXIsIEQgcm9vdHNbc3RhdGljIDNdKQp7CglEUiBtb2QgPSBzcXJ0KCBjcmVhbCh2YXIpICogY3JlYWwodmFyKSArIGNpbWFnKHZhcikgKiBjaW1hZyh2YXIpICk7CglEUiBleHAgPSBhdGFuMihjaW1hZyh2YXIpLCBjcmVhbCh2YXIpKTsKCURSIHBpID0gYWNvcygtMS4wKTsKCgkvL0RVTVAodmFyKTsgRFVNUChtb2QpOyBEVU1QKGV4cCk7CgkvL2R1bXAoInBvdyByZXN1bHQiLCBwb3codmFyLCAxLi8zKSk7CgovLyBhdGFuMiBjb21wdXRlcyBpbiBpbnRlcnZhbCBbLXBpLCBwaV07IGNvbnZlcnQgdG8gWzAsIDJwaV0KCWlmICggZXhwIDwgMCApCgkJZXhwICs9IDIqcGk7CgoJLy9EVU1QKGV4cCk7CgovLyBUaHJlZSBjdWJlIHJvb3RzCglmb3IgKGludCByID0gMDsgciA8IDM7ICsrcikKCXsKCQlEUiBjcl9tb2QgPSBjYnJ0KG1vZCk7CgkJRFIgY3JfZXhwID0gKGV4cCArIHIqMipwaSkgLyAzOwoKCQlyb290c1tyXSA9IGNyX21vZCAqIChjb3MoY3JfZXhwKSArIEkqc2luKGNyX2V4cCkpOwoKCQkvL0RVTVAoY3JfbW9kKTsKCQkvL0RVTVAoY3JfZXhwKTsKCQkvL0RVTVAocm9vdHNbcl0pOwoJfQoJLy9leGl0KDApOwp9CiNlbmRpZgoKLyoKICogUXVhcnRpYyBzb2x2ZXIgdXNpbmcgV2lraXBlZGlhIGFsZ29yaXRobQogKi8KaW50IG1haW4oKQp7Ci8vIElucHV0cyBmcm9tIGh0dHA6Ly9tLi4uY29udGVudC1hdmFpbGFibGUtdG8tYXV0aG9yLW9ubHkuLi5lLmNvbS9xdWVzdGlvbnMvMTc5NjAxNS9uZWVkLWhlbHAtc29sdmluZy14NC0zeDMtMTF4MjN4MTAtMC8KCUQgYSA9IDEsIGIgPSAtMywgYyA9IC0xMSwgZCA9IDMsIGUgPSAxMDsKCi8vIFNvbHZlCglEIHAgPSAoOCphKmMgLSAzKmIqYikgLyAoOCphKmEpOwoJRCBxID0gKGIqYipiIC0gNCphKmIqYyArIDgqYSphKmQpIC8gKDgqYSphKmEpOwoKCUQgZDAgPSBjKmMgLSAzKmIqZCArIDEyKmEqZTsKCUQgZDEgPSAyKmMqYypjIC0gOSpiKmMqZCArIDI3KmIqYiplICsgMjcqYSpkKmQgLSA3MiphKmMqZTsKCglEIGRpc2MgPSBkMSpkMSAtIDQqZDAqZDAqZDA7CglEIGRpc2NzcSA9IHNxcnQoZGlzYyk7CQkvLyBjYW4gbmVnYXRlIHRoaXMKCglEIFEzID0gKGQxICsgZGlzY3NxKSAvIDI7CglEIFEgPSBwb3coUTMsIDEuLzMpOwoKI2lmZGVmIFRFU1RfQ1VCRVJPT1QKCUQgUXhbM107CgljY2JydChRMywgUXgpOwoJUSA9IFF4WzFdOwkJLy8gQ2hvb3NlIDAsMSwyIGhlcmUgdG8gdGFzdGUKI2VuZGlmCgoJRCBTMiA9IC1wKjIvMyArIChRICsgZDAvUSkgLyAoMyphKTsKCUQgUyA9IDAuNSAqIHNxcnQoUzIpOwoKCUQgcWRwID0gLTQqUypTIC0gMipwICsgcS9TOwoJRCBxZHBzcSA9IHNxcnQocWRwKTsKCglEIHFkbiA9IC00KlMqUyAtIDIqcCAtIHEvUzsKCUQgcWRuc3EgPSBzcXJ0KHFkbik7CgoJRCB4MSA9IC1iLyg0KmEpIC0gUyArIHFkcHNxLzI7CglEIHgyID0gLWIvKDQqYSkgLSBTIC0gcWRwc3EvMjsKCUQgeDMgPSAtYi8oNCphKSArIFMgKyBxZG5zcS8yOwoJRCB4NCA9IC1iLyg0KmEpICsgUyAtIHFkbnNxLzI7CgoJRFVNUChwKTsKCURVTVAocSk7CglEVU1QKGQwKTsKCURVTVAoZDEpOwoJRFVNUChkaXNjKTsKCURVTVAoZGlzY3NxKTsKCURVTVAoUTMpOwoJRFVNUChRKTsKI2lmZGVmIFRFU1RfQ1VCRVJPT1QKCURVTVAoUXhbMF0pOwoJRFVNUChReFsxXSk7CglEVU1QKFF4WzJdKTsKI2VuZGlmCglEVU1QKFMyKTsKCURVTVAoUyk7CglEVU1QKHFkcCk7CglEVU1QKHFkbik7CglEVU1QKHgxKTsKCURVTVAoeDIpOwoJRFVNUCh4Myk7CglEVU1QKHg0KTsKfQo=