taming-cpp

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

zmodn-1.cpp (1261B)


      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 
     18 	Zmod operator+(const Zmod& z) const { return value + z.value; }
     19 	Zmod operator-(const Zmod& z) const { return value - z.value; }
     20 	Zmod operator*(const Zmod& z) const { return value * z.value; }
     21 
     22 	std::optional<Zmod> inverse() const {
     23 		auto [g, a, _] = extended_gcd(value, N);
     24 		return g == 1 ? Zmod(a) : std::optional<Zmod>{};
     25 	}
     26 
     27 	std::optional<Zmod> operator/(const Zmod& d) const {
     28 		auto i = d.inverse();
     29 		return i ? (*this) * i.value() : i;
     30 	}
     31 
     32 	std::optional<Zmod> operator/=(const Zmod& d) {
     33 		auto q = *this / d;
     34 		return q ? (*this = q.value()) : q;
     35 	}
     36 };
     37 
     38 int main() {
     39 	Zmod<57> x(34);
     40 	Zmod<57> y(11);
     41 
     42 	std::cout << "34 * 11 = " << (x * y).value << " (mod 57)" << std::endl;
     43 
     44 	if (auto inv = y.inverse(); inv)
     45 		std::cout << "11 * " << inv.value().value << " = 1 (mod 57)" << std::endl;
     46 	else
     47 		std::cout << "11 is not invertible in Z/57Z" << std::endl;
     48 
     49 
     50 	// The following line gives a run-time exception
     51 	// Zmod<0> z(157);
     52 
     53 	return 0;
     54 }