From 7f1b8a358515b45d717c3c4b5baf2fbc0f568170 Mon Sep 17 00:00:00 2001 From: Sebastiano Tronto Date: Wed, 26 Feb 2025 17:12:06 +0100 Subject: Initial commit --- code/cpp/zmodn.h | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 code/cpp/zmodn.h (limited to 'code/cpp/zmodn.h') diff --git a/code/cpp/zmodn.h b/code/cpp/zmodn.h new file mode 100644 index 0000000..a24f293 --- /dev/null +++ b/code/cpp/zmodn.h @@ -0,0 +1,79 @@ +#ifndef ZMODN_H +#define ZMODN_H + +#include +#include +#include +#include +#include + +template +concept Integer = requires(T a, T b, int i, std::ostream& os) { + {T(i)}; + + {a + b} -> std::same_as; + {a - b} -> std::same_as; + {a * b} -> std::same_as; + {a / b} -> std::same_as; + {a % b} -> std::same_as; + + {a == b} -> std::same_as; + {a != b} -> std::same_as; + + {os << a} -> std::same_as; +}; + +template +std::tuple extended_gcd(T a, 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)}; +} + +template +requires(N > 1) +class Zmod { +public: + Zmod(decltype(N) z) : value{(z%N + N) % N} {} + decltype(N) toint() const { return 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) 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; } + + Zmod operator^(decltype(N) z) const { + if (z == 0) return 1; + if (z % 2 == 0) return (((*this) * (*this)) ^ (z/2)); + return (*this) * ((*this) ^ (z-1)); + } + + bool operator==(const Zmod& z) const { return value == z.value; } + bool operator!=(const Zmod& z) const { return value != z.value; } + + std::optional inverse() const { + auto [g, a, _] = extended_gcd(value, N); + return g == 1 ? Zmod(a) : std::optional{}; + } + + std::optional operator/(const Zmod& d) const { + auto i = d.inverse(); + return i ? (*this) * i.value() : i; + } + + std::optional operator/=(const Zmod& d) { + auto q = *this / d; + return q ? (*this = q.value()) : q; + } + + friend std::ostream& operator<<(std::ostream& os, const Zmod& z) { + return os << "(" << z.value << " mod " << N << ")"; + } +private: + decltype(N) value; +}; + +#endif -- cgit v1.3