00001
00002
00003
00004
00005
00006
00008 #ifndef realroot_UPOL_BOUND_H
00009 #define realroot_UPOL_BOUND_H
00010
00011 #include <realroot/rounding_mode.hpp>
00012 #include <realroot/GMP.hpp>
00013 #include <realroot/texp_rationalof.hpp>
00014 #include <realroot/vector_monomials.hpp>
00015 #include <vector>
00016 #include <stack>
00017 #include <queue>
00018
00019
00020 namespace mmx {
00021
00022 using univariate::lcoeff;
00023
00024 #ifndef MMX_ABS_FCT
00025 #define MMX_ABS_FCT
00026 template<typename T> inline T abs(const T& x) { return (x < 0 ? -x : x); }
00027 #endif
00028
00029
00030 template<class T>
00031 T pow2(int i)
00032 {
00033 assert(i>=0);
00034 if(i == 1) return 2;
00035 if(i > 0)
00036 {
00037 T y(2);
00038 T z(1);
00039 unsigned int n = i;
00040 unsigned int m;
00041 while (n > 0) {
00042 m = n / 2;
00043 if (n %2 )
00044 {
00045 z *= y;
00046 }
00047 y = y * y;
00048 n = m;
00049 }
00050 return z;
00051 }
00052 return T(1);
00053 }
00054
00055
00057 template<class C> struct NISP
00058 {
00059
00067 template <typename POLY> static
00068 C upper_bound(const POLY& p)
00069 {
00070 typedef typename texp::rationalof<C>::T rational;
00071
00072
00073 C max(0), sum(0);
00074
00075 unsigned i;
00076 unsigned n = p.size();
00077
00078
00079 i = n; while ( p[--i] == 0 ) ; n = i+1;
00080 if ( p[i] > 0 )
00081 {
00082 i = 0;
00083 while ( p[i] > 0 && i < n ) i++;
00084 if ( i == n ) return 0;
00085
00086 for ( unsigned k = i+1; k < n; k ++ )
00087 if ( p[k] > 0 ) sum += p[k];
00088
00089 for ( unsigned k = i; k < n; k ++ )
00090 {
00091 if ( p[k] < 0 )
00092 { rational tmp = -p[k]/sum; if ( tmp > max ) max = tmp; }
00093 else
00094 sum -= p[k];
00095 };
00096 }
00097 else
00098 {
00099 i = 0;
00100 while ( p[i] < 0 && i < n ) i++;
00101 if ( i == n ) return 0;
00102 for ( unsigned k = i+1; k < n; k ++ )
00103 if ( p[k] < 0 ) sum += p[k];
00104 for ( unsigned k = i; k < n; k ++ )
00105 if ( p[k] > 0 ) { rational tmp = -p[k]/sum; if ( tmp > max ) max = tmp; }
00106 else sum -= p[k];
00107 };
00108 max += 1;
00109 return max;
00110 }
00111
00112
00113 template <typename POLY> static
00114 C lower_bound(const POLY& p)
00115 {
00116 typedef typename texp::rationalof<C>::T rational;
00117 using univariate::degree;
00118
00119 POLY r(p);
00120 reverse(r,degree(r));
00121 rational m = NISP<rational>::upper_bound(r);
00122 return denominator(m)/numerator(m);
00123 }
00124 };
00125
00127 template<class FT> struct NISN
00128 {
00136 template <typename POLY> static
00137 FT upper_bound(const POLY& p)
00138 {
00139 POLY tmp = p;
00140 for ( unsigned i = 1; i < p.size(); i += 2 )
00141 tmp[i] = -tmp[i];
00142 return -NISP<FT>::upper_bound(tmp);
00143 }
00144 };
00145
00146
00147 template < typename T >
00148 struct abs_max : public std::unary_function<T, void>
00149 {
00150 abs_max() : max(T(-1)) {}
00151 void operator() (const T& x)
00152 {
00153
00154 T temp = abs(x);
00155 if (temp > max) max = temp;
00156 }
00157 T max;
00158 };
00159
00161 template<class C> struct Cauchy
00162 {
00163
00185 template<class Poly> static
00186 C upper_bound(const Poly& p)
00187 {
00188
00189 typedef typename Poly::value_type RT;
00190 typedef typename texp::rationalof<RT>::T rational;
00191
00192
00193 abs_max<RT> M = std::for_each(p.begin(), p.end()-1, abs_max<RT>());
00194 RT an = abs(lcoeff(p));
00195
00196
00197 C res= C(M.max/an) + C(1);
00198
00199 return res;
00200 }
00201
00208 template<class Poly>
00209 C lower_bound(const Poly& f) const
00210 {
00211 using univariate::degree;
00212
00213 typedef C RT;
00214 long deg = degree( f);
00215 long l = 0;
00216
00217 for (int i = 1; i <= deg; ++i) {
00218 if ( sign( f[i]) * sign( f[0]) < 0 ) {
00219 ++l;
00220 }
00221 }
00222
00223 long ba0 = bit_size(f[0]) - 1;
00224 bool bound_set = false;
00225 long K = 0;
00226
00227 for (int i = 1; i <= deg; ++i) {
00228 if ( sign( f[i]) * sign( f[0]) < 0 ) {
00229 long bai = bit_size( RT( l * f[i])) - 1;
00230 long p = bai - ba0 - 1 ;
00231 long k = i;
00232 long q = p / k;
00233 long r = p % k;
00234
00235 long rq = 0;
00236 if (r <= k-2) {
00237 rq = q + 1;
00238 } else {
00239 rq = q + 2;
00240 }
00241
00242 if ( (bound_set == false) || (K < rq) ) {
00243 K = rq;
00244 bound_set = true;
00245 }
00246 }
00247 }
00248 if ( K < 0 ) {return pow2<RT>( abs( K) );}
00249
00250 return 0;
00251 }
00252
00253
00254 template<class Poly>
00255 long lower_power_2(const Poly& f) const
00256 {
00257 using univariate::degree;
00258
00259 typedef typename Poly::value_type RT;
00260
00261 long deg = degree( f);
00262 long l = 0;
00263
00264 for (int i = 1; i <= deg; ++i) {
00265 if ( sign( f[i]) * sign( f[0]) < 0 ) {
00266 ++l;
00267 }
00268 }
00269
00270 long ba0 = bit_size(f[0]) - 1;
00271 bool bound_set = false;
00272 long K = 0;
00273
00274 for (int i = 1; i <= deg; ++i) {
00275 if ( sign( f[i]) * sign( f[0]) < 0 ) {
00276 long bai = bit_size( RT( l * f[i])) - 1;
00277 long p = bai - ba0 - 1 ;
00278 long k = i;
00279 long q = p / k;
00280 long r = p % k;
00281
00282 long rq = 0;
00283 if (r <= k-2) {
00284 rq = q + 1;
00285 } else {
00286 rq = q + 2;
00287 }
00288
00289 if ( (bound_set == false) || (K < rq) ) {
00290 K = rq;
00291 bound_set = true;
00292 }
00293 }
00294 }
00295 if ( K < 0 ) { abs( K);}
00296
00297 return -1;
00298 }
00299
00300 };
00301
00302 template<>
00303 template<class Poly>
00304 double Cauchy<double>::upper_bound(const Poly& p)
00305 {
00306 typedef typename Poly::value_type coeff_t;
00307 numerics::rounding<double> rnd( numerics::rnd_up() );
00308
00309 coeff_t M=0;
00310 for(unsigned i=0;i< p.size(); i++) M = std::max(M, coeff_t(abs(p[i])));
00311
00312
00313 coeff_t an = coeff_t(abs(univariate::lcoeff(p)));
00314
00315
00316 double res=as<double>(coeff_t(M/an)) + 1;
00317
00318 return res;
00319 }
00320
00321
00322 template <typename FT, typename POLY>
00323 FT bound_root(const POLY& p, const Cauchy<FT>& m)
00324 {
00325 return Cauchy<FT>::upper_bound(p);
00326 }
00327
00328
00329 template < typename FT, typename POLY>
00330 FT max_bound(const POLY& p, const Cauchy<FT>& m)
00331 {
00332 return bound_root(p,m);
00333 }
00334
00335 template < typename FT, typename POLY>
00336 FT
00337 min_bound(const POLY& p, Cauchy<FT>)
00338 {
00339 using univariate::degree;
00340
00341 POLY f(p);
00342 univariate::reverse(f, degree(p));
00343 FT tmp = bound_root(f, Cauchy<FT>());
00344
00345 return FT(1)/tmp;
00346 }
00347
00348
00349
00350
00351
00357 template<class RT> struct HongBound
00358 {
00359 template < typename Poly > static
00360 RT lower_bound( const Poly& f)
00361 {
00362 using univariate::degree;
00363
00364 unsigned deg = degree(f);
00365
00366 long lB=0, gB=0;
00367 bool localBoundSet = false, globalBoundSet = false;
00368 long temp, q;
00369 int s = sign(f[0]);
00370
00371 for(int i= deg; i > 0; i--){
00372
00373 if(sign(f[i]) * s < 0){
00374 for(int k=i-1; k >= 0; k--){
00375 if(sign(f[k]) * s > 0){
00376 temp = bit_size( RT(f[i]) ) - bit_size( RT(f[k]) ) - 1;
00377 q = temp /(i-k);
00378 if(!localBoundSet || lB > q + 2){
00379 localBoundSet = true;
00380 lB = q+2;
00381 }
00382 }
00383 }
00384 localBoundSet = false;
00385 if(!globalBoundSet || gB < lB){
00386 globalBoundSet = true;
00387 gB = lB;
00388 }
00389 }
00390
00391 }
00392 if ( gB+1 < 0 ) return pow2<RT>( abs( gB+1) );
00393 return 0;
00394 }
00395 };
00396
00397
00406 template<class RT>
00407 struct AkritasBound
00408 {
00409
00410 template < typename Poly > static
00411 RT lower_bound( const Poly& f)
00412 {
00413 using univariate::degree;
00414
00415
00416 typedef std::pair<RT, int> Coeff_deg;
00417 Coeff_deg T1, T2;
00418
00419 unsigned deg=degree(f);
00420 int s=sign(f[0]);
00421 long B=0;
00422 bool boundSet=false;
00423 long temp,q;
00424 int posCounter=0, negCounter=0, nPosCounter=0;
00425
00426
00427
00428 std::queue< Coeff_deg > Neg;
00429
00430 std::stack< Coeff_deg > Pos;
00431
00432
00433 int l1, l2;
00434
00435 while(posCounter != int(deg+1)){
00436
00437
00438
00439 negCounter = -1;
00440
00441 Pos.push(Coeff_deg(RT(f[posCounter]), posCounter));
00442 for(unsigned i=posCounter + 1;i <= deg; i++){
00443 if(sign(f[i]) * s < 0){
00444 negCounter=i; break;
00445 }
00446 if(sign(f[i]) *s > 0){
00447
00448
00449 Pos.push(Coeff_deg(RT(f[i]), i));
00450 }
00451 }
00452 if(negCounter == -1){
00453
00454 if ( B < 0 )
00455 return pow2<RT>( abs(B) );
00456 else
00457 return 0;
00458 }
00459
00460 nPosCounter = deg+1;
00461 Neg.push(Coeff_deg(RT(f[negCounter]), negCounter));
00462 for(unsigned i=negCounter + 1;i <= deg; i++){
00463 if(sign(f[i]) * s > 0){
00464 nPosCounter=i; break;
00465 }
00466 if(sign(f[i]) *s < 0)
00467 Neg.push(Coeff_deg(RT(f[i]), i));
00468 }
00469
00470
00471
00472
00473
00474
00475
00476 l1 = Neg.size(); l2 = Pos.size();
00477 if(l2 >= l1){
00478
00479
00480
00481 for(int i=0; i < l1; i++){
00482 T1= Neg.front(); Neg.pop();
00483
00484 T2=Pos.top();Pos.pop();
00485
00486
00487
00488 temp = bit_size( T1.first ) - bit_size( T2.first ) - 1;
00489 q = temp/(T1.second - T2.second);
00490
00491
00492 if(!boundSet || B < q + 2){
00493 boundSet = true;
00494 B = q+2;
00495 }
00496 }
00497 }else{
00498
00499
00500
00501
00502
00503 T2= Pos.top();Pos.pop();
00504 for(int i=0; i <= l1-l2; i++){
00505 T1= Neg.front(); Neg.pop();
00506 temp = bit_size( T1.first ) - bit_size( T2.first ) + bit_size(RT(l1-l2+1)) - 1;
00507 q = temp/(T1.second-T2.second);
00508 if(!boundSet || B < q + 2){
00509 boundSet = true;
00510 B = q+2;
00511 }
00512 }
00513
00514 l1 = Neg.size();
00515 for(int i=0; i < l1; i++){
00516 T1= Neg.front(); Neg.pop();
00517
00518 Pos.pop();
00519 temp = bit_size( T1.first ) - bit_size( T2.first ) - 1;
00520 q = temp/(T1.second - T2.second);
00521 if(!boundSet || B < q + 2){
00522 boundSet = true;
00523 B = q+2;
00524 }
00525 }
00526 }
00527
00528 posCounter = nPosCounter; Neg.empty(); Pos.empty();
00529 }
00530
00531 if ( B < 0 ) return pow2<RT>( abs(B) );
00532 return 0;
00533 }
00534
00535
00536 template < typename Poly > static
00537 long lower_power_2( const Poly& f)
00538 {
00539 using univariate::degree;
00540
00541
00542 typedef std::pair<RT, int> Coeff_deg;
00543 Coeff_deg T1, T2;
00544
00545 unsigned deg=degree(f);
00546 int s=sign(f[0]);
00547 long B=0;
00548 bool boundSet=false;
00549 long temp,q;
00550 int posCounter=0, negCounter=0, nPosCounter=0;
00551
00552
00553
00554 std::queue< Coeff_deg > Neg;
00555
00556 std::stack< Coeff_deg > Pos;
00557
00558
00559 int l1, l2;
00560
00561 while(posCounter != int(deg+1)){
00562
00563
00564
00565 negCounter = -1;
00566
00567 Pos.push(Coeff_deg(RT(f[posCounter]), posCounter));
00568 for(unsigned i=posCounter + 1;i <= deg; i++){
00569 if(sign(f[i]) * s < 0){
00570 negCounter=i; break;
00571 }
00572 if(sign(f[i]) *s > 0){
00573
00574
00575 Pos.push(Coeff_deg(RT(f[i]), i));
00576 }
00577 }
00578 if(negCounter == -1){
00579
00580 if ( B < 0 ) return abs( B);
00581 else return -1;
00582 }
00583
00584 nPosCounter = deg+1;
00585 Neg.push(Coeff_deg(RT(f[negCounter]), negCounter));
00586 for(unsigned i=negCounter + 1;i <= deg; i++){
00587 if(sign(f[i]) * s > 0){
00588 nPosCounter=i; break;
00589 }
00590 if(sign(f[i]) *s < 0)
00591 Neg.push(Coeff_deg(RT(f[i]), i));
00592 }
00593
00594
00595
00596
00597
00598
00599
00600 l1 = Neg.size(); l2 = Pos.size();
00601 if(l2 >= l1){
00602
00603
00604
00605 for(int i=0; i < l1; i++){
00606 T1= Neg.front(); Neg.pop();
00607
00608 T2=Pos.top();Pos.pop();
00609
00610
00611
00612 temp = bit_size( T1.first ) - bit_size( T2.first ) - 1;
00613 q = temp/(T1.second - T2.second);
00614
00615
00616 if(!boundSet || B < q + 2){
00617 boundSet = true;
00618 B = q+2;
00619 }
00620 }
00621 }else{
00622
00623
00624
00625
00626
00627 T2= Pos.top();Pos.pop();
00628 for(int i=0; i <= l1-l2; i++){
00629 T1= Neg.front(); Neg.pop();
00630 temp = bit_size( T1.first ) - bit_size( T2.first ) + bit_size(RT(l1-l2+1)) - 1;
00631 q = temp/(T1.second-T2.second);
00632 if(!boundSet || B < q + 2){
00633 boundSet = true;
00634 B = q+2;
00635 }
00636 }
00637
00638 l1 = Neg.size();
00639 for(int i=0; i < l1; i++){
00640 T1= Neg.front(); Neg.pop();
00641
00642 Pos.pop();
00643 temp = bit_size( T1.first ) - bit_size( T2.first ) - 1;
00644 q = temp/(T1.second - T2.second);
00645 if(!boundSet || B < q + 2){
00646 boundSet = true;
00647 B = q+2;
00648 }
00649 }
00650 }
00651
00652 posCounter = nPosCounter; Neg.empty(); Pos.empty();
00653 }
00654
00655 if ( B < 0 ) return abs( B);
00656 else return -1;
00657
00658 }
00659 };
00660
00661
00662 }
00663
00664 #endif // realroot_UPOL_BOUND_H
00665