#include <stdio.h>
#include <math.h>
#define M_PI 3.141592653589793238
#define MATH_2PI (2*M_PI)
#define sgn_float(X) ((X>0)-(X<0)) // returns the sign of X (1 or -1); for floats, doubles
double roots_cubic_constrained(double pc[]){
double a,b,c; // coefficients of input polynomial
double Q, R, theta; // intermediate components of the numerical solution
double A, B; // intermediate value needed for the second case R^2>=Q^3
double x; // solution
// applies to cubic equation x3 + ax2 + bx + c = 0
if(pc[0]){ // ensure a cubic, so that we don't divide by 0
// pc[0] = 1;
a = pc[1] / pc[0]; // divide all coeffs by pc[0] to fit the form (making the coeff of x^3 to be 1)
b = pc[2] / pc[0];
c = pc[3] / pc[0];
// Q = (pc[1] * pc[1] - 3 * pc[2])/9; // component for the solution
// R = (2*pc[1]^3 - 9*px[1]*pc[2] + 27*pc[3])/54;
Q = (a*a - 3*b)/9; // (5.6.10)
R = (2*a*a*a - 9*a*b + 27*c)/54; // (5.6.10)
if((R*R) < (Q*Q*Q)){ // if true, then there are 3 real roots
x
= -2*sqrt(Q
)*cos(theta
/3) - a
/3; // (5.6.12) // if(0.99*(-8) < x & 1.01*(-4) > x){ // TODO use the fmcf floating pt comparison functions
if(-8 < x && -4 > x){ // use float comparison becasue exact comparison does not matter
return x;
}
x
= -2*sqrt(Q
)*cos((theta
+ MATH_2PI
)/3) - a
/3; // (5.6.12) // if(0.99*(-8) < x & 1.01*(-4) > x){
if(-8 < x && -4 > x){ // use float comparison becasue exact comparison does not matter
return x;
}
x
= -2*sqrt(Q
)*cos((theta
+ MATH_2PI
)/3) - a
/3; // (5.6.12) return x; // Paolo assures that there will be 1 root in the acceptable range
}
else{ // otherwise compute A (since Q and R are both real (since a,b,c are Real))
// A = -sgn(R)*[|R| + sqrt(R^2-Q^3)]^(1/3)
// A = fabs(R); // in order to compute sgn(R) via (R/A)
// A = -(R/A)*(A+sqrt(R^2-Q^3))^(1/3); // (5.6.15)
A = (R>0)-(R<0); // sign of R (sgn(R))
A = sgn_float(R); // sign of R
A
= -(A
)*cbrt
(fabs(R
)+sqrt(R
*R
-Q
*Q
*Q
)); // (5.6.15) if(0 == A){ // (5.6.16)
B = 0;
}
else{
B = Q/A;
}
x = (A+B)-(a/3); // (5.6.17) the single real root.
return x;
}
}
else { // use the quadratic equation
a = pc[1];
b = pc[2];
c = pc[3];
printf ("%f, %f, %f\n", a
,b
,c
);
R = b*b-4*a*c; // Use R as the discriminant
if(R >= 0){ // Should always be this case - otherwise there are no real roots
Q
= -(b
+ sgn_float
(b
)*sqrt(R
))/2; // (5.6.4) with 'Q' substituted for 'q' x = Q/a; // (5.6.5)
if(-8 < x && -4 > x){ // use float comparison becasue exact comparison does not matter
return x;
}
x = c/Q; // (5.6.5)
return x;
}
// else{
// print("ERRGG!!!")
// }
}
}
int main(void) {
// your code goes here
double temp[5];
double res;
// temp[0] = 100.123;
// temp[1] = .1234124;
// temp[2] = .000234567891234;
// temp[3] = .000000031415926535;
// temp[4] = 492314.1;
temp[0] = 1;
temp[1] = -5;
temp[2] = -21;
temp[3] = 145;
// res = pfit(&temp[2]);
// res = pfit((double *)&temp[2]);
res = roots_cubic_constrained(temp);
// printf("main \n%3.3lg %3.3g %3.3g \n", temp[0], temp[1], temp[2]);
return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxtYXRoLmg+CgojZGVmaW5lIE1fUEkJCQkJCTMuMTQxNTkyNjUzNTg5NzkzMjM4CiNkZWZpbmUgTUFUSF8yUEkgICAgICAgICAgICAgICAgKDIqTV9QSSkKI2RlZmluZSBzZ25fZmxvYXQoWCkgICAgICAgICAgICAoKFg+MCktKFg8MCkpICAgLy8gcmV0dXJucyB0aGUgc2lnbiBvZiBYICgxIG9yIC0xKTsgZm9yIGZsb2F0cywgZG91YmxlcwoKZG91YmxlIHJvb3RzX2N1YmljX2NvbnN0cmFpbmVkKGRvdWJsZSBwY1tdKXsKICAgIGRvdWJsZSBhLGIsYzsgICAgICAgICAgICAgICAvLyBjb2VmZmljaWVudHMgb2YgaW5wdXQgcG9seW5vbWlhbAogICAgZG91YmxlIFEsIFIsIHRoZXRhOyAgICAgICAgIC8vIGludGVybWVkaWF0ZSBjb21wb25lbnRzIG9mIHRoZSBudW1lcmljYWwgc29sdXRpb24KICAgIGRvdWJsZSBBLCBCOyAgICAgICAgICAgICAgICAvLyBpbnRlcm1lZGlhdGUgdmFsdWUgbmVlZGVkIGZvciB0aGUgc2Vjb25kIGNhc2UgUl4yPj1RXjMKICAgIGRvdWJsZSB4OyAgICAgICAgICAgICAgICAgICAvLyBzb2x1dGlvbgoKICAgIC8vIGFwcGxpZXMgdG8gY3ViaWMgZXF1YXRpb24geDMgKyBheDIgKyBieCArIGMgPSAwCiAgICBpZihwY1swXSl7ICAgICAgICAgICAgICAgICAgLy8gZW5zdXJlIGEgY3ViaWMsIHNvIHRoYXQgd2UgZG9uJ3QgZGl2aWRlIGJ5IDAKICAgICAgICAvLyBwY1swXSA9IDE7CiAgICAgICAgYSA9IHBjWzFdIC8gcGNbMF07ICAgICAvLyBkaXZpZGUgYWxsIGNvZWZmcyBieSBwY1swXSB0byBmaXQgdGhlIGZvcm0gKG1ha2luZyB0aGUgY29lZmYgb2YgeF4zIHRvIGJlIDEpCiAgICAgICAgYiA9IHBjWzJdIC8gcGNbMF07CiAgICAgICAgYyA9IHBjWzNdIC8gcGNbMF07CgogICAgICAgIC8vIFEgPSAocGNbMV0gKiBwY1sxXSAtIDMgKiBwY1syXSkvOTsgICAgICAgICAgICAgIC8vIGNvbXBvbmVudCBmb3IgdGhlIHNvbHV0aW9uCiAgICAgICAgLy8gUiA9ICgyKnBjWzFdXjMgLSA5KnB4WzFdKnBjWzJdICsgMjcqcGNbM10pLzU0OwogICAgICAgIFEgPSAoYSphIC0gMypiKS85OyAgICAgICAgICAgICAgLy8gKDUuNi4xMCkKICAgICAgICBSID0gKDIqYSphKmEgLSA5KmEqYiArIDI3KmMpLzU0OyAgLy8gKDUuNi4xMCkKCiAgICAgICAgaWYoKFIqUikgPCAoUSpRKlEpKXsgICAgICAgICAgICAgICAgICAgIC8vIGlmIHRydWUsIHRoZW4gdGhlcmUgYXJlIDMgcmVhbCByb290cwogICAgICAgICAgICB0aGV0YSA9IGFjb3MoUi9zcXJ0KFEqUSpRKSk7CgogICAgICAgICAgICB4ID0gLTIqc3FydChRKSpjb3ModGhldGEvMykgLSBhLzM7ICAgICAgLy8gKDUuNi4xMikKICAgICAgICAgICAgLy8gaWYoMC45OSooLTgpIDwgeCAmIDEuMDEqKC00KSA+IHgpeyAgICAgIC8vIFRPRE8gdXNlIHRoZSBmbWNmIGZsb2F0aW5nIHB0IGNvbXBhcmlzb24gZnVuY3Rpb25zCiAgICAgICAgICAgIGlmKC04IDwgeCAmJiAtNCA+IHgpeyAgICAgIC8vICB1c2UgZmxvYXQgY29tcGFyaXNvbiBiZWNhc3VlIGV4YWN0IGNvbXBhcmlzb24gZG9lcyBub3QgbWF0dGVyCiAgICAgICAgICAgICAgICByZXR1cm4geDsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgeCA9IC0yKnNxcnQoUSkqY29zKCh0aGV0YSArIE1BVEhfMlBJKS8zKSAtIGEvMzsgLy8gKDUuNi4xMikKICAgICAgICAgICAgLy8gaWYoMC45OSooLTgpIDwgeCAmIDEuMDEqKC00KSA+IHgpewogICAgICAgICAgICBpZigtOCA8IHggJiYgLTQgPiB4KXsgICAgICAvLyAgdXNlIGZsb2F0IGNvbXBhcmlzb24gYmVjYXN1ZSBleGFjdCBjb21wYXJpc29uIGRvZXMgbm90IG1hdHRlciAgICAgIAogICAgICAgICAgICAgICAgcmV0dXJuIHg7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIHggPSAtMipzcXJ0KFEpKmNvcygodGhldGEgKyBNQVRIXzJQSSkvMykgLSBhLzM7IC8vICg1LjYuMTIpCiAgICAgICAgICAgIHJldHVybiB4OyAgICAgICAgICAgICAgICAgICAvLyBQYW9sbyBhc3N1cmVzIHRoYXQgdGhlcmUgd2lsbCBiZSAxIHJvb3QgaW4gdGhlIGFjY2VwdGFibGUgcmFuZ2UKCiAgICAgICAgfQogICAgICAgIGVsc2V7ICAgICAgICAgICAgICAgICAgIC8vIG90aGVyd2lzZSBjb21wdXRlIEEgKHNpbmNlIFEgYW5kIFIgYXJlIGJvdGggcmVhbCAoc2luY2UgYSxiLGMgYXJlIFJlYWwpKQogICAgICAgICAgICAvLyBBID0gLXNnbihSKSpbfFJ8ICsgc3FydChSXjItUV4zKV1eKDEvMykKICAgICAgICAgICAgLy8gQSA9IGZhYnMoUik7ICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluIG9yZGVyIHRvIGNvbXB1dGUgc2duKFIpIHZpYSAoUi9BKQogICAgICAgICAgICAvLyBBID0gLShSL0EpKihBK3NxcnQoUl4yLVFeMykpXigxLzMpOyAgICAgLy8gKDUuNi4xNSkKICAgICAgICAgICAgQSA9IChSPjApLShSPDApOyAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNpZ24gb2YgUiAoc2duKFIpKQogICAgICAgICAgICBBID0gc2duX2Zsb2F0KFIpOyAgICAgICAgICAgICAgICAgICAgICAgLy8gc2lnbiBvZiBSCiAgICAgICAgICAgIEEgPSAtKEEpKmNicnQoZmFicyhSKStzcXJ0KFIqUi1RKlEqUSkpOyAvLyAoNS42LjE1KQogICAgICAgICAgICBpZigwID09IEEpeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gKDUuNi4xNikKICAgICAgICAgICAgICAgIEIgPSAwOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2V7CiAgICAgICAgICAgICAgICBCID0gUS9BOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHggPSAoQStCKS0oYS8zKTsgICAgICAgICAgICAgICAgICAgICAgICAvLyAoNS42LjE3KSB0aGUgc2luZ2xlIHJlYWwgcm9vdC4KICAgICAgICAgICAgcmV0dXJuIHg7CiAgICAgICAgfQogICAgfQogICAgZWxzZSB7ICAgICAgICAgICAgICAgICAgICAgIC8vIHVzZSB0aGUgcXVhZHJhdGljIGVxdWF0aW9uCiAgICAgICAgYSA9IHBjWzFdOwogICAgICAgIGIgPSBwY1syXTsKICAgICAgICBjID0gcGNbM107CgoJCXByaW50ZiAoIiVmLCAlZiwgJWZcbiIsIGEsYixjKTsKCiAgICAgICAgUiA9IGIqYi00KmEqYzsgICAgICAgICAgLy8gVXNlIFIgYXMgdGhlIGRpc2NyaW1pbmFudAogICAgICAgIGlmKFIgPj0gMCl7ICAgICAgICAgICAgIC8vIFNob3VsZCBhbHdheXMgYmUgdGhpcyBjYXNlIC0gb3RoZXJ3aXNlIHRoZXJlIGFyZSBubyByZWFsIHJvb3RzCiAgICAgICAgICAgIFEgPSAtKGIgKyBzZ25fZmxvYXQoYikqc3FydChSKSkvMjsgICAgLy8gKDUuNi40KSB3aXRoICdRJyBzdWJzdGl0dXRlZCBmb3IgJ3EnCiAgICAgICAgICAgIHByaW50ZigiUSA9ICVmXG4iLCBRKTsKICAgICAgICAgICAgeCA9IFEvYTsgICAgICAgICAgICAvLyAoNS42LjUpCgkJCXByaW50ZiAoImZpcnN0ICVmXG4iLCB4KTsKICAgICAgICAgICAgaWYoLTggPCB4ICYmIC00ID4geCl7ICAgICAgLy8gIHVzZSBmbG9hdCBjb21wYXJpc29uIGJlY2FzdWUgZXhhY3QgY29tcGFyaXNvbiBkb2VzIG5vdCBtYXR0ZXIgICAgICAKICAgICAgICAgICAgICAgIHJldHVybiB4OwogICAgICAgICAgICB9CiAgICAgICAgICAgIHggPSBjL1E7ICAgICAgICAgICAgLy8gKDUuNi41KQoJCQlwcmludGYgKCJzZWNvbmQgJWZcbiIsIHgpOwogICAgICAgIHJldHVybiB4OwogICAgICAgIH0KICAgICAgICAvLyBlbHNlewogICAgICAgIC8vICAgICBwcmludCgiRVJSR0chISEiKQogICAgICAgIC8vIH0KICAgIH0KCn0KCgppbnQgbWFpbih2b2lkKSB7CgkvLyB5b3VyIGNvZGUgZ29lcyBoZXJlCglkb3VibGUgdGVtcFs1XTsKCWRvdWJsZSByZXM7CgkKCS8vIHRlbXBbMF0gPSAxMDAuMTIzOwoJLy8gdGVtcFsxXSA9IC4xMjM0MTI0OwoJLy8gdGVtcFsyXSA9IC4wMDAyMzQ1Njc4OTEyMzQ7CgkvLyB0ZW1wWzNdID0gLjAwMDAwMDAzMTQxNTkyNjUzNTsKCS8vIHRlbXBbNF0gPSA0OTIzMTQuMTsKCgl0ZW1wWzBdID0gMTsKCXRlbXBbMV0gPSAtNTsKCXRlbXBbMl0gPSAtMjE7Cgl0ZW1wWzNdID0gMTQ1OwoJCgkvLyByZXMgPSBwZml0KCZ0ZW1wWzJdKTsKCS8vIHJlcyA9IHBmaXQoKGRvdWJsZSAqKSZ0ZW1wWzJdKTsKCXJlcyA9IHJvb3RzX2N1YmljX2NvbnN0cmFpbmVkKHRlbXApOwoJcHJpbnRmKCJhbnM6ICU2LjZmIiwgcmVzKTsKCS8vIHByaW50ZigibWFpbiBcbiUzLjNsZyAgJTMuM2cgJTMuM2cgXG4iLCB0ZW1wWzBdLCB0ZW1wWzFdLCB0ZW1wWzJdKTsKCQoJcmV0dXJuIDA7Cn0KCg==