00001
00018 #ifndef __POLYNOMIAL_H
00019 #define __POLYNOMIAL_H
00020 #include "math.h"
00021 #include "complex.h"
00022 double cbrt(double x){
00023 if (x<0) return -pow(-x,1.0/3.0);
00024 return pow(x,1.0/3.0);
00025 }
00026
00027
00028
00029
00030 int solve_quadratic(double a,double b,double c,double* x1,double* x2)
00031 {
00032 if (a==0)
00033 {
00034 if (b==0) return 0;
00035 *x1=-c/b;
00036 return 1;
00037 }
00038 double d=b*b-4*a*c;
00039 if (d<0) return 0;
00040 *x1=(-b+sqrt(d))/2*a;
00041 *x2=(-b-sqrt(d))/2*a;
00042 return 2;
00043
00044
00045 }
00046
00047
00048 int solve_cubic(double a,double b,double c,double d,double* x1,double* x2,double* x3)
00049 { if (a==0) return solve_quadratic(b,c,d,x1,x2);
00050 double pi=3.141592653589793;
00051 double p=(3*a*c-b*b)/(3*a*a);
00052 double q=(2*b*b*b)/(27*a*a*a)-(b*c)/(3*a*a)+d/a;
00053 double D=(q*q/4)+(p*p*p/27);
00054 if (D>epsilon)
00055 {
00056 *x1=cbrt(-q/2+sqrt(D))+cbrt(-q/2-sqrt(D))-b/(3*a);
00057 *x2=HUGE_VAL;
00058 *x3=HUGE_VAL;
00059 return 1;
00060 }
00061 else if (D<-epsilon)
00062 {
00063 double alpha=acos(-q/(2*sqrt(-p*p*p/27)));
00064 *x1=2*sqrt(-p/3)*cos(alpha/3+0.0/3.0*pi)-b/(3*a);
00065 *x2=2*sqrt(-p/3)*cos(alpha/3+2.0/3.0*pi)-b/(3*a);
00066 *x3=2*sqrt(-p/3)*cos(alpha/3+4.0/3.0*pi)-b/(3*a);
00067 return 3;
00068 }
00069 else
00070 {
00071 if (abs(p)<epsilon)
00072 {
00073 *x1=*x2=*x3=-b/(3*a);
00074 return 3;
00075 } else
00076 { *x1=cbrt(-4*q)-b/(3*a);
00077 *x2=*x3=cbrt(q/2)-b/(3*a);
00078 return 3;
00079 }
00080 }
00081 }
00082
00083 double sqrt2(double x)
00084 {
00085 return sqrt(abs(x));
00086 }
00087
00088
00089 void setpos(int p,complex a,double* x1,double* x2,double* x3,double* x4)
00090 {
00091 switch (p)
00092 {
00093 case 1:*x1=a.r;break;
00094 case 2:*x2=a.r;break;
00095 case 3:*x3=a.r;break;
00096 case 4:*x4=a.r;
00097 }
00098 }
00099
00100
00101 int solve_biquadratic(double a4,double a3,double a2,double a1,double a0,double* x1,double* x2,double* x3,double* x4)
00102 {
00103 if (a4==0) return solve_cubic(a3,a2,a1,a0,x1,x2,x3);
00104 if ((a3==0) && (a1==0))
00105 {
00106 if (solve_quadratic(a4,a2,a0,x1,x3)==0) return 0;
00107 int s=0;
00108 if (*x1>=0)
00109 {
00110 *x1=sqrt(*x1);
00111 *x2=-*x1;
00112 s+=2;
00113 }
00114 if (*x3>=0)
00115 {
00116 if (s==0)
00117 {
00118 *x1=sqrt(*x3);
00119 *x2=-*x1;
00120 s+=2;
00121 } else
00122 {
00123 *x3=sqrt(*x3);
00124 *x4=-*x3;
00125 s+=2;
00126 }
00127 }
00128 return s;
00129 }
00130 complex A=r2c(a4);
00131 complex B=r2c(a3);
00132 complex C=r2c(a2);
00133 complex D=r2c(a1);
00134 complex E=r2c(a0);
00135 complex a = cadd(cdiv (cmul(cmul(r2c(-3),B),B) , cmul(cmul(r2c(8),A),A)) , cdiv(C,A));
00136
00137 complex b = cadd(csub(cdiv(cpow(B,3),cmul(r2c(8),cpow(A,3))),
00138 cdiv(cmul(B,C),cmul(cmul(r2c(2),A),A))),
00139 cdiv(D,A));
00140
00141 complex c = cadd(csub(cadd(cdiv(cmul(r2c(-3),cpow(B,4)),cmul(r2c(256),cpow(A,4))),
00142 cdiv(cmul(C,cmul(B,B)),cmul(r2c(16),cpow(A,3)))),
00143 cdiv(cmul(B,D),cmul(cmul(r2c(4),A),A))),
00144 cdiv(E,A));
00145
00146 if (isEqualE(b,czero))
00147 { if (solve_quadratic(1,a.r,c.r,x1,x3)==0) return 0;
00148 int s=0;
00149 if (*x1>=0)
00150 {
00151 *x1=sqrt(*x1);
00152 *x2=-*x1-a3/(4*a4);
00153 *x1-=a3/(4*a4);
00154 s+=2;
00155 }
00156 if (*x3>=0)
00157 {
00158 if (s==0)
00159 {
00160 *x1=sqrt(*x3);
00161 *x2=-*x1-a3/(4*a4);
00162 *x1-=a3/(4*a4);
00163 s+=2;
00164 } else
00165 {
00166 *x3=sqrt(*x3);
00167 *x4=-*x3-a3/(4*a4);
00168 *x3-=a3/(4*a4);
00169 s+=2;
00170 }
00171 }
00172 return s;
00173 }
00174 complex P = csub(cdiv(cmul(a,a),r2c(-12)),c);
00175 complex Q = csub(cadd(cdiv(cpow(a,3),r2c(-108)),cdiv(cmul(a,c),r2c(3))),cdiv(cmul(b,b),r2c(8)));
00176 complex R = cadd(cdiv(Q,r2c(2)),csqrt( cadd(cdiv(cmul(Q,Q),r2c(4)),cdiv(cpow(P,3),r2c(27))) ));
00177 complex U = czero;
00178 if (isEqualE(R,czero))
00179 {
00180 U=czero;
00181 } else
00182 {
00183 U = cexp(cdiv(cln(R),r2c(3)));
00184 }
00185 complex y=csub(cmul(r2c(-5.0/6.0),a),U);
00186 if (!isEqualE(U,czero))
00187 {
00188 y=cadd(y,cdiv(P,cmul(r2c(3),U)));
00189 }
00190
00191
00192 complex a2y = cadd(a,cmul(r2c(2),y));
00193 complex L1 = cneg(cdiv(B,cmul(r2c(4),A)));
00194 complex L2 = csqrt(a2y);
00195 complex L3 = cneg(a2y);
00196 complex L4 = cmul(r2c(2),cadd(a,cdiv(b,L2)));
00197 complex L5 = csqrt(csub(L3,L4));
00198 complex L6 = cmul(r2c(2),csub(a,cdiv(b,L2)));
00199 complex L7 = csqrt(csub(L3,L6));
00200 complex X1 = cadd(L1,cdiv(cadd( L2 , L5),r2c(2)));
00201 complex X2 = cadd(L1,cdiv(cadd(cneg(L2), L7),r2c(2)));
00202 complex X3 = cadd(L1,cdiv(cadd( L2 ,cneg(L5)),r2c(2)));
00203 complex X4 = cadd(L1,cdiv(cadd(cneg(L2),cneg(L7)),r2c(2)));
00204 int s=0;
00205 if (isReal(X1)) {s++;setpos(s,X1,x1,x2,x3,x4);}
00206 if (isReal(X2)) {s++;setpos(s,X2,x1,x2,x3,x4);}
00207 if (isReal(X3)) {s++;setpos(s,X3,x1,x2,x3,x4);}
00208 if (isReal(X4)) {s++;setpos(s,X4,x1,x2,x3,x4);}
00209 return s;
00210 }
00211 #endif