diff options
| author | Sebastiano Tronto <sebastiano@tronto.net> | 2024-12-21 17:22:09 +0100 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano@tronto.net> | 2024-12-21 17:22:09 +0100 |
| commit | 7e705a3342bc36f9f02b4e8e0050bc5842a62f9b (patch) | |
| tree | e496ef743d63168bc1f7a5d57167a0229889b396 /zmodn.h | |
| parent | b0d8a2f5f5718ba3fea628cad7bcbbc76c6a140c (diff) | |
| download | zmodn-7e705a3342bc36f9f02b4e8e0050bc5842a62f9b.tar.gz zmodn-7e705a3342bc36f9f02b4e8e0050bc5842a62f9b.zip | |
Make N's type generic for possible use with bigint
Diffstat (limited to 'zmodn.h')
| -rw-r--r-- | zmodn.h | 44 |
1 files changed, 23 insertions, 21 deletions
| @@ -5,27 +5,35 @@ | |||
| 5 | #include <iostream> | 5 | #include <iostream> |
| 6 | #include <optional> | 6 | #include <optional> |
| 7 | #include <tuple> | 7 | #include <tuple> |
| 8 | #include <type_traits> | ||
| 8 | 9 | ||
| 9 | std::tuple<int64_t, int64_t, int64_t> extended_gcd(int64_t, int64_t); | 10 | template<typename INT> |
| 11 | requires std::is_integral_v<INT> | ||
| 12 | std::tuple<INT, INT, INT> extended_gcd(INT a, INT b) { | ||
| 13 | if (b == 0) return {a, 1, 0}; | ||
| 14 | auto [g, x, y] = extended_gcd(b, a%b); | ||
| 15 | return {g, y, x - y*(a/b)}; | ||
| 16 | } | ||
| 10 | 17 | ||
| 11 | template<int64_t N> requires(N > 1) | 18 | template<auto N> |
| 19 | requires(N > 1) && std::is_integral_v<decltype(N)> | ||
| 12 | class Zmod { | 20 | class Zmod { |
| 13 | public: | 21 | public: |
| 14 | Zmod(int64_t z) : int64{(z%N + N) % N} {} | 22 | Zmod(decltype(N) z) : value{(z%N + N) % N} {} |
| 15 | int64_t toint64() const { return int64; } | 23 | decltype(N) toint() const { return value; } |
| 16 | 24 | ||
| 17 | Zmod operator+(const Zmod& z) const { return int64 + z.int64; } | 25 | Zmod operator+(const Zmod& z) const { return value + z.value; } |
| 18 | Zmod operator-(const Zmod& z) const { return int64 - z.int64; } | 26 | Zmod operator-(const Zmod& z) const { return value - z.value; } |
| 19 | Zmod operator*(const Zmod& z) const { return int64 * z.int64; } | 27 | Zmod operator*(const Zmod& z) const { return value * z.value; } |
| 20 | Zmod operator+=(const Zmod& z) { return (*this) = int64 + z.int64; } | 28 | Zmod operator+=(const Zmod& z) { return (*this) = value + z.value; } |
| 21 | Zmod operator-=(const Zmod& z) { return (*this) = int64 - z.int64; } | 29 | Zmod operator-=(const Zmod& z) { return (*this) = value - z.value; } |
| 22 | Zmod operator*=(const Zmod& z) { return (*this) = int64 * z.int64; } | 30 | Zmod operator*=(const Zmod& z) { return (*this) = value * z.value; } |
| 23 | 31 | ||
| 24 | bool operator==(const Zmod& z) const { return int64 == z.int64; } | 32 | bool operator==(const Zmod& z) const { return value == z.value; } |
| 25 | bool operator!=(const Zmod& z) const { return int64 != z.int64; } | 33 | bool operator!=(const Zmod& z) const { return value != z.value; } |
| 26 | 34 | ||
| 27 | std::optional<Zmod> inverse() const { | 35 | std::optional<Zmod> inverse() const { |
| 28 | auto [g, a, _] = extended_gcd(int64, N); | 36 | auto [g, a, _] = extended_gcd(value, N); |
| 29 | return g == 1 ? Zmod(a) : std::optional<Zmod>{}; | 37 | return g == 1 ? Zmod(a) : std::optional<Zmod>{}; |
| 30 | } | 38 | } |
| 31 | 39 | ||
| @@ -40,16 +48,10 @@ public: | |||
| 40 | } | 48 | } |
| 41 | 49 | ||
| 42 | friend std::ostream& operator<<(std::ostream& os, const Zmod<N>& z) { | 50 | friend std::ostream& operator<<(std::ostream& os, const Zmod<N>& z) { |
| 43 | return os << "(" << z.int64 << " mod " << N << ")"; | 51 | return os << "(" << z.value << " mod " << N << ")"; |
| 44 | } | 52 | } |
| 45 | private: | 53 | private: |
| 46 | int64_t int64; | 54 | decltype(N) value; |
| 47 | }; | 55 | }; |
| 48 | 56 | ||
| 49 | std::tuple<int64_t, int64_t, int64_t> extended_gcd(int64_t a, int64_t b) { | ||
| 50 | if (b == 0) return {a, 1, 0}; | ||
| 51 | auto [g, x, y] = extended_gcd(b, a%b); | ||
| 52 | return {g, y, x - y*(a/b)}; | ||
| 53 | } | ||
| 54 | |||
| 55 | #endif | 57 | #endif |
