ExecStatus Pow<A,B>::propagate(Space& home, const ModEventDelta&) { GECODE_ME_CHECK(x1.eq(home,pow(x0.domain(),m_n))); if ((m_n % 2) == 0) { if (x0.min() >= 0) GECODE_ME_CHECK(x0.eq(home,nth_root(x1.domain(),m_n))); else if (x0.max() <= 0) GECODE_ME_CHECK(x0.eq(home,-nth_root(x1.domain(),m_n))); else GECODE_ME_CHECK(x0.eq(home, hull( nth_root(x1.domain(),m_n), -nth_root(x1.domain(),m_n) ) )); } else GECODE_ME_CHECK(x0.eq(home,nth_root(x1.domain(),m_n))); return x0.assigned() ? home.ES_SUBSUMED(*this) : ES_FIX; }
mp_int<A,T> nth_root(const mp_int<A,T>& x, const mp_int<A,T>& n) { if (n.is_odd() && x.is_negative()) throw std::domain_error("nth_root: argument must be positive if n is even"); if (n.size() == 1) return nth_root(x, n[0]); // if x is negative fudge the sign but keep track const int neg = x.sign(); const_cast<mp_int<A,T>*>(&x)->set_sign(1); mp_int<A,T> t1, t2, t3; typedef typename mp_int<A,T>::size_type size_type; static const size_type digit_bits = mp_int<A,T>::digit_bits; const size_type result_precision = (x.precision() - 1) / n.template to_integral<size_type>() + 1; t2.grow_capacity((result_precision + digit_bits - 1) / digit_bits); t2.set_size ((result_precision + digit_bits - 1) / digit_bits); t2[t2.size()-1] = 0; t2.set_bits(0, result_precision + 1); do { t1 = t2; // t2 = t1 - ((t1**n - x) / (n * t1**(n-1))) // t3 = t1**(n-1) t3 = pow(t1, n-1); // numerator // t2 = t1**n t2 = t3 * t1; // t2 = t1**n - x t2 -= x; // denominator // t3 = t1**(n-1) * n t3 *= n; // t3 = (t1**n - x)/(n * t1**(n-1)) t3 = t2 / t3; t2 = t1 - t3; } while (t1 != t2); // result can be off by a few so check for (;;) { t2 = pow(t1, n); if (t2 > x) --t1; else break; } // reset the sign of x first const_cast<mp_int<A,T>*>(&x)->set_sign(neg); // set the sign of the result t1.set_sign(neg); return t1; }
ExecStatus NthRoot<A,B>::propagate(Space& home, const ModEventDelta&) { GECODE_ME_CHECK(x1.eq(home,nth_root(x0.domain(),m_n))); GECODE_ME_CHECK(x0.eq(home,pow(x1.domain(),m_n))); return x0.assigned() ? home.ES_SUBSUMED(*this) : ES_FIX; }