realroot_doc 0.1.1
/Users/mourrain/Devel/mmx/realroot/include/realroot/solver_binary.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_binary_hpp
00007 #define realroot_solver_binary_hpp
00008 /********************************************************************/
00009 #include <realroot/Seq.hpp>
00010 #include <realroot/binomials.hpp>
00011 #include <realroot/univariate_bounds.hpp>
00012 #include <realroot/rounding_mode.hpp>
00013 #include <realroot/numerics_hdwi.hpp>
00014 #include <realroot/sign_variation.hpp>
00015 #include <realroot/solver.hpp>
00016 #include <realroot/homography.hpp>
00017 #include <realroot/scalar_bigunsigned.hpp>
00018 #include <assert.h>
00019 #include <vector>
00020 #include <algorithm>
00021 //====================================================================
00022 namespace mmx {
00023 
00024 #ifndef WITH_AS
00025 #define WITH_AS
00026   template<typename T,typename F>
00027   struct cast_helper {
00028     static inline T cv (const F& x) { return x; }
00029   };
00030   
00031   template<typename T,typename F> inline 
00032   T as (const F& x) {  return cast_helper<T,F>::cv (x); }
00033 #endif
00034 
00035   //  template<class C> inline void operator<<(std::vector<C>& v, const C& x) { v.push_back(x) ; }
00036 
00037   template<class C, int N> struct Interval;
00038   //  template<class C> struct with_rounding { typedef meta::false_t T;};
00039   //  template<class C, int N> struct with_rounding<Interval<C,N> > { typedef typename with_rounding<C>::T T;};
00040   //  template<>               struct with_rounding<double> { typedef meta::true_t T;};
00041 
00042  //  template<class real>  struct Homography
00043 //   {
00044 //     real a,b,c,d;
00045 //     Homography(): a(1),b(0),c(0),d(1) {}
00046 //     Homography(const Homography& H): a(H.a),b(H.b),c(H.c),d(H.d) {}
00047 //     Homography(const real& A, const real& B, const real& C, const real&D): a(A),b(B),c(C),d(D) {}
00048 //   };
00049 
00050   //====================================================================
00051   struct bound
00052   {
00053     unsigned  e; 
00054     unsigned  m;
00055 
00056 //     bound() :e(0), m(0){}
00057 //     bound(const bound& b) :e(b.e), m(b_m.hpp){}
00058 //     bound & operator=(const bound& b) {e=b.e; m=b_m.hpp;return *this;}
00059 
00060     bool operator==( const bound& b )
00061     {
00062       if ( e < b.e )
00063         {
00064           return (m << (b.e-e)) == b.m;
00065         };
00066       return (b.m << (e-b.e)) == m;
00067     };
00068   };
00069   //--------------------------------------------------------------------
00070   //    struct dmn_t
00071   //    {
00072   //      unsigned   h;
00073   //      unsigned_t v;
00074   //    };
00075   //====================================================================
00076   struct res_t { 
00077     bound a;
00078     bound b;
00079     bool t;  
00080   };
00081   //====================================================================
00082   struct data_t {
00083     typedef double creal_t;
00084     typedef unsigned sz_t;
00085     typedef unsigned unsigned_t;
00086 
00087     creal_t  *m_data;
00088     bound    *m_dmn ;
00089     sz_t      m_limit;
00090     sz_t      m_s;
00091     sz_t      m_cup;
00092     sz_t      m_cdw;
00093     creal_t   eps, root_bound;
00094     bool      isole;
00095     std::vector<res_t> m_res;
00096 
00097     data_t(): eps(1e-6) { m_data = 0; };
00098     data_t(bool isl): eps(1e-6), isole(isl) { m_data = 0; };
00099     data_t(const creal_t& e): eps(e) { m_data = 0; };
00100     ~data_t() { Free(); };
00101     
00102     inline 
00103     void Free() 
00104     { 
00105       if ( m_data ) 
00106         { 
00107           delete[] m_data; 
00108           delete[] m_dmn; 
00109           m_res.resize(0); 
00110         }; 
00111     }
00112         
00113     inline 
00114     void alloc( sz_t s, sz_t cs, sz_t deep  )
00115     { 
00116       Free();
00117       m_s = s;
00118       m_limit = std::min((sz_t)numerics::hdwi<sz_t>::nbit,deep);
00119       m_data  = new creal_t [ cs*m_limit ];
00120       m_dmn   = new bound   [ m_limit ];
00121       m_res.resize(0);
00122       //      std::cout<<"Alloc "<<m_limit<<std::endl;
00123     }
00124   
00125     inline const bound& bcka() const { return m_res.back().a; };
00126     inline       bound& bcka()       { return m_res.back().a; };
00127     inline const bound& bckb() const { return m_res.back().b; };
00128     inline       bound& bckb()       { return m_res.back().b; };
00129     
00130     inline        bool& bckt()       { return m_res.back().t; };
00131     inline        bool  bckt() const { return m_res.back().t; };
00132     
00133 
00134     inline void set_back_a(const bound& a) { m_res.back().a = a;};
00135     inline void set_back_b(const bound& b) { m_res.back().b = b;};
00136     
00137     inline void setbck( const bound& a, const bound& b, bool type )
00138     {
00139       bcka() = a;
00140       bckb() = b;
00141       bckt() = type;
00142     };
00143 
00144     inline 
00145     void pshbck()
00146     {
00147       m_res.push_back(res_t());
00148     };
00149     
00150     inline 
00151     void sstore( int d, int t = 1 ) 
00152     {
00153       // m_data + d*m_s;
00154       pshbck();
00155       bcka() = m_dmn[d];
00156       bckb() = bcka();
00157       bckb().m += t;
00158       bckt() = true;
00159     };
00160   
00161     inline 
00162     void bstore( int d, int t = 1 ) 
00163     {
00164       // m_data + d*m_s;
00165       pshbck();
00166       bcka() = m_dmn[d];
00167       bcka().m += t;
00168       bckb() = bcka();
00169       bckt() = true;
00170     };
00171 
00172     inline 
00173     void estore( int d, int t = 1 ) 
00174     {
00175       // m_data + d*m_s;
00176       pshbck();
00177       bckb() = m_dmn[d];
00178       bckb().m += t;
00179       bcka() = bckb();
00180       bckt() = true;
00181     };
00182   
00183     inline 
00184     void mstore( int d ) 
00185     {
00186       sstore(d);
00187       bckt() = false;
00188     };
00189 
00190     sz_t size() const  { return m_res.size(); };
00191     sz_t nb_sol()      { return m_res.size();}
00192 
00193 
00194     void writedomain( int d )
00195     {
00196       std::cout << "Domaine-" << d << std::endl;
00197       std::cout << "\thauteur = " << m_dmn[d].e << std::endl;
00198       std::cout << "\tvaleur  = " << m_dmn[d].m << std::endl;
00199     };
00200 
00201     void writebck()
00202     {
00203       std::cout << "Back " << std::endl;
00204       std::cout << "\tA = " << bcka().e << " , " << bcka().m  << std::endl;
00205       std::cout << "\tB = " << bckb().e << " , " << bckb().m  << std::endl;
00206     };
00207     
00208     inline creal_t get_root_bound() { return root_bound;}
00209 
00210     template<class real> static
00211     void convert( real& a, const bound& b, 
00212                   const real & first = 0, const real & scale = 1  )
00213     {
00214       unsigned m(b.m);
00215       numerics::hdwi<unsigned_t>::reverse(b.e+1,m);
00216       a = first;
00217       real x = scale;
00218       for ( unsigned i = 0; i < b.e + 1; x /= 2, i ++ )
00219         {
00220           if ( m & 1 ) a += x;
00221           m >>= 1;
00222         };
00223     }
00224 
00225     template<class real, class coeff> 
00226     void convert( real& a, const bound& b, const homography<coeff>& H)
00227     {
00228       unsigned_t m(b.m);
00229       numerics::hdwi<unsigned_t>::reverse(b.e+1,m);
00230       a = H.b;
00231       real d = -H.d;
00232       real x = H.a, y = -H.c;
00233       for ( unsigned i = 0; i < b.e + 1; x /= 2, y/=2, i ++ )
00234         {
00235           if ( m & 1 ) {a += x; d+=y;}
00236           m >>= 1;
00237         };
00238       //      std::cout <<"\n\t d= "<<d<<" a= "<<a<< std::endl;
00239       if(d==0 )
00240         {
00241           //  std::cout <<"\n\t rb= "<<this->root_bound<< std::endl;
00242           a = real(root_bound);
00243         }
00244       else
00245         {
00246           a /= real(-d);
00247           //std::cout <<"\t d!=0 a= "<<a<< std::endl;
00248         }
00249     };
00250 
00251 
00252   };
00253 
00254   //====================================================================
00255   template<class K >
00256   struct binary_subdivision : public K {
00257    
00258     typedef typename K::integer  integer;
00259     typedef typename K::rational rational;
00260     typedef typename K::floating floating;
00261     typedef typename K::ieee     C;
00262   
00263     typedef unsigned sz_t;
00264     //  typedef unsigned unsigned_t;
00265     static const sz_t bitquo = numerics::bit_resolution<C>::nbit / numerics::hdwi<sz_t>::nbit;
00266     static const sz_t bitrem = numerics::bit_resolution<C>::nbit % numerics::hdwi<sz_t>::nbit;
00267 
00268     typedef bigunsigned<bitquo+(sz_t)(bitrem!=0)> unsigned_t;
00269     typedef C creal_t;
00270 
00271     static data_t data;
00272   
00273     inline
00274     static void split( creal_t * r, creal_t * l, sz_t sz )
00275     {
00276       creal_t * er, * p;
00277       er = r + (sz-1);
00278       for ( er = r + (sz-1); er != r; er--, l++ )
00279         {
00280           *l = *r;
00281           for ( p = r; p != er; p ++ )
00282             *p = (*p+*(p+1))/2;
00283         };
00284       *l = *r;
00285     };
00286   
00287     static sz_t sgncnt ( creal_t const *  b , sz_t sz )
00288     {
00289       creal_t const * last = b + sz;
00290       sz_t c;
00291       int prv = (((*b>0)<<1)|(*b<0));
00292       int crr;
00293       for ( c = 0; b != last && c<2; crr = (((*b>0)<<1)|(*b<0)), c += prv != crr, prv = crr, b ++ ) ;
00294       //      std::cout<<"sgncnt "<< c<<std::endl;
00295       return c;
00296     };
00297   
00298     static inline void split( bound& r, bound& l )
00299     {
00300       r.m <<= 1;
00301       l.m = r.m;
00302       r.m |=  1;
00303       r.e ++;
00304       l.e = r.e;
00305     };
00306         
00307     static inline
00308     void print( creal_t * p, sz_t  n )
00309     {
00310       std::cout << "[";
00311       for ( sz_t i = 0; i < n-1; i ++ )
00312         std::cout << p[i] << ",";
00313       std::cout << p[n-1] << " ]";
00314     };
00315     
00316     void Loop( bool isole = true )
00317     {
00318       //      std::cout <<"Starting simple solver loop"<<std::endl;
00319       creal_t * pup, * pdw;
00320       int d;
00321       sz_t h,a,s,cup,cdw;
00322       unsigned_t v;
00323       s = data.m_s;
00324       pup = data.m_data;
00325       data.m_dmn[0].m = 0;
00326       data.m_dmn[0].e = 0;
00327       for( a = 0, d = 0; d >= 0; d--, a -= s   ) 
00328         {
00329           cup = sgncnt(pup+a,s);
00330           if ( cup ) 
00331             {
00332               if ( isole && cup == 1 ) { data.sstore(d); continue; };
00333               if ( data.m_dmn[d].e == data.m_limit-1 )
00334                 {
00335                   if ( cup == 1 ) 
00336                     {
00337                       if ( *(pup+a) != 0 )
00338                         {
00339                           if ( *(pup+a+s-1) == 0 )
00340                             data.sstore(d,0);
00341                           else 
00342                             data.sstore(d);
00343                         };
00344                     }
00345                   else  
00346                     {
00347                       data.mstore(d);
00348                       //std::cout<<"s "<<cup<<" "<<d<<" "<<data.m_limit<<std::endl;
00349                     }
00350                   continue;
00351                 };
00352               split(pup+a,pup+a+s,s);
00353               split(data.m_dmn[d],data.m_dmn[d+1]);
00354               d += 2;
00355               a += 2*s;
00356             };
00357         };
00358       //std::cout <<"End of simple solver loop"<<std::endl;
00359     };
00360 
00361     //--------------------------------------------------------------------
00362     template<class output>
00363     void get_flags( output& o )
00364     {
00365       unsigned s = o.size();
00366       o.resize( s + o.size() );
00367       for ( sz_t i = 0; i < data.m_res.size(); o[s+i] = data.m_res[i++].t ) ;
00368     };
00369     //--------------------------------------------------------------------
00370     template<class input>
00371     void run_loop( const input& in, const creal_t& eps, bool isole, texp::false_t)
00372     {
00373       sz_t prec = numerics::bitprec(eps);
00374       data.alloc(in.size(),prec);
00375       std::copy(in.begin(),in.end(),data.m_data);
00376       Loop(isole);
00377     };
00378    
00379   };
00380 
00381   template <class K>  data_t binary_subdivision<K>::data;
00382 //====================================================================
00383 } //namespace mmx
00384 #endif //realroot_solver_binary_hpp