// // This file is part of // // CTBignum // // C++ Library for Compile-Time and Run-Time Multi-Precision and Modular Arithmetic // // // This file is distributed under the Apache License, Version 2.0. See the LICENSE // file for details. #ifndef CT_GCD_HPP #define CT_GCD_HPP #include #include #include #include #include #include #include namespace cbn { namespace detail { template constexpr auto ext_gcd_impl(std::integer_sequence, std::integer_sequence, std::integer_sequence) { using detail::pad; using detail::first; using detail::take; using detail::skip; using detail::join; constexpr auto a = big_int{A...}; constexpr auto b = big_int{B...}; constexpr auto dummy = big_int{}; constexpr bool a_equals_zero = std::is_same, std::integer_sequence>::value; if constexpr(a_equals_zero) return join( b, join(big_int{0}, big_int{1})); else { constexpr auto qr = div(b, a); constexpr auto rem = qr.remainder; constexpr auto arg1 = pad(rem); constexpr auto triple = ext_gcd_impl(std::integer_sequence(), std::integer_sequence(), std::integer_sequence()); constexpr auto x = first(triple); constexpr auto y = take(triple); constexpr auto z = skip<2 * N>(triple); constexpr auto qy = partial_mul(qr.quotient, y); return join(join(x, subtract_ignore_carry(z, qy)), y); } } } template constexpr auto ext_gcd(std::integer_sequence, std::integer_sequence) { constexpr std::size_t N = std::max(sizeof...(A), sizeof...(B)); return detail::ext_gcd_impl(std::integer_sequence{}, std::integer_sequence{}, std::make_integer_sequence{}); } template constexpr auto mod_inv(std::integer_sequence, std::integer_sequence) { constexpr auto triple = ext_gcd(std::integer_sequence{}, std::integer_sequence{}); constexpr auto N = std::max(sizeof...(X), sizeof...(Modulus)); if (triple[0] != 1) { throw std::runtime_error("modular inverse does not exist"); } else { using namespace detail; constexpr auto mod_inverse = take(triple); constexpr auto L = tight_length(mod_inverse); return first(mod_inverse); } } } #endif /* template