zmodn

A simple C++ library for integers modulo N
git clone https://git.tronto.net/zmodn
Download | Log | Files | Refs | README

commit 7e705a3342bc36f9f02b4e8e0050bc5842a62f9b
parent b0d8a2f5f5718ba3fea628cad7bcbbc76c6a140c
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Sat, 21 Dec 2024 17:22:09 +0100

Make N's type generic for possible use with bigint

Diffstat:
Mtest | 6+++---
Mzmodn.h | 44+++++++++++++++++++++++---------------------
2 files changed, 26 insertions(+), 24 deletions(-)

diff --git a/test b/test @@ -34,7 +34,7 @@ public: .name = "Constructor 2 mod 3", .f = []() { Zmod<3> two = Zmod<3>(2); - assert_equal(two.toint64(), INT64_C(2)); + assert_equal(two.toint(), INT64_C(2)); } }, { @@ -121,7 +121,7 @@ public: Zmod<10> n = 8; Zmod<10> m = 9; auto prod = m * n; - assert_equal(prod.toint64(), 2); + assert_equal(prod.toint(), 2); } }, { @@ -130,7 +130,7 @@ public: Zmod<10> n = 8; Zmod<10> m = 9; n *= m; - assert_equal(n.toint64(), 2); + assert_equal(n.toint(), 2); } }, }; diff --git a/zmodn.h b/zmodn.h @@ -5,27 +5,35 @@ #include <iostream> #include <optional> #include <tuple> +#include <type_traits> -std::tuple<int64_t, int64_t, int64_t> extended_gcd(int64_t, int64_t); +template<typename INT> +requires std::is_integral_v<INT> +std::tuple<INT, INT, INT> extended_gcd(INT a, INT b) { + if (b == 0) return {a, 1, 0}; + auto [g, x, y] = extended_gcd(b, a%b); + return {g, y, x - y*(a/b)}; +} -template<int64_t N> requires(N > 1) +template<auto N> +requires(N > 1) && std::is_integral_v<decltype(N)> class Zmod { public: - Zmod(int64_t z) : int64{(z%N + N) % N} {} - int64_t toint64() const { return int64; } + Zmod(decltype(N) z) : value{(z%N + N) % N} {} + decltype(N) toint() const { return value; } - Zmod operator+(const Zmod& z) const { return int64 + z.int64; } - Zmod operator-(const Zmod& z) const { return int64 - z.int64; } - Zmod operator*(const Zmod& z) const { return int64 * z.int64; } - Zmod operator+=(const Zmod& z) { return (*this) = int64 + z.int64; } - Zmod operator-=(const Zmod& z) { return (*this) = int64 - z.int64; } - Zmod operator*=(const Zmod& z) { return (*this) = int64 * z.int64; } + Zmod operator+(const Zmod& z) const { return value + z.value; } + Zmod operator-(const Zmod& z) const { return value - z.value; } + Zmod operator*(const Zmod& z) const { return value * z.value; } + Zmod operator+=(const Zmod& z) { return (*this) = value + z.value; } + Zmod operator-=(const Zmod& z) { return (*this) = value - z.value; } + Zmod operator*=(const Zmod& z) { return (*this) = value * z.value; } - bool operator==(const Zmod& z) const { return int64 == z.int64; } - bool operator!=(const Zmod& z) const { return int64 != z.int64; } + bool operator==(const Zmod& z) const { return value == z.value; } + bool operator!=(const Zmod& z) const { return value != z.value; } std::optional<Zmod> inverse() const { - auto [g, a, _] = extended_gcd(int64, N); + auto [g, a, _] = extended_gcd(value, N); return g == 1 ? Zmod(a) : std::optional<Zmod>{}; } @@ -40,16 +48,10 @@ public: } friend std::ostream& operator<<(std::ostream& os, const Zmod<N>& z) { - return os << "(" << z.int64 << " mod " << N << ")"; + return os << "(" << z.value << " mod " << N << ")"; } private: - int64_t int64; + decltype(N) value; }; -std::tuple<int64_t, int64_t, int64_t> extended_gcd(int64_t a, int64_t b) { - if (b == 0) return {a, 1, 0}; - auto [g, x, y] = extended_gcd(b, a%b); - return {g, y, x - y*(a/b)}; -} - #endif