diff options
| author | Sebastiano Tronto <sebastiano@tronto.net> | 2025-01-17 16:53:40 +0100 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano@tronto.net> | 2025-01-17 16:53:40 +0100 |
| commit | 6cfb7b4d8e6b0838bfcde290e5fac18f46f18fb4 (patch) | |
| tree | 9de2aeda48fc63652cb2fe50acd142afe4d854db /templates | |
| parent | 0b43d984905f07c59e3236d98d4e27409aba3cda (diff) | |
| download | taming-cpp-6cfb7b4d8e6b0838bfcde290e5fac18f46f18fb4.tar.gz taming-cpp-6cfb7b4d8e6b0838bfcde290e5fac18f46f18fb4.zip | |
Added first two zmodn versions
Diffstat (limited to '')
| -rw-r--r-- | templates/zmodn-1.cpp | 55 | ||||
| -rw-r--r-- | templates/zmodn-2.cpp | 56 |
2 files changed, 111 insertions, 0 deletions
diff --git a/templates/zmodn-1.cpp b/templates/zmodn-1.cpp new file mode 100644 index 0000000..a8e26ca --- /dev/null +++ b/templates/zmodn-1.cpp | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | #include <iostream> | ||
| 2 | #include <optional> | ||
| 3 | #include <tuple> | ||
| 4 | |||
| 5 | std::tuple<int, int, int> extended_gcd(int a, int b) { | ||
| 6 | if (b == 0) return {a, 1, 0}; | ||
| 7 | auto [g, x, y] = extended_gcd(b, a%b); | ||
| 8 | return {g, y, x - y*(a/b)}; | ||
| 9 | } | ||
| 10 | |||
| 11 | template<int N> | ||
| 12 | class Zmod { | ||
| 13 | public: | ||
| 14 | int value; | ||
| 15 | |||
| 16 | Zmod(int z) : value{(z%N + N) % N} {} | ||
| 17 | int toint() const { return value; } | ||
| 18 | |||
| 19 | Zmod operator+(const Zmod& z) const { return value + z.value; } | ||
| 20 | Zmod operator-(const Zmod& z) const { return value - z.value; } | ||
| 21 | Zmod operator*(const Zmod& z) const { return value * z.value; } | ||
| 22 | |||
| 23 | std::optional<Zmod> inverse() const { | ||
| 24 | auto [g, a, _] = extended_gcd(value, N); | ||
| 25 | return g == 1 ? Zmod(a) : std::optional<Zmod>{}; | ||
| 26 | } | ||
| 27 | |||
| 28 | std::optional<Zmod> operator/(const Zmod& d) const { | ||
| 29 | auto i = d.inverse(); | ||
| 30 | return i ? (*this) * i.value() : i; | ||
| 31 | } | ||
| 32 | |||
| 33 | std::optional<Zmod> operator/=(const Zmod& d) { | ||
| 34 | auto q = *this / d; | ||
| 35 | return q ? (*this = q.value()) : q; | ||
| 36 | } | ||
| 37 | }; | ||
| 38 | |||
| 39 | int main() { | ||
| 40 | Zmod<57> x(34); | ||
| 41 | Zmod<57> y(11); | ||
| 42 | |||
| 43 | std::cout << "34 * 11 = " << (x * y).value << " (mod 57)" << std::endl; | ||
| 44 | |||
| 45 | if (auto inv = y.inverse(); inv) | ||
| 46 | std::cout << "11 * " << inv.value().value << " = 1 (mod 57)" << std::endl; | ||
| 47 | else | ||
| 48 | std::cout << "11 is not invertible in Z/57Z" << std::endl; | ||
| 49 | |||
| 50 | |||
| 51 | // The following line gives a run-time exception | ||
| 52 | // Zmod<0> z(157); | ||
| 53 | |||
| 54 | return 0; | ||
| 55 | } | ||
diff --git a/templates/zmodn-2.cpp b/templates/zmodn-2.cpp new file mode 100644 index 0000000..f96ef8c --- /dev/null +++ b/templates/zmodn-2.cpp | |||
| @@ -0,0 +1,56 @@ | |||
| 1 | #include <iostream> | ||
| 2 | #include <optional> | ||
| 3 | #include <tuple> | ||
| 4 | |||
| 5 | std::tuple<int, int, int> extended_gcd(int a, int b) { | ||
| 6 | if (b == 0) return {a, 1, 0}; | ||
| 7 | auto [g, x, y] = extended_gcd(b, a%b); | ||
| 8 | return {g, y, x - y*(a/b)}; | ||
| 9 | } | ||
| 10 | |||
| 11 | template<int N> | ||
| 12 | requires (N > 1) | ||
| 13 | class Zmod { | ||
| 14 | public: | ||
| 15 | int value; | ||
| 16 | |||
| 17 | Zmod(int z) : value{(z%N + N) % N} {} | ||
| 18 | int toint() const { return value; } | ||
| 19 | |||
| 20 | Zmod operator+(const Zmod& z) const { return value + z.value; } | ||
| 21 | Zmod operator-(const Zmod& z) const { return value - z.value; } | ||
| 22 | Zmod operator*(const Zmod& z) const { return value * z.value; } | ||
| 23 | |||
| 24 | std::optional<Zmod> inverse() const { | ||
| 25 | auto [g, a, _] = extended_gcd(value, N); | ||
| 26 | return g == 1 ? Zmod(a) : std::optional<Zmod>{}; | ||
| 27 | } | ||
| 28 | |||
| 29 | std::optional<Zmod> operator/(const Zmod& d) const { | ||
| 30 | auto i = d.inverse(); | ||
| 31 | return i ? (*this) * i.value() : i; | ||
| 32 | } | ||
| 33 | |||
| 34 | std::optional<Zmod> operator/=(const Zmod& d) { | ||
| 35 | auto q = *this / d; | ||
| 36 | return q ? (*this = q.value()) : q; | ||
| 37 | } | ||
| 38 | }; | ||
| 39 | |||
| 40 | int main() { | ||
| 41 | Zmod<57> x(34); | ||
| 42 | Zmod<57> y(11); | ||
| 43 | |||
| 44 | std::cout << "34 * 11 = " << (x * y).value << " (mod 57)" << std::endl; | ||
| 45 | |||
| 46 | if (auto inv = y.inverse(); inv) | ||
| 47 | std::cout << "11 * " << inv.value().value << " = 1 (mod 57)" << std::endl; | ||
| 48 | else | ||
| 49 | std::cout << "11 is not invertible in Z/57Z" << std::endl; | ||
| 50 | |||
| 51 | |||
| 52 | // Contrary to zmodn-1.cpp, the following line does not compile at all | ||
| 53 | Zmod<0> z(157); | ||
| 54 | |||
| 55 | return 0; | ||
| 56 | } | ||
