#if 0 cc=${CC:-g++} bin="$(mktemp)" ${cc} -x c++ -std=c++20 -o "$bin" "$(realpath $0)" "$bin" exit 0 #endif #include "zmodn.h" #include #include #include #include template requires std::convertible_to || std::convertible_to void assert_equal(S actual, T expected) { if (actual != expected) { std::cout << "Error!" << std::endl; std::cout << "Expected: " << expected << std::endl; std::cout << "But got: " << actual << std::endl; exit(1); } } class Test { public: std::string name; std::function f; } tests[] = { { .name = "Constructor 2 mod 3", .f = []() { Zmod<3> two = Zmod<3>(2); assert_equal(two.toint(), INT64_C(2)); } }, { .name = "Constructor -7 mod 3", .f = []() { Zmod<3> z = -7; assert_equal(z, Zmod<3>(2)); } }, { .name = "1+1 mod 2", .f = []() { auto oneplusone = Zmod<2>(1) + Zmod<2>(1); assert_equal(oneplusone, Zmod<2>(0)); } }, { .name = "2 -= 5 (mod 4)", .f = []() { Zmod<4> z = 2; auto diff = (z -= 5); assert_equal(z, Zmod<4>(1)); assert_equal(diff, Zmod<4>(1)); } }, { .name = "Inverse of 0 mod 2", .f = []() { Zmod<2> z = 0; auto inv = z.inverse(); assert_equal(inv.has_value(), false); } }, { .name = "Inverse of 1 mod 2", .f = []() { Zmod<2> z = 1; auto inv = z.inverse(); assert_equal(inv.has_value(), true); assert_equal(inv.value(), Zmod<2>(1)); } }, { .name = "Inverse of 5 mod 7", .f = []() { Zmod<7> z = 5; auto inv = z.inverse(); assert_equal(inv.has_value(), true); assert_equal(inv.value(), Zmod<7>(3)); } }, { .name = "Inverse of 4 mod 12", .f = []() { Zmod<12> z = 4; auto inv = z.inverse(); assert_equal(inv.has_value(), false); } }, { .name = "4 / 7 (mod 12)", .f = []() { Zmod<12> n = 4; Zmod<12> d = 7; auto inv = n / d; assert_equal(inv.has_value(), true); assert_equal(inv.value(), Zmod<12>(4)); } }, { .name = "4 /= 7 (mod 12)", .f = []() { Zmod<12> n = 4; Zmod<12> d = 7; auto inv = (n /= d); assert_equal(inv.has_value(), true); assert_equal(inv.value(), Zmod<12>(4)); assert_equal(n, Zmod<12>(4)); } }, { .name = "Multiplication overflow", .f = []() { Zmod<10> n = 8; Zmod<10> m = 9; auto prod = m * n; assert_equal(prod.toint(), 2); } }, { .name = "Multiplication and assignment overflow", .f = []() { Zmod<10> n = 8; Zmod<10> m = 9; n *= m; assert_equal(n.toint(), 2); } }, { .name = "2^12 mod 154", .f = []() { Zmod<154> b = 2; auto p = b ^ 12; assert_equal(p, 92); } }, }; int main() { for (auto t : tests) { std::cout << t.name << ": "; t.f(); std::cout << "OK" << std::endl; } std::cout << "All tests passed" << std::endl; return 0; }