00001
00002
00003
00004 #ifndef _realroot_SOLVER_FIRST_ROOT_CONFRAC_H
00005 #define _realroot_SOLVER_FIRST_ROOT_CONFRAC_H
00006
00007
00008 # include <realroot/Interval.hpp>
00009
00010 # include <realroot/homography.hpp>
00011 # include <realroot/sign_variation.hpp>
00012 # include <realroot/univariate_bounds.hpp>
00013 # include <stack>
00014 # include <realroot/solver.hpp>
00015
00016 # define NO_ROOT -1.0
00017 # define TMPL template<class POL>
00018 # define TMPLR template<class Real, class POL>
00019 # define N_ITER 10000
00020
00021 namespace mmx {
00022
00023 struct CFfirstIsolate{};
00024 struct CFfirstApproximate{};
00025 struct CFfirstFloor{};
00026 struct CFallIsolate{};
00027 struct CFseparate{};
00028 struct CFdecide{};
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 TMPL
00047 class interval_rep
00048 {
00049 typedef typename POL::scalar_t C;
00050
00051 POL f;
00052 homography<C> hg;
00053
00054 public:
00055
00056 interval_rep(){ }
00057
00058 interval_rep(const POL p)
00059 {
00060 f = p;
00061 hg = homography<C>() ;
00062 }
00063
00064 interval_rep(const POL p, homography<C> h)
00065 {
00066 f = p;
00067 hg = h;
00068 }
00069
00070
00071 interval_rep(const POL p, C u, C v )
00072 {
00073 f = p;
00074 hg = homography<C>() ;
00075
00076 shift_box ( u );
00077 contract_box ( v-u );
00078 reverse_and_shift_box (1);
00079
00080 }
00081
00082
00083 POL inline poly() {return f;};
00084
00085 homography<C> hom() { return hg; }
00086
00087
00088 template<class Real>
00089 Interval<Real> domain()
00090 {
00091 Real l, r;
00092 Interval<Real> s ;
00093
00094 if ( hg.b!=0 && hg.d!=0 )
00095 l= as<Real>(hg.b)/as<Real>(hg.d);
00096 else if ( hg.d==0 )
00097 l= 10000000;
00098 else if ( hg.b==0 )
00099 l= 0 ;
00100 else
00101 l= as<Real>(hg.a)/as<Real>(hg.c) ;
00102
00103 if ( hg.a!=0 && hg.c!=0 )
00104 r= as<Real>(hg.a)/as<Real>(hg.c);
00105 else if ( hg.c==0 )
00106 r=10000000;
00107 else if ( hg.a==0 )
00108 r= 0 ;
00109 else
00110 r= as<Real>(hg.b)/as<Real>(hg.d);
00111
00112 if ( l<=r ) s= Interval<Real>(l,r);
00113 else s= Interval<Real>(r,l);
00114
00115 return s;
00116 }
00117
00118
00119 template<class Real>
00120 Real inline width()
00121 {
00122 return this->template domain<Real>().width();
00123 }
00124
00125
00126 template<class Real>
00127 Real inline point(C & t)
00128 {
00129 return ( as<Real>(hg.a)*as<Real>(t) + as<Real>(hg.b) ) /
00130 ( as<Real>(hg.c)*as<Real>(t) + as<Real>(hg.d) ) ;
00131 }
00132
00133 C middle()
00134 {
00135 C t(hg.d / hg.c);
00136
00137 if (t>0)
00138 return ( t ) ;
00139 else
00140 return C(1);
00141 }
00142
00143 unsigned sign_var()
00144 {
00145 return sign_variation(f.begin(),f.end()) ;
00146 }
00147
00148
00149
00150 void shift_box(const C& t)
00151 {
00152 int s, k,j, sz= f.size();
00153
00154 for ( s = sz, j = 0; j <= s-2; j++ )
00155 for( k = s-2; k >= j; k-- )
00156 f[k] += t*f[k+1];
00157
00158
00159 hg.shift_hom(t);
00160 };
00161
00162
00163 void contract_box(const C & t )
00164 {
00165 int s, sz= f.size();
00166
00167 for ( s = 0 ; s < sz; ++s )
00168 f[s] *= pow(t,s) ;
00169
00170
00171 hg.contract_hom(t);
00172 };
00173
00174
00175 void reverse_box(const C & t=1 )
00176 {
00177 unsigned s, l= f.size()-1;
00178
00179 for (s = 0 ; s <= l/2; s++ )
00180 std::swap(f[s], f[l-s]);
00181
00182
00183 hg.reciprocal_hom(t);
00184 };
00185
00186
00187 void inline reverse_and_shift_box(const C & t=1)
00188 {
00189 reverse_box(t);
00190 shift_box (C(1));
00191 };
00192
00193 void print()
00194 {
00195 std::cout << "----------Interval---------------" << "\n" ;
00196 std::cout << poly() << "\n" ;
00197 std::cout<< "("<<hg.a <<"x + " << hg.b<<")/("<<hg.c<<"x+ "<<hg.d << ")"<<", sv:"<<sign_var() <<std::endl;
00198 std::cout << domain() << "\n" ;
00199 std::cout << "-------------------------------" << "\n" ;
00200 }
00201
00202 };
00203
00204
00205
00206
00207
00208
00209 TMPLR
00210 struct solver_cffirst {
00211
00212 interval_rep<POL> ir;
00213 Real eps;
00214
00215 solver_cffirst(interval_rep<POL> p){
00216 ir = p;
00217 eps= as<Real>(1e-7);
00218 }
00219
00220 interval_rep<POL> first_root();
00221 Interval<Real> first_root_isolate();
00222 Real first_root_approximate();
00223 Real first_root_floor();
00224
00225 Seq<interval_rep<POL> > all_roots();
00226 Seq<Interval<Real> > all_roots_isolate();
00227 Seq<Real> all_roots_separate();
00228 };
00229
00230
00231
00232
00233
00234 TMPLR
00235 interval_rep<POL> solver_cffirst<Real,POL>::first_root()
00236 {
00237 typedef interval_rep<POL> BOX;
00238 std::stack<BOX * > uboxes;
00239 typedef typename POL::scalar_t C;
00240
00241 POL zero(0);
00242 Interval<Real> mid(0);
00243 BOX * b, * tmp;
00244 POL p;
00245 unsigned s, iters=0;
00246
00247 Interval<Real> I;
00248 AkritasBound<C> lb;
00249
00250
00251
00252
00253
00254 C lower;
00255 b= new BOX(ir);
00256 uboxes.push (b);
00257
00258 while ( !uboxes.empty() && iters++ < N_ITER )
00259
00260 {
00261 b = uboxes.top() ;
00262 p = b->poly() ;
00263 uboxes.pop();
00264
00265 if ( p==zero && (!uboxes.empty()) ) {
00266 return *b;}
00267
00268 s = b->sign_var() ;
00269 I = b->template domain<Real>();
00270
00271 if ( s==1 && (!uboxes.empty()) ) {
00272 return *b;}
00273
00274 if ( s > 0 )
00275 {
00276 if ( b->template width<Real>() < eps )
00277 {std::cout<< "first_root: multiple root?"<<b->template domain<Real>() <<std::endl;}
00278 else
00279 {
00280 lower= lb.lower_bound(p) ;
00281 if ( lower!=0 )
00282 {
00283 if ( p( lower ) == 0 )
00284 return *b;
00285
00286 tmp= new BOX( *b ) ;
00287 free(b);
00288 tmp->shift_box( lower );
00289 uboxes.push (tmp);
00290 }
00291 else
00292 {
00293
00294 tmp = new BOX( *b ) ;
00295 tmp->shift_box( 1 );
00296 uboxes.push ( tmp );
00297
00298 if ( p( Real(1) ) == Real(0) )
00299 { tmp = new BOX(zero, b->hom() ) ;
00300 uboxes.push ( tmp ); }
00301
00302 tmp = new BOX( *b ) ;
00303 tmp->reverse_and_shift_box( 1 );
00304 tmp->reverse_box( 1 );
00305 uboxes.push ( tmp );
00306
00307 free(b);
00308 }
00309 }
00310 }
00311 }
00312
00313 return BOX(-1);
00314 }
00315
00316
00317
00318
00319
00320 TMPLR
00321 Seq<interval_rep<POL> > solver_cffirst<Real,POL>::all_roots()
00322 {
00323 typedef interval_rep<POL> BOX;
00324 std::stack<BOX * > uboxes;
00325 typedef typename POL::scalar_t C;
00326
00327 Real ev(0);
00328 Seq<interval_rep<POL> > sols;
00329 POL zero(0);
00330 Interval<Real> mid(0);
00331 BOX * b, * tmp;
00332 POL p;
00333 unsigned s, iters=0;
00334
00335 Interval<Real> I;
00336 AkritasBound<C> lb;
00337
00338
00339
00340
00341
00342 C lower;
00343 b= new BOX(ir);
00344 uboxes.push (b);
00345
00346 while ( !uboxes.empty() && iters++ < N_ITER )
00347 {
00348 b = uboxes.top() ;
00349 p = b->poly() ;
00350 uboxes.pop();
00351
00352 if ( p==zero && (!uboxes.empty()) ) {
00353 sols<< *b;}
00354
00355 I = b->template domain<Real>();
00356
00357
00358 s = b->sign_var() ;
00359 if ( s==1 && (!uboxes.empty()) ) {
00360 sols << *b; continue; }
00361
00362 if ( s > 0 )
00363 {
00364 if ( (!uboxes.empty()) && b->template width<Real>() < eps*.1 )
00365 {std::cout<<
00366 "all_roots: multiple root?"<<b->template domain<Real>() <<std::endl;
00367 std::cout<< b->poly()<<" , "<<b->template width<Real>()<<std::endl;
00368 std::cout<<"source: "<<ir.poly()<<std::endl;
00369
00370 }
00371 else
00372 {
00373 lower= lb.lower_bound(p) ;
00374 if ( lower!=0 )
00375 {
00376
00377 let::assign(ev,lower);
00378 if ( p(ev) == 0 )
00379 sols<< *b;
00380
00381 tmp= new BOX( *b ) ;
00382 free(b);
00383 tmp->shift_box( lower );
00384 uboxes.push (tmp);
00385 }
00386 else
00387 {
00388
00389 tmp = new BOX( *b ) ;
00390 tmp->shift_box( 1 );
00391 uboxes.push ( tmp );
00392
00393 ev=1;
00394 if ( p( ev ) == Real(0) )
00395 { tmp = new BOX(zero, b->hom() ) ;
00396 uboxes.push ( tmp ); }
00397
00398 tmp = new BOX( *b ) ;
00399 tmp->reverse_and_shift_box( 1 );
00400 tmp->reverse_box( 1 );
00401 uboxes.push ( tmp );
00402
00403 free(b);
00404 }
00405 }
00406 }
00407 }
00408 return sols;
00409 }
00410
00411
00412
00413
00414 TMPLR
00415 Interval<Real> solver_cffirst<Real,POL>::first_root_isolate()
00416 {
00417 interval_rep<POL> a( first_root() );
00418 typename POL::scalar_t t(1);
00419
00420 if ( a.poly()== POL(-1) )
00421 return (0);
00422 else
00423 if (a.poly()==POL(0) )
00424 return( a.template point<Real>(t) );
00425 else
00426 return ( a.template domain<Real>() );
00427 }
00428
00429 TMPLR
00430 Real solver_cffirst<Real,POL>::first_root_approximate()
00431 {
00432 typedef interval_rep<POL> BOX;
00433 typedef typename POL::scalar_t C;
00434 BOX * l, * r= new BOX( first_root() ) ;
00435 C t(1);
00436
00437 if ( r->poly()== POL(-1) )
00438 return (0);
00439 else
00440 if (r->poly()==POL(0) )
00441 return( r->template point<Real>(t) );
00442 else
00443 {
00444
00445 while ( r->template width<Real>() > eps )
00446 {
00447 t= r->middle();
00448
00449 if ( r->poly()( t ) == 0 ) return( r->template point<Real>(t) );
00450 l= new BOX( *r) ;
00451 l->shift_box( t );
00452
00453 if ( l->sign_var() )
00454 {
00455 free(r);
00456 r=l;
00457 continue;
00458 }
00459 else
00460 {
00461 free(l);
00462 r->contract_box(t);
00463 r->reverse_and_shift_box(1);
00464 r->reverse_box(1);
00465 }
00466 }
00467
00468 return ( r->template domain<Real>() );
00469 }
00470 }
00471
00472 TMPLR
00473 Real solver_cffirst<Real,POL>::first_root_floor()
00474 {
00475 typedef interval_rep<POL> BOX;
00476 typedef typename POL::scalar_t C;
00477
00478 BOX * l, * r= new BOX( first_root() ) ;
00479 Interval<Real> I;
00480 C t(1);
00481 if ( r->poly()== POL(-1) )
00482 return (0);
00483 else
00484 if (r->poly()==POL(0) )
00485 return( r->template point<Real>(t) );
00486 else
00487 {
00488
00489 I= r->template domain<Real>();
00490 if ( r->poly() == POL(0) ) return as<Real> (floor(as<double>(r->template point<Real>(t))) );
00491 while ( rfloor(I.m)!=rfloor(I.M) )
00492 {
00493 t= r->middle();
00494 if ( r->poly()( t ) == 0 ) return as<Real>( floor(as<double>(r->template point<Real>(t))) );
00495
00496 l= new BOX( *r) ;
00497 l->shift_box( t );
00498
00499 if ( l->sign_var() )
00500 {
00501 free(r);
00502 r=l;
00503 I= r->template domain<Real>();
00504 continue;
00505 }
00506 else
00507 {
00508 free(l);
00509 r->reverse_and_shift_box();
00510 r->reverse_box();
00511 I= r->template domain<Real>();
00512 }
00513 }
00514 }
00515 return as<Real>( floor(as<double>(I.m)) );
00516 }
00517
00518 TMPLR
00519 Seq<Interval<Real> > solver_cffirst<Real,POL>::all_roots_isolate()
00520 {
00521 Seq<interval_rep<POL> > a( all_roots() );
00522 Seq<Interval<Real> > s;
00523 typename POL::scalar_t t(1);
00524
00525 for ( unsigned i=0; i<a.size(); ++i)
00526 if (a[i].poly()==POL(0) )
00527 s<< Interval<Real>(a[i].template point<Real>(t) );
00528 else
00529 s<< a[i].template domain<Real>();
00530
00531 return s;
00532 }
00533
00534 TMPLR
00535 Seq<Real> solver_cffirst<Real,POL>::all_roots_separate()
00536 {
00537 Seq< Interval<Real> > ints;
00538 Seq<Real> sep;
00539
00540 ints= all_roots_isolate();
00541 for (unsigned i=1; i<ints.size(); ++i)
00542 sep << (ints[i-1].M + ints[i].m)*Real(0.5) ;
00543
00544 return sep;
00545 }
00546
00547
00548 template<class Ring>
00549 struct solver<Ring, CFfirstIsolate > {
00550
00551 typedef typename Ring::scalar_t base_t;
00552
00553 template<class Real, class POL> static Interval<Real>
00554 solve(const POL& p,const base_t& u,const base_t& v);
00555
00556 template<class Real, class POL> static Interval<Real>
00557 solve(const POL& p);
00558 };
00559
00564 template<class Ring>
00565 template<class Real, class POL>
00566 Interval<Real>
00567 solver<Ring,CFfirstIsolate >::solve(const POL& p,
00568 const base_t & u,
00569 const base_t & v) {
00570
00571 interval_rep<POL> i(p,u,v);
00572 solver_cffirst<Real,POL> slv(i);
00573
00574 return slv.first_root_isolate();
00575 }
00576
00580 template<class Ring>
00581 template<class Real, class POL>
00582 Interval<Real>
00583 solver<Ring,CFfirstIsolate >::solve(const POL& p) {
00584
00585 interval_rep<POL> i(p);
00586 solver_cffirst<Real,POL> slv(i);
00587
00588 return slv.first_root_isolate();
00589 }
00590
00591
00592
00593 template<class Ring>
00594 struct solver<Ring, CFfirstApproximate > {
00595
00596 typedef typename Ring::scalar_t base_t;
00597
00598 template<class Real, class POL> static Real
00599 solve(const POL& p, const base_t& u, const base_t& v);
00600
00601 template<class Real, class POL> static Real
00602 solve(const POL& p);
00603 };
00604
00609 template<class Ring>
00610 template<class Real, class POL>
00611 Real
00612
00613 solver<Ring,CFfirstApproximate >::solve(const POL& p,
00614 const base_t& u, const base_t& v) {
00615
00616
00617 interval_rep<POL> i(p,u,v);
00618 solver_cffirst<Real,POL> slv(i);
00619
00620 return slv.first_root_approximate();
00621 }
00622
00626 template<class Ring>
00627 template<class Real, class POL>
00628 Real
00629 solver<Ring,CFfirstApproximate >::solve(const POL& p) {
00630
00631
00632 interval_rep<POL> i(p);
00633 solver_cffirst<Real,POL> slv(i);
00634
00635 return slv.first_root_approximate();
00636 }
00637
00638
00639
00640 template<class Ring>
00641 struct solver<Ring, CFfirstFloor> {
00642 typedef typename Ring::Scalar base_t;
00643
00644 template<class Real, class POL> static Real
00645 solve(const POL& p, const base_t& u, const base_t& v);
00646
00647 template<class Real,class POL> static Real
00648 solve(const POL& p);
00649 };
00650
00655 template<class Ring>
00656 template<class Real,class POL>
00657 Real
00658 solver<Ring,CFfirstFloor >::solve(const POL& p,
00659 const base_t& u, const base_t& v) {
00660
00661 interval_rep<POL> i(p,u,v);
00662 solver_cffirst<Real,POL> slv(i);
00663
00664 return slv.first_root_floor();
00665 }
00666
00670 template<class Ring>
00671 template<class Real, class POL>
00672 Real
00673 solver<Ring,CFfirstFloor >::solve(const POL& p) {
00674
00675 interval_rep<POL> i(p);
00676 solver_cffirst<Real,POL> slv(i);
00677
00678 return slv.first_root_floor();
00679 }
00680
00681
00682
00683 template<class Ring>
00684 struct solver<Ring, CFallIsolate > {
00685
00686 typedef typename Ring::Scalar base_t;
00687
00688 template<class Real, class POL> static Seq<Interval<Real> >
00689 solve(const POL& p,const base_t& u,const base_t& v);
00690
00691 template<class Real,class POL> static Seq<Interval<Real> >
00692 solve(const POL& p);
00693 };
00694
00698 template<class Ring>
00699 template<class Real, class POL>
00700 Seq<Interval<Real> >
00701 solver<Ring,CFallIsolate >::solve(const POL& p,
00702 const base_t& u, const base_t& v) {
00703
00704 interval_rep<POL> i(p,u,v);
00705 solver_cffirst<Real,POL> slv(i);
00706
00707 return slv.all_roots_isolate();
00708 }
00709
00713 template<class Ring>
00714 template<class Real,class POL>
00715 Seq<Interval<Real> >
00716 solver<Ring,CFallIsolate >::solve(const POL& p) {
00717
00718 interval_rep<POL> i(p);
00719 solver_cffirst<Real,POL> slv(i);
00720
00721 return slv.all_roots_isolate();
00722 }
00723
00724
00725
00726 template<class Ring>
00727 struct solver<Ring, CFseparate > {
00728
00729 typedef typename Ring::Scalar base_t;
00730
00731 template<class Real,class POL> static Seq<Real>
00732 solve(const POL& p,const base_t& u,const base_t& v);
00733
00734 template<class Real, class POL> static Seq<Real>
00735 solve(const POL& p);
00736 };
00737
00741 template<class Ring>
00742 template<class Real, class POL>
00743 Seq<Real>
00744 solver<Ring,CFseparate >::solve(const POL& p,
00745 const base_t& u, const base_t& v) {
00746
00747 interval_rep<POL> i(p,u,v);
00748 solver_cffirst<Real,POL> slv(i);
00749
00750 return slv.all_roots_separate();
00751 }
00752
00756 template<class Ring>
00757 template<class Real,class POL>
00758 Seq<Real>
00759 solver<Ring,CFseparate >::solve(const POL& p) {
00760
00761 interval_rep<POL> i(p);
00762 solver_cffirst<Real,POL> slv(i);
00763
00764 return slv.all_roots_separate();
00765 }
00766
00767
00768
00769 template<class Ring>
00770 struct solver<Ring,CFdecide> {
00771
00772 template<class POL> static bool
00773 solve(const POL& p);
00774 };
00775
00779 template<class Ring>
00780 template<class POL>
00781 bool
00782 solver<Ring,CFdecide>::solve(const POL& p) {
00783
00784 interval_rep<POL> i(p);
00785 solver_cffirst<QQ,POL> slv(i);
00786
00787 return ( slv.all_roots_isolate().size() );
00788 }
00789
00790
00791 }
00792
00793 #undef TMPL
00794 #undef TMPLR
00795 #undef NO_ROOT
00796 #undef N_ITER
00797 #endif // _realroot_SOLVER_FIRST_ROOT_CONFRAC_H