taming-cpp

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

zmodn-2.cpp (1297B)


      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 
     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 	// Contrary to zmodn-1.cpp, the following line does not compile at all
     52 	Zmod<0> z(157);
     53 
     54 	return 0;
     55 }