00001
00002
00003
00004
00005 #include <math.h>
00006
00007 #include "MathHelpers/Resectionsolver/poly34.h"
00008 #define TwoPi 6.28318530717958648
00009 const double eps=1e-14;
00010
00011
00012
00013
00014
00015 int SolveP3(double *x,double a,double b,double c) {
00016 double a2 = a*a;
00017 double q = (a2 - 3*b)/9;
00018 double r = (a*(2*a2-9*b) + 27*c)/54;
00019 double r2 = r*r;
00020 double q3 = q*q*q;
00021 double A,B;
00022 if(r2<q3) {
00023 double t=r/sqrt(q3);
00024 if( t<-1) t=-1;
00025 if( t> 1) t= 1;
00026 t=acos(t);
00027 a/=3; q=-2*sqrt(q);
00028 x[0]=q*cos(t/3)-a;
00029 x[1]=q*cos((t+TwoPi)/3)-a;
00030 x[2]=q*cos((t-TwoPi)/3)-a;
00031 return(3);
00032 } else {
00033 A =-pow(fabs(r)+sqrt(r2-q3),1./3);
00034 if( r<0 ) A=-A;
00035 B = A==0 ? 0 : q/A;
00036
00037 a/=3;
00038 x[0] =(A+B)-a;
00039 x[1] =-0.5*(A+B)-a;
00040 x[2] = 0.5*sqrt(3.)*(A-B);
00041 if(fabs(x[2])<eps) { x[2]=x[1]; return(2); }
00042 return(1);
00043 }
00044 }
00045
00046
00047 void CSqrt( double x, double y, double &a, double &b)
00048 {
00049 double r = sqrt(x*x+y*y);
00050 if( y==0 ) {
00051 r = sqrt(r);
00052 if(x>=0) { a=r; b=0; } else { a=0; b=r; }
00053 } else {
00054 a = sqrt(0.5*(x+r));
00055 b = 0.5*y/a;
00056 }
00057 }
00058
00059 int SolveP4Bi(double *x, double b, double d)
00060 {
00061 double D = b*b-4*d;
00062 if( D>=0 )
00063 {
00064 double sD = sqrt(D);
00065 double x1 = (-b+sD)/2;
00066 double x2 = (-b-sD)/2;
00067 if( x2>=0 )
00068 {
00069 double sx1 = sqrt(x1);
00070 double sx2 = sqrt(x2);
00071 x[0] = -sx1;
00072 x[1] = sx1;
00073 x[2] = -sx2;
00074 x[3] = sx2;
00075 return 4;
00076 }
00077 if( x1 < 0 )
00078 {
00079 double sx1 = sqrt(-x1);
00080 double sx2 = sqrt(-x2);
00081 x[0] = 0;
00082 x[1] = sx1;
00083 x[2] = 0;
00084 x[3] = sx2;
00085 return 0;
00086 }
00087
00088 double sx1 = sqrt( x1);
00089 double sx2 = sqrt(-x2);
00090 x[0] = -sx1;
00091 x[1] = sx1;
00092 x[2] = 0;
00093 x[3] = sx2;
00094 return 2;
00095 } else {
00096 double sD2 = 0.5*sqrt(-D);
00097 CSqrt(-0.5*b, sD2, x[0],x[1]);
00098 CSqrt(-0.5*b,-sD2, x[2],x[3]);
00099 return 0;
00100 }
00101 }
00102
00103 #define SWAP(a,b) { t=b; b=a; a=t; }
00104 static void dblSort3( double &a, double &b, double &c)
00105 {
00106 double t;
00107 if( a>b ) SWAP(a,b);
00108 if( c<b ) {
00109 SWAP(b,c);
00110 if( a>b ) SWAP(a,b);
00111 }
00112 }
00113
00114 int SolveP4De(double *x, double b, double c, double d)
00115 {
00116
00117 if( fabs(c)<1e-14*(fabs(b)+fabs(d)) ) return SolveP4Bi(x,b,d);
00118
00119 int res3 = SolveP3( x, 2*b, b*b-4*d, -c*c);
00120
00121 if( res3>1 )
00122 {
00123 dblSort3(x[0], x[1], x[2]);
00124
00125 if( x[0] > 0)
00126 {
00127 double sz1 = sqrt(x[0]);
00128 double sz2 = sqrt(x[1]);
00129 double sz3 = sqrt(x[2]);
00130
00131 if( c>0 )
00132 {
00133 x[0] = (-sz1 -sz2 -sz3)/2;
00134 x[1] = (-sz1 +sz2 +sz3)/2;
00135 x[2] = (+sz1 -sz2 +sz3)/2;
00136 x[3] = (+sz1 +sz2 -sz3)/2;
00137 return 4;
00138 }
00139
00140 x[0] = (-sz1 -sz2 +sz3)/2;
00141 x[1] = (-sz1 +sz2 -sz3)/2;
00142 x[2] = (+sz1 -sz2 -sz3)/2;
00143 x[3] = (+sz1 +sz2 +sz3)/2;
00144 return 4;
00145 }
00146
00147
00148 double sz1 = sqrt(-x[0]);
00149 double sz2 = sqrt(-x[1]);
00150 double sz3 = sqrt( x[2]);
00151
00152 if( c>0 )
00153 {
00154 x[0] = -sz3/2;
00155 x[1] = ( sz1 -sz2)/2;
00156 x[2] = sz3/2;
00157 x[3] = (-sz1 -sz2)/2;
00158 return 0;
00159 }
00160
00161 x[0] = sz3/2;
00162 x[1] = (-sz1 +sz2)/2;
00163 x[2] = -sz3/2;
00164 x[3] = ( sz1 +sz2)/2;
00165 return 0;
00166 }
00167
00168
00169
00170 double sz1 = sqrt(x[0]);
00171 double szr, szi;
00172 CSqrt(x[1], x[2], szr, szi);
00173 if( c>0 )
00174 {
00175 x[0] = -sz1/2-szr;
00176 x[1] = -sz1/2+szr;
00177 x[2] = sz1/2;
00178 x[3] = szi;
00179 return 2;
00180 }
00181
00182 x[0] = sz1/2-szr;
00183 x[1] = sz1/2+szr;
00184 x[2] = -sz1/2;
00185 x[3] = szi;
00186 return 2;
00187 }
00188
00189 double N4Step(double x, double a,double b,double c,double d)
00190 {
00191 double fxs= ((4*x+3*a)*x+2*b)*x+c;
00192 if( fxs==0 ) return 1e99;
00193 double fx = (((x+a)*x+b)*x+c)*x+d;
00194 return x - fx/fxs;
00195 }
00196
00197
00198
00199
00200
00201 int SolveP4(double *x,double a,double b,double c,double d) {
00202
00203 double d1 = d + 0.25*a*( 0.25*b*a - 3./64*a*a*a - c);
00204 double c1 = c + 0.5*a*(0.25*a*a - b);
00205 double b1 = b - 0.375*a*a;
00206 int res = SolveP4De( x, b1, c1, d1);
00207 if( res==4) { x[0]-= a/4; x[1]-= a/4; x[2]-= a/4; x[3]-= a/4; }
00208 else if (res==2) { x[0]-= a/4; x[1]-= a/4; x[2]-= a/4; }
00209 else { x[0]-= a/4; x[2]-= a/4; }
00210
00211 if( res>0 )
00212 {
00213 x[0] = N4Step(x[0], a,b,c,d);
00214 x[1] = N4Step(x[1], a,b,c,d);
00215 }
00216 if( res>2 )
00217 {
00218 x[2] = N4Step(x[2], a,b,c,d);
00219 x[3] = N4Step(x[3], a,b,c,d);
00220 }
00221 return res;
00222 }
00223
00224 #define F5(t) (((((t+a)*t+b)*t+c)*t+d)*t+e)
00225
00226 double SolveP5_1(double a,double b,double c,double d,double e)
00227 {
00228 int cnt;
00229 if( fabs(e)<eps ) return 0;
00230
00231 double brd = fabs(a);
00232 if( fabs(b)>brd ) brd = fabs(b);
00233 if( fabs(c)>brd ) brd = fabs(c);
00234 if( fabs(d)>brd ) brd = fabs(d);
00235 if( fabs(e)>brd ) brd = fabs(e);
00236 brd++;
00237
00238 double x0, f0;
00239 double x1, f1;
00240 double x2, f2, f2s;
00241 double dx = 0.0;
00242
00243 if( e<0 ) { x0 = 0; x1 = brd; f0=e; f1=F5(x1); x2 = 0.01*brd; }
00244 else { x0 =-brd; x1 = 0; f0=F5(x0); f1=e; x2 =-0.01*brd; }
00245
00246 if( fabs(f0)<eps ) return x0;
00247 if( fabs(f1)<eps ) return x1;
00248
00249
00250
00251 for( cnt=0; cnt<5; cnt++)
00252 {
00253 x2 = (x0 + x1)/2;
00254 f2 = F5(x2);
00255 if( fabs(f2)<eps ) return x2;
00256 if( f2>0 ) { x1=x2; f1=f2; }
00257 else { x0=x2; f0=f2; }
00258 }
00259
00260
00261
00262
00263
00264 do {
00265 cnt++;
00266 if( x2<=x0 || x2>= x1 ) x2 = (x0 + x1)/2;
00267 f2 = F5(x2);
00268 if( fabs(f2)<eps ) return x2;
00269 if( f2>0 ) { x1=x2; f1=f2; }
00270 else { x0=x2; f0=f2; }
00271 f2s= (((5*x2+4*a)*x2+3*b)*x2+2*c)*x2+d;
00272 if( fabs(f2s)<eps ) { x2=1e99; continue; }
00273 dx = f2/f2s;
00274 x2 -= dx;
00275 } while(fabs(dx)>eps);
00276 return x2;
00277 }
00278
00279 int SolveP5(double *x,double a,double b,double c,double d,double e)
00280 {
00281 double r = x[0] = SolveP5_1(a,b,c,d,e);
00282 double a1 = a+r, b1=b+r*a1, c1=c+r*b1, d1=d+r*c1;
00283 return 1+SolveP4(x+1, a1,b1,c1,d1);
00284 }
00285
00286
00287
00288
00289
00290
00291
00292 int Solve2( double x0, double x1, double x2, double f0, double f1, double f2, double &r1, double &r2)
00293 {
00294 double w0 = f0*(x1-x2);
00295 double w1 = f1*(x2-x0);
00296 double w2 = f2*(x0-x1);
00297 double a1 = w0 + w1 + w2;
00298 double b1 = -w0*(x1+x2) - w1*(x2+x0) - w2*(x0+x1);
00299 double c1 = w0*x1*x2 + w1*x2*x0 + w2*x0*x1;
00300 double Di = b1*b1 - 4*a1*c1;
00301 if( Di<0 ) { r1=r2=1e99; return 0; }
00302 Di = sqrt(Di);
00303 r1 = (-b1 + Di)/2/a1;
00304 r2 = (-b1 - Di)/2/a1;
00305 return 2;
00306 }
00307
00308
00309