Пример #1
0
 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;
 }
Пример #2
0
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;
}
Пример #3
0
 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;
 }