inline size_t descartesQuarticSolve(const double& a, const double& b, const double& c, const double& d, double& root1, double& root2, double& root3, double& root4) { double rts[4]; double worst3[3]; double qrts[4][3]; /* quartic roots for each cubic root */ if (d == 0.0) { root1 = 0.0; return cubicSolve(a,b,c,root2,root3,root4) + 1; } int j, n4[4]; double v1[4] = {0,0,0,0}, v2[4] = {0,0,0,0},v3[4]={0,0,0,0}; double k,y; double p,q,r; double e0,e1,e2; double g,h; double asq; double ainv4; double e1invk; asq = a*a; e2 = b - asq * (3.0/8.0); e1 = c + a*(asq*0.125 - b*0.5); e0 = d + asq*(b*0.0625 - asq*(3.0/256.0)) - a*c*0.25; p = 2.0*e2; q = e2*e2 - 4.0*e0; r = -e1*e1; size_t n3 = cubicSolve(p,q,r,v3[0],v3[1],v3[2]); for (size_t j3 = 0; j3 < n3; ++j3) { y = v3[j3]; if (y <= 0.0) n4[j3] = 0; else { k = std::sqrt(y); ainv4 = a*0.25; e1invk = e1/k; g = (y + e2 + e1invk)*0.5; h = (y + e2 - e1invk)*0.5 ; bool n1 = quadSolve( g, -k, 1.0, v1[0], v1[1]); bool n2 = quadSolve( h, k, 1.0, v2[0], v2[1]); qrts[0][j3] = v1[0] - ainv4; qrts[1][j3] = v1[1] - ainv4; qrts[n1*2][j3] = v2[0] - ainv4; qrts[n1*2+1][j3] = v2[1] - ainv4; n4[j3]= n1*2 + n2*2; } /* y>=0 */ for (j = 0; j < n4[j3]; ++j) rts[j] = qrts[j][j3]; worst3[j3] = quarticError(a, b, c, d, rts, n4[j3]); } /* j3 loop */ size_t j3 = 0; if (n3 != 1) { if ((n4[1] > n4[j3]) || ((worst3[1] < worst3[j3] ) && (n4[1] == n4[j3]))) j3 = 1; if ((n4[2] > n4[j3]) || ((worst3[2] < worst3[j3] ) && (n4[2] == n4[j3]))) j3 = 2; } root1 = qrts[0][j3]; root2 = qrts[1][j3]; root3 = qrts[2][j3]; root4 = qrts[3][j3]; return (n4[j3]); }
inline size_t ferrariQuarticSolve(const double& a, const double& b, const double& c, const double& d, double& root1, double& root2, double& root3, double& root4) { double rts[4]; double worst3[3]; double qrts[4][3]; /* quartic roots for each cubic root */ if (d == 0.0) { root1 = 0.0; return cubicSolve(a,b,c,root2,root3,root4) + 1; } int j; int n4[4]; double asqinv4; double ainv2; double d4; double yinv2; double v1[4] = {0}; double v2[4] = {0}; double v3[4] = {0}; double p,q,r; double y; double e,f,esq,fsq,ef; double g,gg,h,hh; ainv2 = a*0.5; asqinv4 = ainv2*ainv2; d4 = d*4.0 ; p = b; q = a*c-d4; r = (asqinv4 - b)*d4 + c*c; size_t n3 = cubicSolve(p,q,r,v3[0],v3[1],v3[2]); for (size_t j3 = 0; j3 < n3; ++j3) { y = v3[j3]; yinv2 = y*0.5; esq = asqinv4 - b - y; fsq = yinv2*yinv2 - d; if ((esq < 0.0) && (fsq < 0.0)) n4[j3] = 0; else { ef = -(0.25*a*y + 0.5*c); if ( ((a > 0.0)&&(y > 0.0)&&(c > 0.0)) || ((a > 0.0)&&(y < 0.0)&&(c < 0.0)) || ((a < 0.0)&&(y > 0.0)&&(c < 0.0)) || ((a < 0.0)&&(y < 0.0)&&(c > 0.0)) || (a == 0.0)||(y == 0.0)||(c == 0.0)) /* use ef - */ { if ((b < 0.0)&&(y < 0.0)) { e = sqrt(esq); f = ef/e; } else if (d < 0.0) { f = sqrt(fsq); e = ef/f; } else { if (esq > 0.0) e = sqrt(esq); else e = 0.0; if (fsq > 0.0) f = sqrt(fsq); else f = 0.0; if (ef < 0.0) f = -f; } } else /* use esq and fsq - */ { if (esq > 0.0) e = sqrt(esq); else e = 0.0; if (fsq > 0.0) f = sqrt(fsq); else f = 0.0; if (ef < 0.0) f = -f; } /* note that e >= 0.0 */ g = ainv2 - e; gg = ainv2 + e; if ( ((b > 0.0)&&(y > 0.0)) || ((b < 0.0)&&(y < 0.0)) ) { if (((a > 0.0) && (e > 0.0)) || ((a < 0.0) && (e < 0.0)) ) g = (b + y)/gg; else if (((a > 0.0) && (e < 0.0)) || ((a < 0.0) && (e > 0.0)) ) gg = (b + y)/g; } hh = -yinv2 + f; h = -yinv2 - f; if ( ((f > 0.0)&&(y < 0.0)) || ((f < 0.0)&&(y > 0.0)) ) h = d/hh; else if ( ((f < 0.0)&&(y < 0.0)) || ((f > 0.0)&&(y > 0.0)) ) hh = d/h; bool n1 = quadSolve(hh,gg,1.0,v1[0],v1[1]); bool n2 = quadSolve(h,g,1.0,v2[0],v2[1]); n4[j3] = n1*2+n2*2; qrts[0][j3] = v1[0]; qrts[1][j3] = v1[1]; qrts[n1*2+0][j3] = v2[0]; qrts[n1*2+1][j3] = v2[1]; } for (j = 0; j < n4[j3]; ++j) rts[j] = qrts[j][j3]; worst3[j3] = quarticError(a, b, c, d, rts, n4[j3]); } /* j3 loop */ size_t j3 = 0; if (n3 != 1) { if ((n4[1] > n4[j3]) || ((worst3[1] < worst3[j3] ) && (n4[1] == n4[j3]))) j3 = 1; if ((n4[2] > n4[j3]) || ((worst3[2] < worst3[j3] ) && (n4[2] == n4[j3]))) j3 = 2; } root1 = qrts[0][j3]; root2 = qrts[1][j3]; root3 = qrts[2][j3]; root4 = qrts[3][j3]; return (n4[j3]); }