aboutsummaryrefslogtreecommitdiff
path: root/zmodn.h
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano@tronto.net>2024-12-21 12:30:41 +0100
committerSebastiano Tronto <sebastiano@tronto.net>2024-12-21 12:30:41 +0100
commit6eaa7b33aa8690f5ba4cee0897d2d05c71c27c20 (patch)
treeef686d3341f046ffe69945c3af40ec5dd4cad321 /zmodn.h
downloadzmodn-6eaa7b33aa8690f5ba4cee0897d2d05c71c27c20.tar.gz
zmodn-6eaa7b33aa8690f5ba4cee0897d2d05c71c27c20.zip
Initial commit
Diffstat (limited to 'zmodn.h')
-rw-r--r--zmodn.h71
1 files changed, 71 insertions, 0 deletions
diff --git a/zmodn.h b/zmodn.h
new file mode 100644
index 0000000..8981257
--- /dev/null
+++ b/zmodn.h
@@ -0,0 +1,71 @@
1#ifndef ZMODN_H
2#define ZMODN_H
3
4#include <cstdint>
5#include <iostream>
6#include <optional>
7#include <tuple>
8
9std::tuple<int64_t, int64_t, int64_t> extended_gcd(int64_t, int64_t);
10
11template<int64_t N> requires(N > 1)
12class Zmod {
13public:
14 Zmod(int64_t z) : int64{(z%N + N) % N} {}
15 int64_t toint64() const { return int64; }
16
17 Zmod operator+(const Zmod& z) const { return int64 + z.int64; }
18 Zmod operator-(const Zmod& z) const { return int64 - z.int64; }
19 Zmod operator*(const Zmod& z) const { return int64 * z.int64; }
20 Zmod operator+=(const Zmod& z) { return int64 += z.int64; }
21 Zmod operator-=(const Zmod& z) { return int64 -= z.int64; }
22 Zmod operator*=(const Zmod& z) { return int64 *= z.int64; }
23
24 bool operator==(const Zmod& z) const { return int64 == z.int64; }
25 bool operator!=(const Zmod& z) const { return int64 != z.int64; }
26
27 std::optional<Zmod> inverse() const {
28 auto [g, a, _] = extended_gcd(int64, N);
29 return g == 1 ? Zmod(a) : std::optional<Zmod>{};
30 }
31
32 std::optional<Zmod> operator/(const Zmod& d) const {
33 auto i = d.inverse();
34 return i ? (*this) * i.value() : i;
35 }
36
37 std::optional<Zmod> operator/=(const Zmod& d) {
38 auto q = *this / d;
39 return q ? (*this = q.value()) : q;
40 }
41
42 friend std::ostream& operator<<(std::ostream& os, const Zmod<N>& z) {
43 return os << "(" << z.int64 << " mod " << N << ")";
44 }
45private:
46 int64_t int64;
47};
48
49void swapdiv(int64_t& oldx, int64_t& x, int64_t q) {
50 int64_t tmp = x;
51 x = oldx - q*tmp;
52 oldx = tmp;
53}
54
55std::tuple<int64_t, int64_t, int64_t> extended_gcd(int64_t a, int64_t b) {
56 int64_t oldr = a;
57 int64_t r = b;
58 int64_t olds = 1;
59 int64_t s = 0;
60 int64_t oldt = 0;
61 int64_t t = 1;
62 while (r != 0) {
63 auto q = oldr / r;
64 swapdiv(oldr, r, q);
65 swapdiv(olds, s, q);
66 swapdiv(oldt, t, q);
67 }
68 return {oldr, olds, oldt};
69}
70
71#endif