|
realroot_doc 0.1.1
|
#include <solver_uv_interval_newton.hpp>
Definition at line 64 of file solver_uv_interval_newton.hpp.
| 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.
| 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] |
Definition at line 70 of file solver_uv_interval_newton.hpp.
References mmx::lower(), and interval_newton< INT, CT >::width().
Referenced by interval_newton< INT, CT >::bisection_iteration(), and interval_newton< INT, CT >::newton_iteration().
{ return mmx::lower(x) + width(x)/BT(2); }
| 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] |
Definition at line 69 of file solver_uv_interval_newton.hpp.
References mmx::lower(), and mmx::upper().
Referenced by interval_newton< INT, CT >::median(), and interval_newton< INT, CT >::newton_iteration().
{ return mmx::upper(x) - mmx::lower(x); }