inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type eval_lsb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a) { using default_ops::eval_get_sign; if(eval_get_sign(a) == 0) { BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); } if(a.sign()) { BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); } // // Find the index of the least significant limb that is non-zero: // unsigned index = 0; while(!a.limbs()[index] && (index < a.size())) ++index; // // Find the index of the least significant bit within that limb: // unsigned result = boost::multiprecision::detail::find_lsb(a.limbs()[index]); return result + index * cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits; }
inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type eval_gcd( cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a, limb_type v) { using default_ops::eval_lsb; using default_ops::eval_is_zero; using default_ops::eval_get_sign; int shift; cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> u(a); int s = eval_get_sign(u); /* GCD(0,x) := x */ if(s < 0) { u.negate(); } else if(s == 0) { result = v; return; } if(v == 0) { result = u; return; } /* Let shift := lg K, where K is the greatest power of 2 dividing both u and v. */ unsigned us = eval_lsb(u); unsigned vs = find_lsb(v, mpl::int_<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits>()); shift = (std::min)(us, vs); eval_right_shift(u, us); if(vs) v >>= vs; do { /* Now u and v are both odd, so diff(u, v) is even. Let u = min(u, v), v = diff(u, v)/2. */ if(u.size() == 1) { v = integer_gcd_reduce(*u.limbs(), v); break; } eval_subtract(u, v); us = eval_lsb(u); eval_right_shift(u, us); } while(true); result = v; eval_left_shift(result, shift); }
inline typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a) { using default_ops::eval_get_sign; if(eval_get_sign(a) == 0) { BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); } if(a.sign()) { BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); } return eval_msb_imp(a); }
void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_integer>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/) { using default_ops::eval_get_sign; using default_ops::eval_bitwise_and; using default_ops::eval_convert_to; using default_ops::eval_right_shift; using default_ops::eval_left_shift; using default_ops::eval_bitwise_or; using default_ops::eval_is_zero; // smallest unsigned type handled natively by "From" is likely to be it's limb_type: typedef typename canonical<unsigned char, From>::type limb_type; // get the corresponding type that we can assign to "To": typedef typename canonical<limb_type, To>::type to_type; From t(from); bool is_neg = eval_get_sign(t) < 0; if(is_neg) t.negate(); // Pick off the first limb: limb_type limb; limb_type mask = static_cast<limb_type>(~static_cast<limb_type>(0)); From fl; eval_bitwise_and(fl, t, mask); eval_convert_to(&limb, fl); to = static_cast<to_type>(limb); eval_right_shift(t, std::numeric_limits<limb_type>::digits); // // Then keep picking off more limbs until "t" is zero: // To l; unsigned shift = std::numeric_limits<limb_type>::digits; while(!eval_is_zero(t)) { eval_bitwise_and(fl, t, mask); eval_convert_to(&limb, fl); l = static_cast<to_type>(limb); eval_right_shift(t, std::numeric_limits<limb_type>::digits); eval_left_shift(l, shift); eval_bitwise_or(to, l); shift += std::numeric_limits<limb_type>::digits; } // // Finish off by setting the sign: // if(is_neg) to.negate(); }
inline typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a) { using default_ops::eval_get_sign; if(eval_get_sign(a) == 0) { BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); } if(a.sign()) { BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); } // // Find the index of the least significant bit within that limb: // return boost::multiprecision::detail::find_msb(*a.limbs()); }
void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_floating_point>& /*to_type*/, const mpl::int_<number_kind_floating_point>& /*from_type*/) { #ifdef BOOST_MSVC #pragma warning(push) #pragma warning(disable:4127) #endif // // The code here only works when the radix of "From" is 2, we could try shifting by other // radixes but it would complicate things.... use a string conversion when the radix is other // than 2: // if(std::numeric_limits<number<From> >::radix != 2) { to = from.str(0, std::ios_base::fmtflags()).c_str(); return; } typedef typename canonical<unsigned char, To>::type ui_type; using default_ops::eval_fpclassify; using default_ops::eval_add; using default_ops::eval_subtract; using default_ops::eval_convert_to; // // First classify the input, then handle the special cases: // int c = eval_fpclassify(from); if(c == FP_ZERO) { to = ui_type(0); return; } else if(c == FP_NAN) { to = "nan"; return; } else if(c == FP_INFINITE) { to = "inf"; if(eval_get_sign(from) < 0) to.negate(); return; } typename From::exponent_type e; From f, term; to = ui_type(0); eval_frexp(f, from, &e); static const int shift = std::numeric_limits<boost::intmax_t>::digits - 1; while(!eval_is_zero(f)) { // extract int sized bits from f: eval_ldexp(f, f, shift); eval_floor(term, f); e -= shift; eval_ldexp(to, to, shift); typename boost::multiprecision::detail::canonical<boost::intmax_t, To>::type ll; eval_convert_to(&ll, term); eval_add(to, ll); eval_subtract(f, term); } typedef typename To::exponent_type to_exponent; if((e > (std::numeric_limits<to_exponent>::max)()) || (e < (std::numeric_limits<to_exponent>::min)())) { to = "inf"; if(eval_get_sign(from) < 0) to.negate(); return; } eval_ldexp(to, to, static_cast<to_exponent>(e)); #ifdef BOOST_MSVC #pragma warning(pop) #endif }
inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type eval_gcd( cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b) { using default_ops::eval_lsb; using default_ops::eval_is_zero; using default_ops::eval_get_sign; if(a.size() == 1) { eval_gcd(result, b, *a.limbs()); return; } if(b.size() == 1) { eval_gcd(result, a, *b.limbs()); return; } int shift; cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> u(a), v(b); int s = eval_get_sign(u); /* GCD(0,x) := x */ if(s < 0) { u.negate(); } else if(s == 0) { result = v; return; } s = eval_get_sign(v); if(s < 0) { v.negate(); } else if(s == 0) { result = u; return; } /* Let shift := lg K, where K is the greatest power of 2 dividing both u and v. */ unsigned us = eval_lsb(u); unsigned vs = eval_lsb(v); shift = (std::min)(us, vs); eval_right_shift(u, us); eval_right_shift(v, vs); do { /* Now u and v are both odd, so diff(u, v) is even. Let u = min(u, v), v = diff(u, v)/2. */ s = u.compare(v); if(s > 0) u.swap(v); if(s == 0) break; if(v.size() <= 2) { if(v.size() == 1) u = integer_gcd_reduce(*v.limbs(), *u.limbs()); else { double_limb_type i, j; i = v.limbs()[0] | (static_cast<double_limb_type>(v.limbs()[1]) << sizeof(limb_type) * CHAR_BIT); j = (u.size() == 1) ? *u.limbs() : u.limbs()[0] | (static_cast<double_limb_type>(u.limbs()[1]) << sizeof(limb_type) * CHAR_BIT); u = integer_gcd_reduce(i, j); } break; } eval_subtract(v, u); vs = eval_lsb(v); eval_right_shift(v, vs); } while(true); result = u; eval_left_shift(result, shift); }
inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type eval_gcd( cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a, limb_type v) { using default_ops::eval_lsb; using default_ops::eval_is_zero; using default_ops::eval_get_sign; int shift; cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> u(a); int s = eval_get_sign(u); /* GCD(0,x) := x */ if(s < 0) { u.negate(); } else if(s == 0) { result = v; return; } if(v == 0) { result = u; return; } /* Let shift := lg K, where K is the greatest power of 2 dividing both u and v. */ unsigned us = eval_lsb(u); unsigned vs = boost::multiprecision::detail::find_lsb(v); shift = (std::min)(us, vs); eval_right_shift(u, us); if(vs) v >>= vs; do { /* Now u and v are both odd, so diff(u, v) is even. Let u = min(u, v), v = diff(u, v)/2. */ if(u.size() <= 2) { if(u.size() == 1) v = integer_gcd_reduce(*u.limbs(), v); else { double_limb_type i; i = u.limbs()[0] | (static_cast<double_limb_type>(u.limbs()[1]) << sizeof(limb_type) * CHAR_BIT); v = static_cast<limb_type>(integer_gcd_reduce(i, static_cast<double_limb_type>(v))); } break; } eval_subtract(u, v); us = eval_lsb(u); eval_right_shift(u, us); } while(true); result = v; eval_left_shift(result, shift); }