realroot_doc 0.1.1
interval_newton< INT, CT > Struct Template Reference

#include <solver_uv_interval_newton.hpp>

List of all members.

Public Types

Static Public Member Functions


Detailed Description

template<class INT, class CT>
struct mmx::interval_newton< INT, CT >

Definition at line 64 of file solver_uv_interval_newton.hpp.


Member Typedef Documentation

typedef INT::boundary_type BT

Definition at line 67 of file solver_uv_interval_newton.hpp.

typedef ring<CT, MonomialTensor>::Polynomial polynomial

Definition at line 66 of file solver_uv_interval_newton.hpp.


Member Function Documentation

static INT bisection_iteration ( const polynomial p,
const INT  approx,
int &  status_ 
) [inline, static]

Definition at line 73 of file solver_uv_interval_newton.hpp.

References approx(), mmx::lower(), interval_newton< INT, CT >::median(), mmx::sign(), and mmx::upper().

Referenced by interval_newton< INT, CT >::newton_iteration().

      {
          BT x = median(approx);
          INT lval, rval, mval;
          lval = p(INT(mmx::lower(approx)));
          rval = p(INT(mmx::upper(approx)));
          mval = p(INT(x));
          //    std::cerr << lval << ' ' << rval << ' ' << mval << ' ' << x << std::endl;
          //    assert( mmx::sign(lval)*mmx::sign(rval) <= 0 );
                   
          status_ = 0;
          if (mval == 0) return INT(x);
          if (lval == 0) return INT(mmx::lower(approx)); 
          if (rval == 0) return INT(mmx::upper(approx));
                   
          if (mmx::sign(lval) == 0 || mmx::sign(rval) == 0) {
              status_ = -3; return approx;
          }

          if (mmx::sign(lval) == mmx::sign(rval)) {
              status_ = -1; return approx;
          }
          
          if (mmx::sign(mval) == 0) return approx;
          
          if (mmx::sign(lval) == mmx::sign(mval)) return INT(x,mmx::upper(approx));
          return INT(mmx::lower(approx), x);
      }
static BT median ( const INT &  x) [inline, static]
static INT newton_iteration ( const polynomial p,
const polynomial dp,
INT  approx,
BT  delta_,
int &  status_ 
) [inline, static]

Definition at line 112 of file solver_uv_interval_newton.hpp.

References approx(), assert, interval_newton< INT, CT >::bisection_iteration(), mmx::intersect(), mmx::lower(), interval_newton< INT, CT >::median(), mmx::sign(), mmx::upper(), and interval_newton< INT, CT >::width().

      { 
          INT slope, testapprox, newapprox, ver;
          BT oldw = width(approx);
          BT neww;
          int z;
          
#ifdef INEWTONDEBUG
          int i = 0;
#endif
          
          INT lval, rval;
          
          lval = p(INT(mmx::lower(approx)));
          rval = p(INT(mmx::upper(approx)));
#ifdef INEWTONDEBUG
          std::cerr << "approx = " << approx << " lval = " << lval << " rval = " << rval << std::endl;
#endif
          if (lval == 0) { status_ = 0; return INT(mmx::lower(approx)); }
          if (rval == 0) { status_ = 0; return INT(mmx::upper(approx)); }
          if (mmx::sign(lval) == 0 || mmx::sign(rval) == 0) {
              status_ = -3; return approx;
          }
          
          status_ = 0;
          slope = dp(approx);
          
#ifdef INEWTONDEBUG
          std::cerr << "slope = " << slope << width(slope) << std::endl;
#endif

          z = mmx::sign(slope);
          if (mmx::sign(lval) == mmx::sign(rval)) {
              if (z == 0) status_ = -1; else status_ = -2;
              return approx;
          }

#ifdef INEWTONDEBUG
          std::cerr << "solving " << p << std::endl;
#endif

          /* INTERVAL NEWTON MAIN LOOP */
          while (1) {
              // should we always do simple bisection with intervals of length >= 1 ?
              // if (oldw >= 1 || z == 0) {
              
              // slope contains zero
              if (z == 0) {
                  approx = bisection_iteration(p, approx, status_);
                  neww = width(approx);
#ifdef INEWTONDEBUG
                  i++;
                  std::cerr << '(' << i << ") bisect: " << approx << ' ' << neww << std::endl;
#endif
                  if (status_ < 0) return approx;
                  if (neww < delta_) break;
                  assert(neww <= oldw);
                  if (neww == oldw) break;
                  oldw = neww;
                  
              } else {
              // slope doesn't contain zero

                  BT x = median(approx);
                  if (x == mmx::lower(approx) || x == mmx::upper(approx)) break;
#ifdef INEWTONDEBUG
                  std::cerr << "mid = " << x << " mid_INT = " << INT(x) << std::endl;
                  std::cerr << "p(x) = " << p(INT(x)) << std::endl;
                  std::cerr << "p'(approx) = " << dp(approx) << std::endl;
                  std::cerr << "p/p' = " << INT(p(INT(x))/dp(approx)) << std::endl;
#endif
                  testapprox = INT(x) - INT(p(INT(x))/dp(approx)); // Newton approximation

#ifdef INEWTONDEBUG
                  i++;
#endif
                  if (mmx::intersect(newapprox, testapprox, approx)) {
#ifdef INEWTONDEBUG
                      std::cerr <<"new =" << newapprox << " test = " << testapprox << " old = " << approx << std::endl;
#endif
                      neww = width(newapprox);
                      
                      // new approximation SHOULD contain the root
                      // if you want to verify, use the debugging code below
#ifdef INEWTONDEBUG
                      INT ver = p(newapprox);
                      if (ver != INT(0)) {
                          assert (mmx::sign(ver) == 0);
                      }
                      
                      std::cerr << '(' << i << ") Newton: " << newapprox << ' ' << neww << std::endl;
#endif
                      //if (Float(2)*neww >= oldw) break;
                      if (neww >= oldw) break;
                      approx = newapprox;
                      if (neww < delta_) break;
                      oldw = neww;
                  } else {
                      // no convergence
                      status_ = -4;
                      return approx;
                  }
              }
              slope = dp(approx);
#ifdef INEWTONDEBUG
              std::cerr << "slope = " << slope << width(slope) << std::endl;
#endif
              z = mmx::sign(slope);
          }
          if (mmx::sign(dp(approx)) != 0) status_ = 1;
#ifdef INEWTONDEBUG
          std::cerr << "iters = " << i << std::endl;
#endif
          return approx;
      }
static bool singleton ( const INT &  x) [inline, static]

Definition at line 71 of file solver_uv_interval_newton.hpp.

References mmx::lower(), and mmx::upper().

{ return mmx::lower(x) == mmx::upper(x); }
static BT width ( const INT &  x) [inline, static]

The documentation for this struct was generated from the following file: