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 unsigned eval_lsb(const logged_adaptor<Backend>& arg) { using default_ops::eval_lsb; log_prefix_event(arg.value(), "least-significant-bit"); unsigned r = eval_lsb(arg.value()); log_postfix_event(arg.value(), r, "least-significant-bit"); return r; }
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); }
inline unsigned eval_lsb(const debug_adaptor<Backend>& arg) { using default_ops::eval_lsb; return eval_lsb(arg.value()); }