taming-cpp

Experiments with C++ and comparisons with C
git clone https://git.tronto.net/taming-cpp
Download | Log | Files | Refs | README

commit 6cfb7b4d8e6b0838bfcde290e5fac18f46f18fb4
parent 0b43d984905f07c59e3236d98d4e27409aba3cda
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Fri, 17 Jan 2025 16:53:40 +0100

Added first two zmodn versions

Diffstat:
Atemplates/zmodn-1.cpp | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atemplates/zmodn-2.cpp | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 111 insertions(+), 0 deletions(-)

diff --git a/templates/zmodn-1.cpp b/templates/zmodn-1.cpp @@ -0,0 +1,55 @@ +#include <iostream> +#include <optional> +#include <tuple> + +std::tuple<int, int, int> extended_gcd(int a, int 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<int N> +class Zmod { +public: + int value; + + Zmod(int z) : value{(z%N + N) % N} {} + int 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; } + + std::optional<Zmod> inverse() const { + auto [g, a, _] = extended_gcd(value, N); + return g == 1 ? Zmod(a) : std::optional<Zmod>{}; + } + + std::optional<Zmod> operator/(const Zmod& d) const { + auto i = d.inverse(); + return i ? (*this) * i.value() : i; + } + + std::optional<Zmod> operator/=(const Zmod& d) { + auto q = *this / d; + return q ? (*this = q.value()) : q; + } +}; + +int main() { + Zmod<57> x(34); + Zmod<57> y(11); + + std::cout << "34 * 11 = " << (x * y).value << " (mod 57)" << std::endl; + + if (auto inv = y.inverse(); inv) + std::cout << "11 * " << inv.value().value << " = 1 (mod 57)" << std::endl; + else + std::cout << "11 is not invertible in Z/57Z" << std::endl; + + + // The following line gives a run-time exception + // Zmod<0> z(157); + + return 0; +} diff --git a/templates/zmodn-2.cpp b/templates/zmodn-2.cpp @@ -0,0 +1,56 @@ +#include <iostream> +#include <optional> +#include <tuple> + +std::tuple<int, int, int> extended_gcd(int a, int 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<int N> +requires (N > 1) +class Zmod { +public: + int value; + + Zmod(int z) : value{(z%N + N) % N} {} + int 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; } + + std::optional<Zmod> inverse() const { + auto [g, a, _] = extended_gcd(value, N); + return g == 1 ? Zmod(a) : std::optional<Zmod>{}; + } + + std::optional<Zmod> operator/(const Zmod& d) const { + auto i = d.inverse(); + return i ? (*this) * i.value() : i; + } + + std::optional<Zmod> operator/=(const Zmod& d) { + auto q = *this / d; + return q ? (*this = q.value()) : q; + } +}; + +int main() { + Zmod<57> x(34); + Zmod<57> y(11); + + std::cout << "34 * 11 = " << (x * y).value << " (mod 57)" << std::endl; + + if (auto inv = y.inverse(); inv) + std::cout << "11 * " << inv.value().value << " = 1 (mod 57)" << std::endl; + else + std::cout << "11 is not invertible in Z/57Z" << std::endl; + + + // Contrary to zmodn-1.cpp, the following line does not compile at all + Zmod<0> z(157); + + return 0; +}