From 6eaa7b33aa8690f5ba4cee0897d2d05c71c27c20 Mon Sep 17 00:00:00 2001 From: Sebastiano Tronto Date: Sat, 21 Dec 2024 12:30:41 +0100 Subject: Initial commit --- zmodn.h | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 zmodn.h (limited to 'zmodn.h') diff --git a/zmodn.h b/zmodn.h new file mode 100644 index 0000000..8981257 --- /dev/null +++ b/zmodn.h @@ -0,0 +1,71 @@ +#ifndef ZMODN_H +#define ZMODN_H + +#include +#include +#include +#include + +std::tuple extended_gcd(int64_t, int64_t); + +template requires(N > 1) +class Zmod { +public: + Zmod(int64_t z) : int64{(z%N + N) % N} {} + int64_t toint64() const { return 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) const { return int64 * z.int64; } + Zmod operator+=(const Zmod& z) { return int64 += z.int64; } + Zmod operator-=(const Zmod& z) { return int64 -= z.int64; } + Zmod operator*=(const Zmod& z) { return int64 *= z.int64; } + + bool operator==(const Zmod& z) const { return int64 == z.int64; } + bool operator!=(const Zmod& z) const { return int64 != z.int64; } + + std::optional inverse() const { + auto [g, a, _] = extended_gcd(int64, 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.int64 << " mod " << N << ")"; + } +private: + int64_t int64; +}; + +void swapdiv(int64_t& oldx, int64_t& x, int64_t q) { + int64_t tmp = x; + x = oldx - q*tmp; + oldx = tmp; +} + +std::tuple extended_gcd(int64_t a, int64_t b) { + int64_t oldr = a; + int64_t r = b; + int64_t olds = 1; + int64_t s = 0; + int64_t oldt = 0; + int64_t t = 1; + while (r != 0) { + auto q = oldr / r; + swapdiv(oldr, r, q); + swapdiv(olds, s, q); + swapdiv(oldt, t, q); + } + return {oldr, olds, oldt}; +} + +#endif -- cgit v1.2.3