00001
00002
00003
00004
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
00036
00037 template<class C, int N> struct Interval;
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 struct bound
00052 {
00053 unsigned e;
00054 unsigned m;
00055
00056
00057
00058
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
00071
00072
00073
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
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
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
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
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
00239 if(d==0 )
00240 {
00241
00242 a = real(root_bound);
00243 }
00244 else
00245 {
00246 a /= real(-d);
00247
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
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
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
00319 creal_t * pup, * pdw;
00320 int d;
00321 sz_t a,s,cup;
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
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
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 }
00384 #endif //realroot_solver_binary_hpp