realroot_doc 0.1.1
|
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