00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef _realroot_SOLVE_CONTFRAC_HPP_
00014 #define _realroot_SOLVE_CONTFRAC_HPP_
00015
00016 #include <realroot/Interval.hpp>
00017
00018 #include <realroot/upoldse.hpp>
00019 #include <realroot/upoldse_bound.hpp>
00020 #include <realroot/sign.hpp>
00021 #include <realroot/Seq.hpp>
00022
00023 #include <realroot/contfrac_intervaldata.hpp>
00024 #include <realroot/contfrac_lowerbound.hpp>
00025
00026
00027
00028 namespace mmx {
00029
00030
00031 namespace meta {
00032
00033 class Kioustelidis_bound_1
00034 {
00035
00036 public:
00039 Kioustelidis_bound_1() {}
00040
00041
00042 template <typename NT>
00043 long upper( const upoldse<NT>& p)
00044 {
00045 return foo( p.begin(), p.end());
00046
00047 }
00048
00049 template <typename NT>
00050 long lower( const upoldse<NT>& p)
00051 {
00052 return -foo( p.rbegin(), p.rend());
00053 }
00054
00055 template <class IT>
00056 long foo( IT first, IT last)
00057 {
00058 typedef typename std::iterator_traits<IT>::difference_type size_type;
00059
00060 size_type deg = std::distance( first, last);
00061 assert( deg > 0 );
00062
00063 int s = sign( *(last-1));
00064 long lan = bitsize( *(last-1));
00065
00066 bool first_time = true;
00067 long maxpow = 0;
00068
00069 int i = 1;
00070 for ( IT it = (last-2); it != first-1; --it, ++i) {
00071 if ( s * sign( *it) < 0) {
00072 long p = bitsize( abs( *it)) - lan - 1;
00073 long q = p / i;
00074 if ( first_time ) {
00075 first_time = false;
00076 maxpow = q + 2;
00077 } else {
00078 maxpow = std::max( maxpow, q + 2);
00079 }
00080 }
00081 }
00082 return maxpow;
00083 }
00084 };
00085
00086 template <typename T>
00087 void times_2_to_k( T& r, const T& a, long k = 1)
00088 {
00089 r = a << k;
00090
00091 }
00092
00093 template <typename T>
00094 unsigned long int bitsize( const T& a)
00095 {
00096 return std::log( static_cast<double>(a));
00097 }
00098
00099 #define __GMP_EXPR ::__gmp_expr<T, U>
00100 #define TMPL template <class T, class U> inline
00101
00102 TMPL
00103 mpz_class times_2_to_k( const __GMP_EXPR& a, long k = 1)
00104 {
00105 mpz_class b;
00106 mpz_mul_2exp( b.get_mpz_t(), a.get_mpz_t(), k );
00107 return b;
00108 }
00109
00110 TMPL
00111 void times_2_to_k( __GMP_EXPR& r, const __GMP_EXPR& a, long k = 1)
00112 {
00113 mpz_mul_2exp( r.get_mpz_t(), a.get_mpz_t(), k );
00114 }
00115
00116 TMPL
00117 unsigned long int bitsize( const __GMP_EXPR& a)
00118 {
00119 return mpz_sizeinbase( mpz_class( a).get_mpz_t(), 2 );
00120 }
00121
00122 #undef TMPL
00123 #undef __GMP_EXPR
00124
00125
00126
00127 template < typename RT, typename Poly > inline
00128 void do_scale( IntervalData<RT,Poly>& ID, long k)
00129 {
00130 assert( k > 0 );
00131
00132 for (int i = 0; i <= degree( ID.p); ++i) {
00133 times_2_to_k( ID.p[i], ID.p[i], k*i);
00134 }
00135 times_2_to_k( ID.a, ID.a, k);
00136 times_2_to_k( ID.c, ID.c, k);
00137 }
00138
00139 }
00140
00141
00142 template<class C> typename meta::rationalof<C>::T to_rational(const C& a, const C& b)
00143 {
00144 typedef typename meta::rationalof<C>::T rational;
00145 return (rational(a)/b);
00146 }
00147
00149 template < class NT , class LowerBound = AkritasBound<NT> >
00150 struct ContFrac_t
00151 {
00152 typedef NT RT;
00153 typedef typename meta::rationalof<RT>::T FT;
00154 typedef Interval<FT> FIT;
00155 typedef Interval<FT> root_t;
00156 typedef upoldse<NT> Poly;
00157 typedef LowerBound bound;
00158 typedef ContFrac_t self_t;
00159 };
00160
00161
00162 template < class NT, class LB > inline
00163 Seq< typename ContFrac<NT,LB>::root_t >
00164 solve( const typename ContFrac<NT>::Poly& f, ContFrac<NT,LB>)
00165 {
00166 typedef ContFrac<NT,LB> K;
00167 typedef typename K::root_t root_t;
00168
00169 Seq<root_t> sol;
00170
00171 solve_contfrac(f, std::back_inserter(sol.rep()), K());
00172
00173
00174 return sol;
00175 }
00176
00177
00178 template < typename K >
00179 void
00180 CF_positive( const typename K::Poly& f, Seq< typename K::FIT>& RL, bool posneg, K)
00181 {
00182
00183 typedef typename K::RT RT;
00184 typedef typename K::FT FT;
00185 typedef typename K::FT rational_t;
00186 typedef typename K::FIT FIT;
00187 typedef typename K::Poly Poly;
00188
00189 typedef IntervalData< RT, Poly> IntervalData;
00190
00191 meta ::Kioustelidis_bound_1 bound;
00192
00193
00194 int iters = 0;
00195 const RT One( 1);
00196 FT Zero(0);
00197
00198
00199
00200 FT B = meta::times_2_to_k( RT( 1), bound.upper( f));
00201
00202
00203 unsigned long s = sign_variation(f);
00204
00205 if ( s == 0 ) { return; }
00206 if ( s == 1 ) {
00207
00208 if ( posneg )
00209 {
00210
00211 RL.push_back( to_FIT( FT(0), B));
00212 }
00213 else RL.push_back( to_FIT( FT(0), FT(-B)));
00214 return;
00215 }
00216 Poly X(2, AsSize()); X[1] = RT(1); X[0]=RT(0);
00217
00218 std::stack< IntervalData > S;
00219 if ( posneg) S.push( IntervalData( 1, 0, 0, 1, f, s));
00220 else S.push( IntervalData( -1, 0, 0, 1, f, s));
00221
00222 while ( !S.empty() ) {
00223 ++iters;
00224 IntervalData ID = S.top();
00225 S.pop();
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266 long k = AkritasBound<RT>().lower_power_2( ID.p);
00267
00268
00269
00270 if (k > 0) {
00271 meta::do_scale( ID, k);
00272 }
00273
00274
00275
00276
00277
00278 if ( k >= 0 ) {
00279 shift_by_1(ID);
00280
00281
00282 if ( ID.p[0] == RT(0)) {
00283 RL.push_back( to_FIT( to_rational( ID.b, ID.d), to_rational( ID.b, ID.d )));
00284 ID.p /= X;
00285 }
00286 ID.s = sign_variation( ID.p);
00287 if ( ID.s == 0 ) { continue; }
00288 if ( ID.s == 1 ) {
00289
00290 RL.push_back( to_FIT<K>( ID.a, ID.b, ID.c, ID.d, B));
00291 continue;
00292 }
00293 }
00294
00295
00296 IntervalData I1;
00297 shift_by_1( I1, ID);
00298
00299 unsigned long r = 0;
00300
00301 if (I1.p[0] == RT(0)) {
00302
00303 RL.push_back( to_FIT( to_rational( I1.b, I1.d), to_rational(I1.b, I1.d) ));
00304 I1.p /= X;
00305 r = 1;
00306 }
00307 I1.s = sign_variation( I1.p);
00308
00309 IntervalData I2;
00310
00311 I2.s = ID.s - I1.s - r;
00312
00313 I2.a = ID.b;
00314 I2.b = ID.a + ID.b;
00315 I2.c = ID.d;
00316 I2.d = ID.c + ID.d;
00317
00318
00319 if ( I2.s > 1 ) {
00320
00321 reverse( I2.p, ID.p);
00322 shift_by_1( I2.p);
00323
00324 if ( I2.p[0] == 0) {
00325 I2.p /= X;
00326 }
00327 I2.s = sign_variation( I2.p);
00328 }
00329
00330
00331 if ( I1.s < I2.s ) {
00332 std::swap( I1, I2);
00333 }
00334
00335
00336 if ( I1.s == 1 ) {
00337
00338 RL.push_back( to_FIT<K>( I1.a, I1.b, I1.c, I1.d, B));
00339 } else if ( I1.s > 1) {
00340 S.push( IntervalData( I1.a, I1.b, I1.c, I1.d, I1.p, I1.s));
00341 }
00342
00343
00344 if ( I2.s == 1 ) {
00345
00346 RL.push_back( to_FIT<K>( I2.a, I2.b, I2.c, I2.d, B));
00347 } else if ( I2.s > 1) {
00348 S.push( IntervalData( I2.a, I2.b, I2.c, I2.d, I2.p, I2.s));
00349 }
00350 }
00351
00352 return;
00353 }
00354
00355
00356
00357
00358 template < typename K >
00359 void
00360 MCF_positive( const typename K::Poly& f, Seq< typename K::root_t>& RL, bool posneg, K)
00361 {
00362
00363 typedef typename K::RT RT;
00364 typedef typename K::FT FT;
00365 typedef typename K::root_t FIT;
00366 typedef typename K::Poly Poly;
00367
00368 typedef IntervalData< RT, Poly> IntervalData;
00369
00370 int iters = 0;
00371
00372
00373 FT B = bound_root( f, Cauchy<FT>());
00374
00375 unsigned long s = sign_variation( f);
00376 if ( s == 0 ) { return; }
00377 if ( s == 1 ) {
00378 if ( posneg ) RL.push_back( to_FIT( FT(0), B));
00379 else RL.push_back( to_FIT( FT(0), FT(-B)));
00380 return;
00381 }
00382
00383 Poly X(2, AsSize()); X[1] = RT(1);
00384
00385 std::stack< IntervalData > S;
00386 if ( posneg) S.push( IntervalData( 1, 0, 0, 1, f, s));
00387 else S.push( IntervalData( -1, 0, 0, 1, f, s));
00388
00389 IntervalData ID, I1, I2;
00390
00391
00392 RT lowerBound;
00393 FT midpoint;
00394
00395 FT temp;
00396 unsigned long mult = 0;
00397
00398 while ( !S.empty() ) {
00399 ++iters;
00400 ID = S.top();
00401 S.pop();
00402
00403
00404
00405 lowerBound = CauchyMinimumBound( ID.p);
00406 std::cout << "lower bound is "<< lowerBound << std::endl;
00407
00408 if(ID.c == 0){
00409 midpoint = FT(ID.d * B - ID.b*sign(ID.a), 2* abs(ID.a));
00410
00411 }else if (ID.d > ID.c ){
00412 midpoint = FT(ID.d, ID.c);
00413 }else{}
00414
00415 if(midpoint < 1) midpoint = 1;
00416 std::cout << "Midpoint = " << midpoint << std::endl;
00417
00418 if(lowerBound >= midpoint){
00419 if ( lowerBound > 1 ) {
00420 UPOLDSE::scale( ID.p, ID.p, lowerBound);
00421 ID.a *= lowerBound;
00422 ID.c *= lowerBound;
00423 lowerBound = 1;
00424 }
00425
00426 if ( lowerBound == 1 ) {
00427 shift_by_1( ID.p, ID.p);
00428 ID.b += ID.a;
00429 ID.d += ID.c;
00430
00431 if ( ID.p[0] == RT(0)) {
00432 RL.push_back( to_FIT( FT( ID.b, ID.d), FT( ID.b, ID.d)));
00433 ID.p /= X;
00434 }
00435 ID.s = sign_variation( ID.p);
00436 if ( ID.s == 0 ) { continue; }
00437 if ( ID.s == 1 ) {
00438 RL.push_back( to_FIT<K>( ID.a, ID.b, ID.c, ID.d, B));
00439 continue;
00440 }
00441 }
00442
00443 shift_by_1( I1.p, ID.p);
00444 I1.a = ID.a;
00445 I1.b = ID.a + ID.b;
00446 I1.c = ID.c;
00447 I1.d = ID.c + ID.d;
00448
00449 if (I1.p[0] == RT(0)) {
00450 RL.push_back( to_FIT( FT( I1.b, I1.d), FT( I1.b, I1.d)));
00451 I1.p /= X;
00452 mult = 1;
00453 }
00454 I1.s = sign_variation( I1.p);
00455
00456 I2.s = ID.s - I1.s - mult;
00457 I2.a = ID.b;
00458 I2.b = ID.a + ID.b;
00459 I2.c = ID.d;
00460 I2.d = ID.c + ID.d;
00461
00462 if ( I2.s > 1 ) {
00463
00464 reverse( I2.p, ID.p);
00465 shift_by_1( I2.p);
00466 }
00467 }else{
00468
00469
00470 UPOLDSE::shift(I1.p, ID.p, RT(midpoint));
00471 I1.a = ID.a;
00472 I1.b = ID.a * RT(midpoint) + ID.b;
00473 I1.c = ID.c;
00474 I1.d = ID.c * RT(midpoint) + ID.d;
00475 mult = 0;
00476
00477
00478 if (I1.p[0] == RT(0)) {
00479 RL.push_back( to_FIT( FT( I1.b, I1.d), FT( I1.b, I1.d)));
00480 I1.p /= X;
00481 mult = 1;
00482 }
00483 I1.s = sign_variation( I1.p);
00484
00485 I2.a = ID.b;
00486 I2.b = ID.b + ID.a * RT(midpoint);
00487 I2.c = ID.d;
00488 I2.d = ID.d + ID.c * RT(midpoint);
00489 I2.s = ID.s - I1.s - mult;
00490
00491
00492
00493
00494 if( I2.s > 1){
00495
00496 UPOLDSE::scale( I2.p, ID.p, RT(midpoint));
00497
00498
00499 reverse(I2.p);
00500
00501 shift_by_1(I2.p);
00502
00503 }
00504 }
00505
00506 if(I2.s > 1){
00507 if ( I2.p[0] == 0) {
00508 I2.p /= X;
00509 }
00510 I2.s = sign_variation( I2.p);
00511 }
00512
00513
00514 if ( I1.s < I2.s ) {
00515 std::swap( I1, I2);
00516 }
00517
00518 if ( I1.s == 1 ) {
00519 RL.push_back( to_FIT<K>( I1.a, I1.b, I1.c, I1.d, B));
00520 } else if ( I1.s > 1) {
00521 S.push( IntervalData( I1.a, I1.b, I1.c, I1.d, I1.p, I1.s));
00522 }
00523
00524 if ( I2.s == 1 ) {
00525 RL.push_back( to_FIT<K>( I2.a, I2.b, I2.c, I2.d, B));
00526 } else if ( I2.s > 1) {
00527 S.push( IntervalData( I2.a, I2.b, I2.c, I2.d, I2.p, I2.s));
00528 }
00529 }
00530 std::cout << "---------------- iters: " << iters << std::endl;
00531 return;
00532 }
00533
00534
00535
00536 template < typename OutputIterator, typename K >
00537 OutputIterator
00538 CF_solve( const typename K::Poly& f, OutputIterator sol, int mult, K)
00539 {
00540 typedef typename K::Poly Poly;
00541 typedef typename K::FIT FIT;
00542
00543 Seq < FIT > isolating_intervals;
00544
00545
00546 int idx;
00547 for (idx = 0; idx <= degree( f); ++idx) {
00548 if ( f[idx] != 0 ) break;
00549 }
00550
00551 Poly p;
00552 if ( idx == 0 ) { p = f; }
00553 else {
00554 p.resize( degree(f) + 1 - idx);
00555 for (int j = idx; j <= degree( f); ++j)
00556 p[j-idx] = f[j];
00557 }
00558
00559
00560
00561 for (int i = 1; i <= degree(p); i+=2) p[i] *= -1;
00562
00563 CF_positive( p, isolating_intervals, false, K());
00564
00565
00566
00567
00568 if (idx != 0) isolating_intervals.push_back( FIT( 0, 0));
00569
00570
00571 for (int i = 1; i <= degree(p); i+=2) p[i] *= -1;
00572
00573 CF_positive( p, isolating_intervals, true, K());
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598 for (unsigned i = 0 ; i < isolating_intervals.size(); ++i) {*sol++ = isolating_intervals[i];}
00599 return sol;
00600 }
00601
00602
00603
00604
00605
00606 template < typename K,
00607 typename OutputIterator > inline
00608 OutputIterator
00609 solve_contfrac( const typename K::Poly& h, OutputIterator sol, K)
00610 {
00611 CF_solve( h, sol, 1, K());
00612 return sol;
00613 }
00614
00615
00616
00617 }
00618
00619
00620 #endif // _realroot_SOLVE_CONTFRAC_HPP_
00621