// // 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_FIELD_HPP #define CT_FIELD_HPP #include #include #include #include // #include #include #include #include namespace cbn { class skip_reduction { }; template struct ZqElement { using value_type = T; big_int data; explicit operator auto() const { return data; } // allow casting to big_int constexpr ZqElement() : data() {} //template && std::is_unsigned_v>> //explicit constexpr ZqElement(U x) : data{static_cast(x)} {} //template && std::is_signed_v>> //explicit constexpr ZqElement(U x) { //explicit constexpr ZqElement(long x) { constexpr ZqElement(long x) { auto neg = subtract_ignore_carry(to_big_int(std::integer_sequence{}), big_int{static_cast(-x)}); auto pos = big_int{static_cast(x)}; data = mod((x >= 0) ? pos : neg, std::integer_sequence()); } //constexpr ZqElement(int x) : data{ static_cast(x) } {} template constexpr ZqElement(std::integer_sequence) // reduce init mod q if necessary, where q = Modulus : data(big_int{Limbs...} < big_int{Modulus...} ? detail::to_length( big_int{Limbs...}) : mod(big_int{Limbs...}, std::integer_sequence())) { } template constexpr ZqElement(big_int init) // reduce init mod q if necessary, where q = Modulus : data(init < big_int{Modulus...} ? detail::to_length(init) : mod(init, std::integer_sequence())) { } constexpr ZqElement(big_int init, skip_reduction) : data(init) {} }; template auto Zq(std::integer_sequence) { return ZqElement{}; } template constexpr auto extract_modulus(ZqElement a) { return std::integer_sequence{}; } template constexpr auto &operator+=(ZqElement &a, ZqElement b) { a = ZqElement{mod_add(a.data, b.data, big_int{M...}), skip_reduction{}}; return a; } template constexpr auto operator+(ZqElement a, ZqElement b) { a += b; return a; } template constexpr auto &operator-=(ZqElement &a, ZqElement b) { a = ZqElement{mod_sub(a.data, b.data, big_int{M...}), skip_reduction{}}; return a; } template constexpr auto operator-(ZqElement a, ZqElement b) { a -= b; return a; } template constexpr auto operator-(ZqElement a) { big_int mod{M...}; return ZqElement{mod - a.data}; } template constexpr auto &operator*=(ZqElement &a, ZqElement b) { a = ZqElement{mod(mul(a.data, b.data), std::integer_sequence()), skip_reduction{}}; return a; } template constexpr auto operator*(ZqElement a, ZqElement b) { a *= b; return a; } template constexpr auto &operator/=(ZqElement &a, ZqElement b) { a = ZqElement{ mod(mul(a.data, mod_inv(b.data, big_int{M...})), std::integer_sequence()), skip_reduction{}}; return a; } template constexpr auto operator/(ZqElement a, ZqElement b) { a /= b; return a; } template std::ostream &operator<<(std::ostream &strm, const ZqElement &obj) { strm << obj.data; return strm; } template constexpr bool operator==(ZqElement a, ZqElement b) { return a.data == b.data; } template constexpr bool operator!=(ZqElement a, ZqElement b) { return !(a == b); } } // namespace cbn #endif