Beispiel #1
0
int main(int argc, char * argv[])
{
    unsigned int counts;
    double ce[4]= {1.87832,-0.0950376,-1.87832,-0.882024};
    unsigned int j=5;
    if(argc < j ) j=argc;
    for(unsigned int i=1; i< j; i++) {
        ce[i-1]=strtod(argv[i],NULL);
    }
    std::cout<<"x^4";
    if(argc == 1) j=4;
    else j--;
    for(unsigned int i=0; i< j; i++) {
        std::cout<<" + ("<<ce[i]<<")";
        if ( i != 3 ) {
            std::cout<<"*x^"<<3-i;
        } else {
            std::cout<<" =0\n";
        }
    }

    double roots[4];
    switch (j) {
    case 4:
        std::cout<<"quadratic:\n";
        counts=quarticSolver(ce,roots);
        break;
    case 3:
        std::cout<<"cubic:\n";
        counts=cubicSolver(ce,roots);
        break;
    default:
        std::cout<<"quartic:\n";
        counts=quadraticSolver(ce,roots);
    }
    std::cout<<"Number of real roots="<<counts<<std::endl;
    for(unsigned int i=0; i<counts; i++) {
        std::cout<<"x= "<<roots[i]<<'\t';
    }
    std::cout<<std::endl;
    return 0;


}
Beispiel #2
0
unsigned int RS_Math::quarticSolver(double * ce, double *roots)
//quartic solver
// x^4 + ce[0] x^3 + ce[1] x^2 + ce[2] x + ce[3] = 0
{
    // x^4 + a x^3 + b x^2 +c x + d = 0
    // depressed quartic, x= t - a/4
    // t^4 + ( b - 3/8 a^2 ) t^2 + (c - a b/2 + a^3/8) t + d - a c /4 + a^2 b/16 - 3 a^4/256 =0
    // t^4 + p t^2 + q t + r =0
    // p= b - (3./8)*a*a;
    // q= c - 0.5*a*b+(1./8)*a*a*a;
    // r= d - 0.25*a*c+(1./16)*a*a*b-(3./256)*a^4
    unsigned int ret=0;
    double shift=0.25*ce[0];
    double shift2=shift*shift;
    double a2=ce[0]*ce[0];
    double p= ce[1] - (3./8)*a2;
    double q= ce[2] + ce[0]*((1./8)*a2 - 0.5*ce[1]);
    double r= ce[3] - shift*ce[2] + (ce[1] - 3.*shift2)*shift2;
//    std::cout<<"quartic_solver:: p="<<p<<"\tq="<<q<<"\tr="<<r<<std::endl;
    if (fabs(q) <= RS_TOLERANCE) {// Biquadratic equations
        double discriminant= 0.25*p*p -r;
        if (discriminant < 0.) {
            return 0;
        }
        double t2[2];
        t2[0]=-0.5*p-sqrt(discriminant);
        t2[1]= -p - t2[0];
//        std::cout<<"t2[0]="<<t2[0]<<std::endl;
//        std::cout<<"t2[1]="<<t2[1]<<std::endl;
        if ( t2[0] >= 0. ) {// four real roots
            roots[0]=sqrt(t2[0])-shift;
            roots[1]= -sqrt(t2[0])-shift;
            roots[2]=sqrt(t2[1])-shift;
            roots[3]= -sqrt(t2[1])-shift;
            return 4;
        }
        if ( t2[1] >= 0.) { // two real roots
            roots[0]=sqrt(t2[1])-shift;
            roots[1]= -sqrt(t2[1])-shift;
            return 2;
        }
        return 0;
    }
    if ( fabs(r)< 1.0e-75 ) {
        double cubic[3]= {0.,p,q};
        roots[0]=0.;
        ret=1+cubicSolver(cubic,roots+1);
        for(unsigned int i=0; i<ret; i++) roots[i] -= shift;
        return ret;
    }
    // depressed quartic to two quadratic equations
    // t^4 + p t^2 + q t + r = ( t^2 + u t + v) ( t^2 - u t + w)
    // so,
    // 	p + u^2= w+v
    // 	q/u= w-v
    // 	r= wv
    // so,
    //  (p+u^2)^2 - (q/u)^2 = 4 r
    //  y=u^2,
    //  y^3 + 2 p y^2 + ( p^2 - 4 r) y - q^2 =0
    //
    double cubic[3]= {2.*p,p*p-4.*r,-q*q},croots[3];
    ret = cubicSolver(cubic,croots);
    //std::cout<<"quartic_solver:: real roots from cubic: "<<ret<<std::endl;
    //for(unsigned int i=0; i<ret; i++)
    //   std::cout<<"cubic["<<i<<"]="<<cubic[i]<<" x= "<<croots[i]<<std::endl;
    if (ret==1) { //one real root from cubic
        if (croots[0]< 0.) {//this should not happen
            std::cerr<<"Quartic Error:: Found one real root for cubic, but negative\n";
            return 0;
        }
        double sqrtz0=sqrt(croots[0]);
        double ce2[2];
        ce2[0]=	-sqrtz0;
        ce2[1]=0.5*(p+croots[0])+0.5*q/sqrtz0;
        ret=quadraticSolver(ce2,roots);
        if (! ret ) {
            ce2[0]=	sqrtz0;
            ce2[1]=0.5*(p+croots[0])-0.5*q/sqrtz0;
            ret=quadraticSolver(ce2,roots);
        }
        ret=2;
        for(unsigned int i=0; i<ret; i++) roots[i] -= shift;
        return ret;
    }
    if ( croots[0]> 0. && croots[1] > 0. ) {
        double sqrtz0=sqrt(croots[0]);
        double ce2[2];
        ce2[0]=	-sqrtz0;
        ce2[1]=0.5*(p+croots[0])+0.5*q/sqrtz0;
        ret=quadraticSolver(ce2,roots);
        ce2[0]=	sqrtz0;
        ce2[1]=0.5*(p+croots[0])-0.5*q/sqrtz0;
        ret=quadraticSolver(ce2,roots+2);
        ret=4;
        for(unsigned int i=0; i<ret; i++) roots[i] -= shift;
        return ret;
    }
    return 0;
}
Beispiel #3
0
unsigned int RS_Math::cubicSolver(double * ce, double *roots)
//cubic equation solver
// x^3 + ce[0] x^2 + ce[1] x + ce[2] = 0
{
    // depressed cubic, Tschirnhaus transformation, x= t - b/(3a)
    // t^3 + p t +q =0
    unsigned int ret=0;
    double shift=(1./3)*ce[0];
    double p=ce[1] -shift*ce[0];
    double q=ce[0]*( (2./27)*ce[0]*ce[0]-(1./3)*ce[1])+ce[2];
    //Cardano's method,
    //	t=u+v
    //	u^3 + v^3 + ( 3 uv + p ) (u+v) + q =0
    //	select 3uv + p =0, then,
    //	u^3 + v^3 = -q
    //	u^3 v^3 = - p^3/27
    //	so, u^3 and v^3 are roots of equation,
    //	z^2 + q z - p^3/27 = 0
    //	and u^3,v^3 are,
    //		-q/2 \pm sqrt(q^2/4 + p^3/27)
    //	discriminant= q^2/4 + p^3/27
    //std::cout<<"p="<<p<<"\tq="<<q<<std::endl;
    double discriminant= (1./27)*p*p*p+(1./4)*q*q;
    if ( fabs(p)< 1.0e-75) {
        ret=1;
        *roots=(q>0)?-pow(q,(1./3)):pow(-q,(1./3));
        *roots -= shift;
        return ret;
    }
    //std::cout<<"discriminant="<<discriminant<<std::endl;
    if(discriminant>0) {
        double ce2[2]= {q, -1./27*p*p*p},u3[2];
        ret=quadraticSolver(ce2,u3);
        if (! ret ) { //should not happen
            std::cerr<<"cubicSolver()::Error cubicSolver("<<ce[0]<<' '<<ce[1]<<' '<<ce[2]<<")\n";
        }
        ret=1;
        double u,v;
        u= (q<=0) ? pow(u3[0], 1./3): -pow(-u3[1],1./3);
        //u=(q<=0)?pow(-0.5*q+sqrt(discriminant),1./3):-pow(0.5*q+sqrt(discriminant),1./3);
        v=(-1./3)*p/u;
        //std::cout<<"u="<<u<<"\tv="<<v<<std::endl;
        //std::cout<<"u^3="<<u*u*u<<"\tv^3="<<v*v*v<<std::endl;
        *roots=u+v - shift;
        return ret;
    }
    ret=3;
    std::complex<double> u(q,0),rt[3];
    u=std::pow(-0.5*u-sqrt(0.25*u*u+p*p*p/27),1./3);
    rt[0]=u-p/(3.*u)-shift;
    std::complex<double> w(-0.5,sqrt(3.)/2);
    rt[1]=u*w-p/(3.*u*w)-shift;
    rt[2]=u/w-p*w/(3.*u)-shift;
//	std::cout<<"Roots:\n";
//	std::cout<<rt[0]<<std::endl;
//	std::cout<<rt[1]<<std::endl;
//	std::cout<<rt[2]<<std::endl;

    roots[0]=rt[0].real();
    roots[1]=rt[1].real();
    roots[2]=rt[2].real();
    return ret;
}