Path: blob/main/shared/tests/test_modular.py
483 views
unlisted
"""Tests for cryptolab.modular."""12import sys, os3sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))45from cryptolab.modular import Mod, Zmod, ZmodRing6import pytest789# --- Mod basics ---1011def test_mod_creation():12a = Mod(10, 7)13assert int(a) == 314assert a.modulus == 71516def test_mod_repr():17a = Mod(3, 7)18assert repr(a) == '3'19assert str(a) == '3'2021def test_mod_negative_value():22a = Mod(-1, 7)23assert int(a) == 6242526# --- Mod arithmetic ---2728def test_mod_add():29assert Mod(3, 7) + Mod(5, 7) == Mod(1, 7)3031def test_mod_sub():32assert Mod(2, 7) - Mod(5, 7) == Mod(4, 7)3334def test_mod_mul():35assert Mod(3, 7) * Mod(4, 7) == Mod(5, 7)3637def test_mod_pow():38assert Mod(3, 7) ** 2 == Mod(2, 7)3940def test_mod_neg():41assert -Mod(3, 7) == Mod(4, 7)4243def test_mod_invert():44assert ~Mod(3, 7) == Mod(5, 7)45# Verify: 3 * 5 = 15 = 1 mod 746assert Mod(3, 7) * ~Mod(3, 7) == Mod(1, 7)4748def test_mod_pow_negative():49# 3^(-1) mod 7 = 550assert Mod(3, 7) ** (-1) == Mod(5, 7)5152def test_mod_div():53# 6 / 3 mod 7 = 6 * 5 = 30 = 2 mod 754assert Mod(6, 7) / Mod(3, 7) == Mod(2, 7)555657# --- Mod with int ---5859def test_mod_add_int():60assert Mod(3, 7) + 5 == Mod(1, 7)61assert 5 + Mod(3, 7) == Mod(1, 7)6263def test_mod_mul_int():64assert Mod(3, 7) * 4 == Mod(5, 7)65assert 4 * Mod(3, 7) == Mod(5, 7)666768# --- Mod incompatible ---6970def test_mod_different_modulus():71with pytest.raises(ValueError):72Mod(3, 7) + Mod(3, 5)737475# --- Mod comparison and hashing ---7677def test_mod_eq():78assert Mod(3, 7) == Mod(3, 7)79assert Mod(3, 7) == Mod(10, 7)80assert Mod(3, 7) != Mod(4, 7)8182def test_mod_hash():83s = {Mod(3, 7), Mod(10, 7), Mod(4, 7)}84assert len(s) == 2 # 3 and 10 are the same mod 78586def test_mod_eq_int():87assert Mod(3, 7) == 388assert Mod(3, 7) == 10 # 10 % 7 = 3899091# --- Mod group theory ---9293def test_multiplicative_order():94# ord(3) in (Z/7Z)* = 6 (3 is a primitive root mod 7)95assert Mod(3, 7).multiplicative_order() == 696# ord(2) in (Z/7Z)* = 3 (2^3 = 8 = 1 mod 7)97assert Mod(2, 7).multiplicative_order() == 39899def test_additive_order():100# additive order of 4 in Z/12Z = 12/gcd(4,12) = 12/4 = 3101assert Mod(4, 12).additive_order() == 3102assert Mod(1, 12).additive_order() == 12103assert Mod(0, 12).additive_order() == 1104105def test_multiplicative_order_non_unit():106with pytest.raises(ValueError):107Mod(2, 4).multiplicative_order()108109110# --- ZmodRing ---111112def test_zmod_creation():113R = Zmod(7)114assert R.order() == 7115116def test_zmod_call():117R = Zmod(7)118a = R(10)119assert int(a) == 3120121def test_zmod_iter():122R = Zmod(5)123elts = list(R)124assert len(elts) == 5125assert [int(x) for x in elts] == [0, 1, 2, 3, 4]126127def test_zmod_list():128R = Zmod(4)129assert len(R.list()) == 4130131def test_zmod_multiplicative_group():132R = Zmod(12)133units = R.list_of_elements_of_multiplicative_group()134assert [int(u) for u in units] == [1, 5, 7, 11]135136def test_zmod_contains():137R = Zmod(7)138assert Mod(3, 7) in R139assert Mod(3, 5) not in R140141142# --- Operation tables ---143144def test_addition_table_list():145R = Zmod(3)146table = R.addition_table(style='list')147# Row 0: [0+0, 0+1, 0+2] = [0, 1, 2]148assert table[0] == [0, 1, 2]149# Row 1: [1+0, 1+1, 1+2] = [1, 2, 0]150assert table[1] == [1, 2, 0]151152def test_multiplication_table_list():153R = Zmod(4)154table = R.multiplication_table(style='list')155# Row 2: [2*0, 2*1, 2*2, 2*3] = [0, 2, 0, 2]156assert table[2] == [0, 2, 0, 2]157158159