realroot_doc 0.1.1
|
00001 #include <vector> 00002 #include <realroot/Interval.hpp> 00003 #include <realroot/Seq.hpp> 00004 #define SMALL C(10e-20) 00005 #define REP poly.rep() 00006 #define SIZE poly.size() 00007 00008 #pragma once 00009 00010 using namespace mmx; 00011 00013 //vec_t fcts 00014 00015 template<class C> 00016 std::vector<C> vec (const C c1, const C c2) { 00017 std::vector<C> a(2, C(0)); 00018 a[0]= c1; a[1]= c2; 00019 return a; 00020 } 00021 00022 template<class C> 00023 std::vector<C> rotl(std::vector<C> p){ 00024 std::vector<C> v; v=vec(C(-1)*p[1],p[0]); return(v); 00025 }; /*rotate left*/ 00026 00027 template<class C> 00028 C dot(std::vector<C> p ,std::vector<C> q){ 00029 C v=C(0); 00030 for(unsigned i=0; i<p.size(); i++){ 00031 v +=p[i]*q[i]; 00032 } 00033 return(v); 00034 }; 00035 00036 template<class C> 00037 std::vector<C> v_plus(std::vector<C> p ,std::vector<C> q){ 00038 std::vector<C> v(p.size(),C(0)); 00039 assert( p.size()==q.size() ); 00040 for(unsigned i=0; i<p.size(); i++){ 00041 v[i]=p[i]+q[i]; 00042 } 00043 return(v); 00044 }; 00045 00046 template<class C> 00047 std::vector<C> v_minus(std::vector<C> p ,std::vector<C> q){ 00048 std::vector<C> v(p.size(),C(0)); 00049 assert( p.size()==q.size() ); 00050 for(unsigned i=0; i<p.size(); i++){ 00051 v[i]=p[i]-q[i]; 00052 } 00053 return(v); 00054 }; 00055 00056 template<class C> 00057 std::vector<C> v_div(std::vector<C> p ,C q){ 00058 if (q!=C(0)){ 00059 std::vector<C> v(p.size(),C(0)); 00060 for(unsigned i=0; i<p.size(); i++){ 00061 v[i]=p[i]/q;}; 00062 return(v);}else{return std::vector<C>();} 00063 }; 00064 00065 template<class C> 00066 std::vector<C> v_mul(C q, std::vector<C> p){ 00067 std::vector<C> v(p.size(),C(0)); 00068 for(unsigned i=0; i<p.size(); i++){ 00069 v[i]=p[i]*q; 00070 } 00071 return(v); 00072 }; 00073 00074 template<class C> 00075 C v_length(std::vector<C> p){ 00076 return(sqrt(dot(p,p))); 00077 }; /*length of vector*/ 00078 00079 template<class C> 00080 std::vector<C> matrat(std::vector<C> v1,std::vector<C> v2){ 00081 std::vector<C> mm; mm=vec(v1[0]*v2[0]+v1[1]*v2[1],v1[0]*v2[1]-v2[0]*v1[1]); 00082 return(mm); 00083 }; 00084 00085 template<class C> 00086 std::vector<C> crossrat(std::vector<C> v1,std::vector<C> v2,std::vector<C> v3,std::vector<C> v4){ 00087 std::vector<C> mm=matrat(matrat(v_minus(v1,v2),v_minus(v3,v2)),matrat(v_minus(v1,v4),v_minus(v3,v4))); 00088 return(mm); 00089 }; 00090 00091 00093 //solver and test fcts 00094 template<class C> 00095 bool is_zero(C p){ 00096 if(p==C(0)){return true;} 00097 else{return false;} 00098 }; 00099 00100 template<class C> 00101 bool is_small(C p){ 00102 if(p==C(0)){return true;} 00103 else{return false;} 00104 }; 00105 00106 /* 00107 template<class C> 00108 bool is_small(C p){ 00109 if(p<SMALL && p>C(-1)*SMALL){return true;} 00110 else{return false;} 00111 }; 00112 */ 00113 00114 template<class C> 00115 Seq<C> solve2(C a, C b, C c){ 00116 Seq<C> r; r<<C(-1)<<C(-1); 00117 C root1,root2; 00118 if(is_small(a)){if(!is_small(b)){r[0]=C(-1)*c/b;r[1]=C(-1)*c/b;}} 00119 else{if(sign(b*b-C(4)*a*c) >= 0){ 00120 root1=(C(-1)*b+sqrt(b*b-C(4)*a*c))/(C(2)*a); 00121 root2=(C(-1)*b-sqrt(b*b-C(4)*a*c))/(C(2)*a); 00122 r[0]=root1;r[1]=root2;} 00123 } 00124 00125 return(r); 00126 };/*solve(a*x^2+b*x+c=0)*/ 00127 00128 template<class C> 00129 bool is_unit1(C p){ 00130 if(p<C(0) || p>C(1) ){return false;} 00131 else{return true;} 00132 };/*1dim unit test*/ 00133 00134 00135 template<class C> 00136 bool is_unit2( std::vector<C> p){ 00137 if( is_unit1( p[0] ) && is_unit1( p[1] ) ){return true;} 00138 else{return false;} 00139 };/*2dim unit test*/ 00140 00141 00143 //bezier poly comp. fcts 00144 00145 int binomial(int n, int p) { 00146 int n1=1; 00147 if(p!=0) { 00148 00149 if((n-p)<p){ p=n-p;}; 00150 int n2=n; 00151 for(int i=1;i<=p;i++){ n1=n1*n2/i; n2--;}; 00152 } 00153 00154 return(n1); 00155 }/*binomials*/ 00156 00157 00158 template<class C> 00159 polynomial< C ,with<Bernstein> > bbasis(C co, int n, int deg) 00160 { 00161 polynomial< C ,with<Bernstein> > ti(co*C(binomial(n,deg)),deg,0), t("1-x0"), tj(C(1),0,0); 00162 00163 for(int i=0; i<n-deg; i++){ mul(tj,t); }; 00164 00165 mul(ti, tj); 00166 return(ti); 00167 }/*BB basis polynomials*/ 00168 00169 00170 template<class C> 00171 void pow( polynomial< C ,with<Bernstein> > & poly, int n) 00172 { 00173 polynomial< C ,with<Bernstein> > t=poly; 00174 00175 for(int i=1; i<n; i++){ mul(poly, t); }; 00176 }/*nth power of a bbpoly*/ 00177 00178 00179 00180 template<class C> 00181 polynomial< C ,with<Bernstein> > seq2b( Seq<C> coeffseq ) 00182 { 00183 int n=coeffseq.size()-1; 00184 polynomial< C ,with<Bernstein> > pol, pi; 00185 00186 for(int i=0; i<=n; i++ ){ 00187 pi=bbasis(coeffseq[i],n,i); 00188 add( pol , pi);} 00189 00190 return(pol); 00191 };/*coeff vector -> bbpoly*/ 00192 00193 00194 template<class C> 00195 C pint( polynomial< C ,with<MonomialTensor> > poly) 00196 { 00197 int n=SIZE; 00198 C res=C(0); 00199 00200 for(int i=0; i<n; i++ ){ 00201 res += REP[i]/C(i+1) ;} 00202 00203 return(res); 00204 };/*poly integration on (0,1)*/ 00205 00206 00207 template<class C> 00208 C min_coeff( polynomial< C ,with<Bernstein> > poly){ 00209 00210 C min =REP[0]; 00211 00212 for ( unsigned i = 1; i < SIZE; i++ ){ 00213 if( min > REP[i] ){ 00214 min = REP[i]; 00215 } 00216 00217 } 00218 return min; 00219 };/*minimal coeff*/ 00220 00221 00222 template<class C> 00223 C max_coeff( polynomial< C ,with<Bernstein> > poly){ 00224 00225 C max =REP[0]; 00226 00227 for ( unsigned i = 1; i < SIZE; i++ ){ 00228 if( max < REP[i] ){ 00229 max = REP[i]; 00230 } 00231 00232 } 00233 return max; 00234 };/*max coeff*/ 00235 00236 00237 00238 template<class C> 00239 C abs_max_coeff( polynomial< C ,with<Bernstein> > poly){ 00240 C min =min_coeff(poly); 00241 C max =max_coeff(poly); 00242 00243 if( max*max < min*min){ max =C(-1)*min; }; 00244 00245 return max; 00246 };/* max abs coeff*/ 00247 00248 00249 00250 template<class C> 00251 Seq<C> corner_values(polynomial< C ,with<Bernstein> > p){ 00252 C c00,c10,c01,c11; 00253 00254 eval( c00, p.rep(), vec(C(0),C(0)) ); 00255 eval( c10, p.rep(), vec(C(1),C(0)) ); 00256 eval( c01, p.rep(), vec(C(0),C(1)) ); 00257 eval( c11, p.rep(), vec(C(1),C(1)) ); 00258 Seq<C> cval; cval<<c00<<c10<<c01<<c11; 00259 return(cval); 00260 00261 }; 00262 00264 //arc fcts 00265 00266 template<class C> 00267 std::vector<C> approx(polynomial< C ,with<Bernstein> > poly , std::vector<C> ep1, std::vector<C> ep2, int MTH){ 00268 polynomial< C ,with<MonomialTensor> > xt, yt, res, monp, mp("x0-x0^2"); 00269 polynomial< C ,with<Bernstein> > bxt, byt; 00270 C t, I; 00271 Seq<C> sols; 00272 std::vector<C> movec; 00273 00274 if (ep2.size()==0 ){movec=ep1;} 00275 else{ 00276 tensor::assign(monp.rep(),poly.rep()); 00277 00278 Seq<C> endptsx,endptsy; 00279 00280 endptsx<<ep2[0]<<ep1[0]; 00281 endptsy<<ep2[1]<<ep1[1]; 00282 bxt=seq2b(endptsx); tensor::assign(xt.rep(),bxt.rep()); 00283 byt=seq2b(endptsy); tensor::assign(yt.rep(),byt.rep()); 00284 00285 Seq<polynomial< C ,with<MonomialTensor> > > param; param<<xt<<yt; 00286 00287 tensor::eval(res, monp.rep(), param, 1); 00288 00289 00290 00291 C c0,c1; 00292 tensor::eval(c0,res.rep(),C(0)); 00293 tensor::eval(c1,res.rep(),C(1)); 00294 mul(res,mp); 00295 00296 I=pint(res); 00297 C u=C(15)*I-C(0.75)*(c0+c1); 00298 sols=solve2(c0+c1-C(2)*u,C(2)*(u-c0),c0); 00299 00300 00301 if(is_unit1(sols[0])) 00302 {t=sols[0]; movec=vec(ep1[0]*t+ep2[0]*(C(1)-t),ep1[1]*t+ep2[1]*(C(1)-t));} 00303 else if(is_unit1(sols[1])) 00304 {t=sols[1]; movec=vec(ep1[0]*t+ep2[0]*(C(1)-t),ep1[1]*t+ep2[1]*(C(1)-t));} 00305 else{movec=std::vector<C>();} 00306 00307 } 00308 00309 return movec; 00310 }; /*approx bivar bbpoly along line*/ 00311 00312 00313 template<class C> 00314 arc_rep< C > median( box_rep< C > box, Seq<std::vector<C> > list, int MTH ){ 00315 std::vector<C> endp[2], mpts[3]; 00316 int s=0; 00317 arc_rep<C> medc; 00318 for(int i=0; i<3; i++){mpts[i]=std::vector<C>();}; 00319 00320 00321 mpts[0]=approx(box.poly, list[0], list[1], MTH); 00322 mpts[1]=approx(box.poly, list[2], list[3], MTH); 00323 00324 if( mpts[0].size()!=0 && mpts[1].size()!=0 ){ 00325 00326 std::vector<C> mid, rvec, v; 00327 mid=v_div(v_plus(mpts[0],mpts[1]),C(2)); 00328 rvec=rotl(v_minus(mpts[0],mpts[1])); 00329 C bval[4]; 00330 00331 if(!is_small(rvec[0])){ 00332 bval[0]=rvec[1]*C(-1)*mid[0]/rvec[0]+mid[1]; 00333 bval[1]=rvec[1]*(C(1)-mid[0])/rvec[0]+mid[1];}else{ bval[0]=C(-1); bval[1]=C(-1);} 00334 00335 if(!is_small(rvec[1])){ 00336 bval[2]=rvec[0]*C(-1)*mid[1]/rvec[1]+mid[0]; 00337 bval[3]=rvec[0]*(C(1)-mid[1])/rvec[1]+mid[0];}else{ bval[2]=C(-1); bval[3]=C(-1);} 00338 00339 if(is_unit1(bval[0]) && s<2){endp[s]= vec(C(0),bval[0]); s++;}; 00340 if(is_unit1(bval[1]) && s<2){endp[s]= vec(C(1),bval[1]); s++;}; 00341 if(is_unit1(bval[2]) && s<2){endp[s]= vec(bval[2],C(0)); s++;}; 00342 if(is_unit1(bval[3]) && s<2){endp[s]= vec(bval[3],C(1)); s++;}; 00343 mpts[2]=mpts[1]; 00344 00345 if(s==2){ mpts[1]=approx(box.poly, endp[0], endp[1], MTH);} 00346 00347 if(mpts[1].size()!=0){ medc=arc_rep<C>(mpts);}else{medc=arc_rep<C>();} 00348 //else{ for(int i=0; i<3; i++){mpts[i]= vec(C(-1),C(-1));};} 00349 00350 }else{ medc=arc_rep<C>(); }; 00351 00352 00353 //std::cout <<"med: "<<mpts[0]<<" "<<mpts[1]<<" "<<mpts[2]<<std::endl; 00354 00355 return(medc); 00356 }; /*median arc computation*/ 00357 00358 00359 template<class C> 00360 void circ_is( std::vector<C> * ispts, arc_rep<C> c1, arc_rep<C> c2){ 00361 00362 Seq<C> eh1= c1.arc_eq(), eh2= c2.arc_eq(), sx, a; 00363 C Aeh,Ceh; 00364 if(!is_small(eh1[1]) && !is_small(eh1[2]) && !is_small(eh2[1]) && !is_small(eh2[2])){ 00365 00366 if(is_small(eh1[0]) && is_small(eh2[0])){ 00367 00368 Aeh=(C(-1)*eh2[1])/(eh2[2]); 00369 Ceh=(C(-1)*eh2[3])/(eh2[2]); 00370 sx[0]=(C(-1)*eh1[2]*Ceh-eh1[3])/(eh1[2]*Aeh+eh1[1]); 00371 00372 ispts[0]=vec(sx[0],Aeh*sx[0]+Ceh); 00373 ispts[1]=vec(sx[0],Aeh*sx[0]+Ceh); 00374 } 00375 else{ 00376 if(!is_small(eh1[0]) && !is_small(eh2[0])){ 00377 eh1=eh1/eh1[0]; 00378 eh2=eh2/eh2[0]; 00379 00380 Aeh=(eh2[1]-eh1[1])/(eh1[2]-eh2[2]); 00381 Ceh=(eh2[3]-eh1[3])/(eh1[2]-eh2[2]);} 00382 else{ 00383 if(is_small(eh1[0]) && !is_small(eh2[0])){a=eh1; eh1=eh2; eh2=a;}; 00384 00385 eh1=eh1/eh1[0]; 00386 00387 Aeh=(C(-1)*eh2[1])/(eh2[2]); 00388 Ceh=(C(-1)*eh2[3])/(eh2[2]);}; 00389 00390 00391 00392 sx=solve2(C(1)+Aeh*Aeh, C(2)*Aeh*Ceh+eh1[1]+eh1[2]*Aeh, Ceh*Ceh+eh1[2]*Ceh+eh1[3]); 00393 00394 ispts[0]=vec(sx[0],Aeh*sx[0]+Ceh); 00395 ispts[1]=vec(sx[1],Aeh*sx[1]+Ceh); 00396 00397 } 00398 } 00399 else{ ispts[0]=vec(C(-1),C(-1)); 00400 ispts[1]=vec(C(-1),C(-1)); 00401 }; 00402 };/*cicrcle intersections (numerical behaviour!)*/ 00403 00404 00405 template<class C> 00406 bool is_arc(arc_rep<C> c){ 00407 if( c.pts[0].size()!=0 && c.pts[1].size()!=0 && c.pts[2].size()!=0 ){return true;} 00408 else{return false;} 00409 }; 00410 00411 00412 template<class C> 00413 bool is_infatarc(std::vector<C> p, arc_rep<C> c1, arc_rep<C> c2){ 00414 if(is_arc(c1)&&is_arc(c2)){ 00415 if( crossrat(c1.pts[2],c1.pts[1],c1.pts[0],p)[1]*crossrat(c2.pts[2],c2.pts[1],c2.pts[0],p)[1]<C(0)) 00416 {return true;}else{return false;} 00417 } 00418 else{return false;} 00419 }; 00420 00421 00422 template<class C> 00423 Seq< std::vector<C> > extpts(arc_rep<C> mc1, C r1, arc_rep<C> mc2, C r2){ 00424 00425 arc_rep<C> 00426 c1p=mc1.offset(r1),c1m=mc1.offset(C(-1)*r1), 00427 c2p=mc2.offset(r2),c2m=mc2.offset(C(-1)*r2); 00428 std::vector<C> p[2]; 00429 Seq< std::vector<C> > ispts; 00430 00431 if(is_arc(c1p) && is_arc(c2p)){ circ_is(p,c1p,c2p); if(is_unit2(p[0])){ispts<<p[0];}; if(is_unit2(p[1])){ispts<<p[1];};}; 00432 if(is_arc(c1p) && is_arc(c2m)){ circ_is(p,c1p,c2m); if(is_unit2(p[0])){ispts<<p[0];}; if(is_unit2(p[1])){ispts<<p[1];};}; 00433 if(is_arc(c1m) && is_arc(c2m)){ circ_is(p,c1m,c2m); if(is_unit2(p[0])){ispts<<p[0];}; if(is_unit2(p[1])){ispts<<p[1];};}; 00434 if(is_arc(c1m) && is_arc(c2p)){ circ_is(p,c1m,c2p); if(is_unit2(p[0])){ispts<<p[0];}; if(is_unit2(p[1])){ispts<<p[1];};}; 00435 00436 if(is_arc(c1p) && is_infatarc(c1p.pts[0],c2m,c2p)){ispts<<c1p.pts[0];}; 00437 if(is_arc(c1p) && is_infatarc(c1p.pts[2],c2m,c2p)){ispts<<c1p.pts[2];}; 00438 if(is_arc(c1m) && is_infatarc(c1m.pts[0],c2m,c2p)){ispts<<c1m.pts[0];}; 00439 if(is_arc(c1m) && is_infatarc(c1m.pts[2],c2m,c2p)){ispts<<c1m.pts[2];}; 00440 00441 if(is_arc(c2p) && is_infatarc(c2p.pts[0],c1m,c1p)){ispts<<c2p.pts[0];}; 00442 if(is_arc(c2p) && is_infatarc(c2p.pts[2],c1m,c1p)){ispts<<c2p.pts[2];}; 00443 if(is_arc(c2m) && is_infatarc(c2m.pts[0],c1m,c1p)){ispts<<c2m.pts[0];}; 00444 if(is_arc(c2m) && is_infatarc(c2m.pts[2],c1m,c1p)){ispts<<c2m.pts[2];}; 00445 00446 if(is_arc(c1p) && is_infatarc(c1p.critpt(0),c2m,c2p)){ispts<<c1p.critpt(0);}; 00447 if(is_arc(c1p) && is_infatarc(c1p.critpt(1),c2m,c2p)){ispts<<c1p.critpt(1);}; 00448 if(is_arc(c1m) && is_infatarc(c1m.critpt(0),c2m,c2p)){ispts<<c1m.critpt(0);}; 00449 if(is_arc(c1m) && is_infatarc(c1m.critpt(1),c2m,c2p)){ispts<<c1m.critpt(1);}; 00450 00451 if(is_arc(c2p) && is_infatarc(c2p.critpt(0),c1m,c1p)){ispts<<c2p.critpt(0);}; 00452 if(is_arc(c2p) && is_infatarc(c2p.critpt(1),c1m,c1p)){ispts<<c2p.critpt(1);}; 00453 if(is_arc(c2m) && is_infatarc(c2m.critpt(0),c1m,c1p)){ispts<<c2m.critpt(0);}; 00454 if(is_arc(c2m) && is_infatarc(c2m.critpt(1),c1m,c1p)){ispts<<c2m.critpt(1);}; 00455 00456 00457 Seq< std::vector<C> > cpts; cpts<<vec(C(0),C(0));cpts<<vec(C(0),C(1));cpts<<vec(C(1),C(0));cpts<<vec(C(1),C(1)); 00458 00459 for(unsigned i=0; i<cpts.size(); i++){ if( is_infatarc(cpts[i],c1m,c1p) && 00460 is_infatarc(cpts[i],c2m,c2p) ){ ispts<<cpts[i]; }; 00461 }; 00462 00463 return ispts; 00464 }; 00465 00466 template<class C> 00467 domain<C> minmax_box(Seq<std::vector<C> > ispts, domain<C> box){ 00468 domain<C> newbox=box; 00469 C minx,maxx,miny,maxy; 00470 if(ispts.size()==0){newbox=domain<C>(int(0));}else{ 00471 int k=0; 00472 for(unsigned i=0; i<ispts.size(); i++){ 00473 if(k==0){ minx=ispts[i][0]; maxx=ispts[i][0]; miny=ispts[i][1]; maxy=ispts[i][1]; k++;}; 00474 if(ispts[i][0]>maxx){maxx=ispts[i][0];}; 00475 if(ispts[i][0]<minx){minx=ispts[i][0];}; 00476 if(ispts[i][1]>maxy){maxy=ispts[i][1];}; 00477 if(ispts[i][1]<miny){miny=ispts[i][1];}; 00478 }; 00479 00480 Interval<C> Jx( minx, maxx), Jy( miny, maxy) ; 00481 if((maxx-minx)>C(0) && (maxy-miny)>C(0)) 00482 { newbox= domain<C>( box.I[0].m + box.delta()[0]*Jx , box.I[1].m + box.delta()[1]*Jy ); }; 00483 } 00484 return(newbox); 00485 };/*minmax box for the arc intersection points and arc end points*/ 00486 00487 00488 //end of arc_rep fcts 00489