realroot_doc 0.1.1
/Users/mourrain/Devel/mmx/realroot/include/realroot/solver_uv_sleeve.hpp
Go to the documentation of this file.
00001 /*******************************************************************
00002  *   This file is part of the source code of the realroot kernel.
00003  *   Author(s): J.P. Pavone GALAAD, INRIA
00004  *              B. Mourrain GALAAD, INRIA
00005  ********************************************************************/
00006 #ifndef realroot_solver_sleeve_hpp
00007 #define realroot_solver_sleeve_hpp
00008 /********************************************************************/
00063 //====================================================================
00064 # include <realroot/IEEE754.hpp>
00065 # include <realroot/texp_bool.hpp>
00066 # include <realroot/array.hpp>
00067 # include <realroot/solver.hpp>
00068 # include <realroot/solver_binary.hpp>
00069 # include <realroot/polynomial_bernstein.hpp>
00070 # include <realroot/polynomial_tensor.hpp>
00071 
00072 # define TMPL    template<class C, class V>
00073 # define SOLVER  solver<C, Sleeve<V> >
00074 //====================================================================
00075 namespace mmx {
00076   template<class V> struct Sleeve{};
00077 
00078   template<class C>
00079   struct sleeve_rep {
00080     C *up, *dw;
00081     unsigned m_sz;
00082 
00083     sleeve_rep(unsigned n): up(new C[n]), dw(new C[n]), m_sz(n) {};
00084     unsigned size() const { return m_sz; }
00085   };
00086 
00087   struct Monomials;
00088   struct Bernstein;
00089   namespace let {
00090     template<class C, class D> void
00091     assign(sleeve_rep<C>& f, const polynomial<D, with<Bernstein> >& p) {
00092       assert(f.size()==(unsigned)(degree(p)+1));
00093       { 
00094         numerics::rounding<C> rnd(numerics::rnd_up());      
00095         for(unsigned i=0;i<f.size();i++) f.up[i]=as<C>(p[i]);
00096       }
00097       { 
00098         numerics::rounding<C> rnd(numerics::rnd_dw());      
00099         for(unsigned i=0;i<f.size();i++) f.dw[i]=as<C>(p[i]);
00100       }
00101     }
00102     template<class C, class D> void
00103     assign(sleeve_rep<C>& f, const polynomial<D, with<MonomialTensor> >& p) {
00104       assert(f.size()==(unsigned)(degree(p)+1));
00105       typedef typename kernelof<D>::T::integer  integer;
00106       typedef typename kernelof<D>::T::rational rational;
00107 
00108       binomials<integer> bn;
00109       unsigned ip=0, in=0;
00110       int d=degree(p);
00111       for(unsigned i=0;i< p.size();i++) {
00112         if(p[i]>p[ip]) {
00113           ip = i;
00114         } 
00115         if(p[i]<p[in]) in=i;
00116       }
00117       rational mx = (p[ip]>-p[in]?as<rational>(p[ip]):as<rational>(-p[in]));
00118       rational c;
00119       {
00120         numerics::rounding<C> rnd( numerics::rnd_up() );
00121         for ( int i = 0; i <= d; i ++ ) {
00122           c = as<rational>(p[i])/(mx*bn(d,i));
00123           f.up[i]=as<C>(c);
00124         }
00125       }
00126       {
00127         numerics::rounding<C> rnd( numerics::rnd_dw() );
00128         for ( int i = 0; i <= d; i ++ ) {
00129           c = as<rational>(p[i])/(mx*bn(d,i));
00130           f.dw[i]=as<C>(c);
00131         }
00132       } 
00133       //      polynom< ring<rational,Bernstein> > q;
00134       //      let::assign(q,p);
00135       //  assign(f,q);
00136     }
00137 
00138   }
00139   //====================================================================  
00140   template<class K, class Num>  struct binary_convert {};
00141   template<class K>
00142   struct binary_convert<K,Isolate>: public K {
00143 
00144     typedef Seq<Interval<typename K::ieee> >  Solutions;
00145     static data_t data;
00146 
00147     template<class output, class real> static inline
00148     void get(output& sol, const real& first = 0, const real& last =1)
00149     {
00150       typedef typename output::value_type root_t;
00151       typedef root_t                      as_root;
00152       //      unsigned s = o.size();
00153       real a,b;
00154       //      o.resize(s+2*size());
00155       real scale = last-first;
00156       for ( unsigned i = 0; i < data.nb_sol(); i ++ )
00157         {
00158           data_t::convert(a,data.m_res[i].a,first, scale);
00159           data_t::convert(b,data.m_res[i].b,first, scale);
00160           sol << as<root_t>(Interval<real>(a,b));
00161         };
00162     };
00163 
00164     template<class output, class real> static inline
00165     void get(output & sol, const homography<real>& H)
00166     {
00167       typedef typename output::value_type root_t;
00168       typedef root_t                      as_root;
00169       typedef typename root_t::value_type bound_t;
00170       //      unsigned s = o.size();
00171       bound_t u,v;
00172       real dt= H.a*H.d-H.b*H.c;
00173       if(dt>0)
00174         for (unsigned i = 0; i < data.nb_sol(); i ++ )
00175           {
00176             data.convert(u,data.m_res[i].a,H);
00177             data.convert(v,data.m_res[i].b,H);
00178             sol << as_root(u,v);
00179           }
00180       else
00181         for ( int i = data.nb_sol()-1; i >=0 ; i --)
00182           {
00183             data.convert(u,data.m_res[i].b,H);
00184             data.convert(v,data.m_res[i].a,H);
00185             sol << as_root(u,v);
00186           }
00187     }
00188   };
00189   template <class K>  data_t binary_convert<K,Isolate>::data(true);
00190   //====================================================================
00191   template<class K>
00192   struct binary_convert<K,Approximate> : public K 
00193   {
00194     typedef unsigned unsigned_t;
00195     typedef Seq<typename K::ieee>  Solutions;
00196     typedef typename K::integer integer;
00197     static data_t data;
00198     
00199     static inline 
00200     integer binomial(const integer& n,const integer& p){return K::binomial(n,p);}
00201 
00202     template<class C> static inline C as_root(const C& a, const C& b) {return (a+b)/2;}
00203 
00204     template<class output, class real> static inline
00205     void get(output& sol, const real& first = 0, const real& last =1)
00206     {
00207       typedef typename output::value_type root;
00208       real a,b;
00209       real scale= last-first;
00210       for (unsigned i = 0; i < data.nb_sol(); i ++ )
00211         {
00212           data_t::convert(a,data.m_res[i].a, first, scale);
00213           data_t::convert(b,data.m_res[i].b, first, scale);
00214           sol << as<root>(Interval<real>(a,b));
00215         }
00216     } 
00217 
00218     template<class output, class real> static inline
00219     void get(output& sol, const homography<real>& H)
00220     {
00221       //  typedef typename output::value_type as_root;
00222       //root_t u,v;
00223       unsigned s=data.nb_sol();
00224       std::vector<real> u(s);
00225       real v;
00226       real dt=H.a*H.d-H.b*H.c;
00227 
00228       if(dt>0)
00229         {
00230           {     
00231             numerics::rounding<real> rnd(numerics::rnd_dw());
00232             for ( unsigned i = 0; i < s; i ++ )
00233               data.convert(u[i],data.m_res[i].a,H);
00234           }
00235           {
00236             numerics::rounding<real> rnd(numerics::rnd_up());
00237             for ( unsigned i = 0; i < s; i ++ ) {
00238               data.convert(v,data.m_res[i].b,H);
00239               sol << as_root(u[i],v);
00240             }
00241           }
00242         }
00243       else
00244         {
00245           {     
00246             numerics::rounding<real> rnd(numerics::rnd_dw());
00247             for (int i = s-1; i >=0; i -- )
00248               data.convert(u[i],data.m_res[i].a,H);
00249           }
00250           {
00251             numerics::rounding<real> rnd(numerics::rnd_up());
00252             for (int i = s-1; i >=0; i -- ) {
00253               data.convert(v,data.m_res[i].b,H);
00254               sol << as_root(v,u[i]);
00255             }
00256           }
00257         }
00258     }
00259 
00260   };
00261 
00262   template <class K>  data_t binary_convert<K,Approximate>::data(false);
00263 
00264   //====================================================================
00266   template < class K>
00267   struct binary_sleeve_subdivision : public K {
00268 
00269     typedef typename K::integer  integer;
00270     typedef typename K::rational rational;
00271     //    typedef typename K::floating floating;
00272     //    typedef typename K::ieee     ieee;
00273 
00274     typedef double                      creal_t;
00275     typedef unsigned                    sz_t; 
00276     typedef binary_subdivision<K>       Base_t;
00277     typedef typename Base_t::unsigned_t unsigned_t;
00278     typedef res_t                       Domain_t;
00279   
00280     //    sleeve(): Base_t(1e-6){}
00281     //    sleeve(creal_t e): Base_t(e){}
00282 
00283     static inline void alloc( sz_t s, sz_t deep  ) 
00284     {
00285       K::data.alloc(s,2*s,deep); 
00286     };
00287     
00288     static void barre( char c, unsigned n )
00289     {
00290       char  _bar[ n+1 ];
00291       std::fill(_bar,_bar+n, c);
00292       _bar[n] = 0;
00293       std::cout << _bar << std::endl;
00294     };
00295     
00296     static void writebounds( creal_t * pup, creal_t * pdw, unsigned s )
00297     {
00298       Base_t::print(pup,s); std::cout << std::endl;
00299       Base_t::print(pdw,s); std::cout << std::endl;
00300     };
00301    
00302     static inline 
00303     bool glue( sz_t cup, sz_t cdw, int d )
00304     {
00305       if ( K::data.bckb() == K::data.m_dmn[d] )
00306         {
00307           K::data.bckb() = K::data.m_dmn[d];
00308           K::data.bckb().m += 1;
00309           if ( cup ) K::data.m_cup = cup;
00310           if ( cdw ) K::data.m_cdw = cdw;
00311           return true;
00312         };
00313       return false;
00314     };
00315     
00316     static inline 
00317     void mstore( sz_t cup, sz_t cdw, int d  ) 
00318     {
00319       if ( K::data.m_res.size() == 0 || !glue(cup,cdw,d)  )
00320         {
00321           K::data.mstore(d);
00322           K::data.m_cup = cup;
00323           K::data.m_cdw = cdw;
00324           //std::cout << "Push ";
00325         };
00326       //      writebck();
00327     };
00328   
00329 
00330     static inline
00331     void dwsplit( creal_t * r, creal_t * l, sz_t s )
00332     {
00333       numerics::rounding<creal_t> rnd( numerics::rnd_dw() );
00334       Base_t::split(r,l,s);
00335     };
00336 
00337     static inline 
00338     void upsplit( creal_t * r, creal_t * l, sz_t s )
00339     {
00340       numerics::rounding<creal_t> rnd( numerics::rnd_up() );
00341       Base_t::split(r,l,s);
00342     };
00343     
00344     static void Loop( bool isole = true ) {
00345       //      std::cout << "LOOP\n";
00346       numerics::rounding<creal_t> rnd(numerics::rnd_dw());
00347       creal_t * pup, * pdw;
00348       int d;
00349       sz_t a,s,cup,cdw;
00350       //      unsigned_t v;
00351       s = K::data.m_s;
00352       pup = K::data.m_data;
00353       pdw = K::data.m_data + s;
00354       K::data.m_dmn[0].m = 0;
00355       K::data.m_dmn[0].e = 0;
00356       for( a = 0, d = 0; d >= 0; d--, a -= 2*s   ) 
00357         {
00358           cup = Base_t::sgncnt(pup+a,s);
00359           cdw = Base_t::sgncnt(pdw+a,s);
00360           if ( cup || cdw )
00361             {
00362               if ( isole && cup == cdw && cup == 1 ){ 
00363                 //std::cout << " (b) \n";
00364                 K::data.sstore(d);
00365                 continue; 
00366               };
00367               if ( K::data.m_dmn[d].e == K::data.m_limit-1 ) { 
00368                 // std::cout << " (c) "<<cup<<" "<<cdw<<"\n";
00369                 if ( cup == cdw && cup == 1 )
00370                   K::data.sstore(d);
00371                 else
00372                   mstore(cup,cdw,d); 
00373                 continue; 
00374               };
00375               dwsplit(pdw+a,pdw+a+2*s,s);    
00376               upsplit(pup+a,pup+a+2*s,s);
00377               Base_t::split(K::data.m_dmn[d],K::data.m_dmn[d+1]);
00378               d += 2;
00379               a += 4*s;
00380               continue;
00381             } else {
00382             //std::cout<<"  (a) ";
00383             sz_t k =0, sv=0;
00384             for (  k = 0; k < K::data.m_s; k ++ ) {
00385               if ( ( pup[a+k] > 0 ) != ( pdw[a+k] > 0 ) ) {
00386                 sv++;
00387                 if(sv>1) { 
00388                   mstore(cup,cdw,d); 
00389                   break; 
00390                 };
00391               }
00392             }
00393             //std::cout<<std::endl;
00394           };
00395         };
00396       // std::cout << "END LOOP\n";
00397     };
00398     
00399 
00400     template<class input> static 
00401     void run_loop( const input& in, const creal_t& eps, const texp::true_t&   ) {
00402       //      binary_subdivision<K> slv(eps);
00403       sz_t prec = numerics::bitprec(eps);
00404       alloc(in.size(),prec);
00405       std::copy(in.begin(),in.end(),K::data.m_data);
00406       std::copy(in.begin(),in.end(),K::data.m_data+K::data.m_s);
00407       Loop(K::data.isole);
00408     };
00409     
00410     const Domain_t& operator[]( int i ) const  { return K::data.m_res[i]; };
00411     Domain_t&       operator[]( int i ) { return K::data.m_res[i]; };
00412     
00413   
00414     template<class output, class input> static inline
00415     void solve_bernstein( output& out, const input& in) {
00416       run(in,K::data.eps);
00417       //      solutions<typename output::value_type>::get(this,out);
00418     }
00419     template<class VECT,class POL,class Q> static inline 
00420     void init_pol(VECT& ubp, VECT& dbp, const POL& r,  unsigned sz, const Q& u, const Q&v);
00421 
00422 
00423     template<class input> static inline
00424     void run( const input& in, const creal_t& eps)
00425     { 
00426       typedef typename numerics::is_rounded<creal_t>::result_t round_t;
00427       run_loop(in,eps,round_t()); 
00428     }
00429     
00430     template<class C> static void 
00431     run( const sleeve_rep<C>& p) {
00432       sz_t prec = numerics::bitprec(K::data.eps);
00433       alloc(p.size(),prec);
00434       std::copy(p.up,p.up+p.size(),K::data.m_data);
00435       std::copy(p.dw,p.dw+p.size(),K::data.m_data+K::data.m_s);
00436       Loop(K::data.isole);
00437     }
00438 
00439     template<class input> static 
00440     void run( const input& up, const input& dw) {
00441       assert(up.size()==dw.size());
00442       sz_t prec = numerics::bitprec(K::data.eps);
00443       alloc(up.size(),prec);
00444       std::copy(up.begin(),up.end(),K::data.m_data);
00445       std::copy(dw.begin(),dw.end(),K::data.m_data+K::data.m_s);
00446       Loop(K::data.isole);
00447     }
00448     
00454     template <typename output, typename POL, typename Q> static 
00455     void solve(output& sol, const POL& r, const Q& u, const Q& v);
00456     
00457     //--------------------------------------------------------------------
00458     template<class output, class input,class real,class MTH> static inline
00459     void solve_bernstein( output& sol, 
00460                           const input& up, const input& dw, 
00461                           const real& u, const real& v, const MTH& mth)
00462     { 
00463       K::data.isole=mth.isole;
00464       run(up,dw);
00465       get(sol,u,v);
00466       //      solutions<typename output::value_type>::get(this,out,u,v);
00467     }
00468   
00469     //--------------------------------------------------------------------
00475     template <typename output, typename POL ,typename real, typename MTH> static 
00476     void solve_bernstein(output& sol, const POL& r, const real& u,const real& v, const MTH& mth )
00477     {
00478       typedef typename output::value_type    root_t;    
00479       using let::assign;
00480       
00481       unsigned sz= r.size();
00482       std::vector<creal_t> ubp( sz ), dbp( sz );
00483       {
00484         numerics::rounding<creal_t> rnd( numerics::rnd_up() );
00485         for(unsigned i=0;i<sz;i++) ubp[i] =as<creal_t>(r[i]);
00486       }
00487       {
00488         numerics::rounding<creal_t> rnd( numerics::rnd_dw() );
00489         for(unsigned i=0;i<sz;i++) dbp[i] =as<creal_t>(r[i]);
00490       }
00491       K::data.isole=mth.isole; 
00492       run(ubp,dbp);
00493       get(sol,u,v);
00494       //      solutions<typename output::value_type>::get(this, sol, u,v);
00495     }
00496   };
00497   //====================================================================
00498   template<class K>
00499   template<class VECT,class POL,class Q>
00500   void binary_sleeve_subdivision<K>::init_pol(VECT& ubp, VECT& dbp, const POL& r, unsigned sz,const Q& u, const Q&v)
00501   {
00502     using let::assign;
00503   
00504 #if 1
00505     //    PRINT_DEBUG("Conversion using exact arithmetic");
00506     rational U,V;
00507     assign(U,u);
00508     assign(V,v);
00509     //    std::vector<interval> bp( sz );
00510     std::vector<rational> bp(sz);
00511     univariate::convertm2b(bp,r,sz,U,V);
00512     rational mx = array::max_abs(bp);
00513     array::div(bp,mx);
00514     // unsigned i;
00515     //    for (i = 0; i < sz && bp[i].upper()-bp[i].lower()<as<floating>(1.e-16); i ++ );
00516     //    if(i<sz) std::cout<<"refine: "<<i<<" " <<(bp[i].upper()-bp[i].lower())<<std::endl;
00517     //    double l; assign(l, rational(V-U));
00518     //    std::cout<<"\t init: "<<sign_variation(bp)<<" "<<l<<std::endl;
00519     {
00520       numerics::rounding<creal_t> rnd( numerics::rnd_up() );
00521       for ( unsigned i = 0; i < sz; i ++ ) ubp[i]=as<creal_t>(bp[i]);
00522     }
00523     {
00524       numerics::rounding<creal_t> rnd( numerics::rnd_dw() );
00525       for ( unsigned i = 0; i < sz; i ++ ) dbp[i]=as<creal_t>(bp[i]);
00526     };
00527    
00528 #else
00529     //    PRINT_DEBUG("Using rounding arithmetic");
00530     O ud, vd;
00531     {
00532       numerics::rounding<creal_t> rnd( numerics::rnd_dw() );
00533       ud=as<creal_t>(u);
00534     };
00535     {
00536       numerics::rounding<creal_t> rnd( numerics::rnd_up() );
00537       vd=as<creal_t>(v);
00538       BEZIER::monomial_to_bezier(ubp,r,r.size(),ud,vd);
00539     };
00540     {
00541       numerics::rounding<creal_t> rnd( numerics::rnd_dw() );
00542       BEZIER::monomial_to_bezier(dbp,r,r.size(),ud,vd);
00543     };
00544 
00545     for ( unsigned i= 0; i < ubp.size(); i ++ )
00546       if ( dbp[i] > ubp[i] ) { 
00547         std::swap(dbp[i], ubp[i]);
00548       };
00549 #endif
00550 
00551   }
00552   //------------------------------------------------------------------
00553    template <class K>
00554   template <typename output, typename POL ,typename Q>
00555   void binary_sleeve_subdivision<K>::solve(output& sol, const POL& r, const Q& u, const Q& v)
00556   {
00557     unsigned sz= r.size();
00558     std::vector<double> ubp(sz), dbp(sz);
00559     init_pol(ubp,dbp,r,sz,u,v);
00560     run(ubp,dbp,true);
00561     //    run(ubp,dbp,this->eps,mth.isolate);
00562     //    solutions<typename output::value_type>::get(this,sol,u,v);
00563   }
00564 
00565   //====================================================================
00566   TMPL
00567   struct solver<C, Sleeve<V> > {
00568   
00569     typedef typename kernelof<C>::T          K;
00570     typedef typename binary_convert<K,V>::Solutions         Solutions;
00571     // Seq<Interval<typename K::ieee> >                    Solutions;
00572     typedef binary_sleeve_subdivision<binary_convert<K,V> > base_t;
00573 
00574 
00575     template<class POL> static void
00576     solve(Solutions& sol, const POL& p);
00577 
00578     template<class POL,class T> static void
00579     solve(Solutions& sol, const POL& p, const T& u, const T& v);
00580 
00581     template<class T, class U, class VRT> static void
00582     solve(Solutions& sol, const polynomial<U,VRT>& pl, const polynomial<U,VRT>& pu, const T& u, const T& v);
00583 
00584     template<class U,class VRT> static void
00585     solve(Solutions& sol, const polynomial<U,VRT>& pl, const polynomial<U,VRT>& pu);
00586 
00587 
00588     static inline void 
00589     set_precision(unsigned p) { binary_convert<K,V>::set_precision(p); }
00590 
00591   };
00592 
00595   TMPL
00596   template<class POL> void
00597   SOLVER::solve(Solutions& sol, const POL& p) {
00598       typedef typename K::ieee real_t;
00599       sleeve_rep<real_t> f(degree(p)+1); 
00600       let::assign(f,p);
00601       real_t c;
00602       for(unsigned i=1;i< f.size();i+=2) {
00603         c=f.up[i];f.up[i]=-f.dw[i];f.dw[i]=-c;
00604       }
00605       base_t::run(f);
00606 
00607       homography<real_t> H(1,0,1,-1);
00608       base_t::data.root_bound = - bound_root(p,Cauchy<real_t>());
00609       base_t::get(sol,H);
00610 
00611       for(unsigned i=1;i< f.size();i+=2) {
00612         c=f.up[i];f.up[i]=-f.dw[i];f.dw[i]=-c;
00613       }
00614       base_t::run(f);
00615       base_t::data.root_bound = - base_t::data.root_bound;
00616       H.c=-1;H.d=1;
00617       base_t::get(sol,H);
00618     }
00619   //--------------------------------------------------------------------
00620   TMPL
00621   template<class T, class U, class VRT> void
00622   SOLVER::solve(Solutions& sol, 
00623                 const polynomial<U,VRT>& pl, const polynomial<U,VRT>& pu,
00624                 const T& u, const T& v) {
00625     base_t::run(pl,pu);
00626     base_t::get(sol,u,v);
00627   }
00628 
00629   //--------------------------------------------------------------------
00630   TMPL
00631   template<class U, class VRT> void
00632   SOLVER::solve(Solutions& sol, 
00633                 const polynomial<U,VRT>& pl, const polynomial<U,VRT>& pu) {
00634     base_t::run(pl,pu);
00635     base_t::get(sol,0,1);
00636   }
00637 
00638   //--------------------------------------------------------------------
00639   TMPL
00640   template<class POL, class T> void
00641   SOLVER::solve(Solutions& sol, const POL& p,
00642                 const T& u, const T& v) {
00643     typedef typename POL::Ring                        Ring;
00644     typedef typename SOLVER::base_t      base_t;
00645     typedef typename SOLVER::Solutions Solutions;
00646     unsigned sz= p.size();
00647     std::vector<double> ubp(sz), dbp(sz);
00648     base_t::init_pol(ubp,dbp,p,sz,u,v);
00649     base_t::run(ubp,dbp);
00650     base_t::get(sol,u,v);
00651   }
00652   //--------------------------------------------------------------------
00653   template<class POL, class M, class B>
00654   typename solver<B, Sleeve<M> >::Solutions 
00655   solve (const POL& p, const Sleeve<M>& slv, const B& u, const B& v) {
00656     typedef solver<B, Sleeve<M> >                       Solver;
00657     typedef typename Solver::Solutions                  Solutions;
00658     Solutions sol;
00659     Solver::solve(sol,p, u,v);
00660     return sol;
00661   }
00662   //--x------------------------------------------------------------------
00663   template<class POL, class M>
00664   typename solver<typename POL::Scalar, Sleeve<M> >::Solutions 
00665   solve (const POL& p, const Sleeve<M>& slv) {
00666     typedef typename POL::Scalar                             Scalar;
00667     typedef solver<Scalar, Sleeve<M> >                       Solver;
00668     typedef typename solver<Scalar, Sleeve<M> >::Solutions   Solutions;
00669     Solutions sol;
00670     Solver::solve(sol,p);
00671     return sol;
00672   }
00673 
00674 } //namespace mmx
00675 //====================================================================
00676 # undef TMPL
00677 # undef SOLVER
00678 //====================================================================
00679 #endif  //realroot_solver_sleeve_hpp
00680