Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
duyuefeng0708
GitHub Repository: duyuefeng0708/Cryptography-From-First-Principle
Path: blob/main/shared/tests/test_modular.py
483 views
unlisted
1
"""Tests for cryptolab.modular."""
2
3
import sys, os
4
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
5
6
from cryptolab.modular import Mod, Zmod, ZmodRing
7
import pytest
8
9
10
# --- Mod basics ---
11
12
def test_mod_creation():
13
a = Mod(10, 7)
14
assert int(a) == 3
15
assert a.modulus == 7
16
17
def test_mod_repr():
18
a = Mod(3, 7)
19
assert repr(a) == '3'
20
assert str(a) == '3'
21
22
def test_mod_negative_value():
23
a = Mod(-1, 7)
24
assert int(a) == 6
25
26
27
# --- Mod arithmetic ---
28
29
def test_mod_add():
30
assert Mod(3, 7) + Mod(5, 7) == Mod(1, 7)
31
32
def test_mod_sub():
33
assert Mod(2, 7) - Mod(5, 7) == Mod(4, 7)
34
35
def test_mod_mul():
36
assert Mod(3, 7) * Mod(4, 7) == Mod(5, 7)
37
38
def test_mod_pow():
39
assert Mod(3, 7) ** 2 == Mod(2, 7)
40
41
def test_mod_neg():
42
assert -Mod(3, 7) == Mod(4, 7)
43
44
def test_mod_invert():
45
assert ~Mod(3, 7) == Mod(5, 7)
46
# Verify: 3 * 5 = 15 = 1 mod 7
47
assert Mod(3, 7) * ~Mod(3, 7) == Mod(1, 7)
48
49
def test_mod_pow_negative():
50
# 3^(-1) mod 7 = 5
51
assert Mod(3, 7) ** (-1) == Mod(5, 7)
52
53
def test_mod_div():
54
# 6 / 3 mod 7 = 6 * 5 = 30 = 2 mod 7
55
assert Mod(6, 7) / Mod(3, 7) == Mod(2, 7)
56
57
58
# --- Mod with int ---
59
60
def test_mod_add_int():
61
assert Mod(3, 7) + 5 == Mod(1, 7)
62
assert 5 + Mod(3, 7) == Mod(1, 7)
63
64
def test_mod_mul_int():
65
assert Mod(3, 7) * 4 == Mod(5, 7)
66
assert 4 * Mod(3, 7) == Mod(5, 7)
67
68
69
# --- Mod incompatible ---
70
71
def test_mod_different_modulus():
72
with pytest.raises(ValueError):
73
Mod(3, 7) + Mod(3, 5)
74
75
76
# --- Mod comparison and hashing ---
77
78
def test_mod_eq():
79
assert Mod(3, 7) == Mod(3, 7)
80
assert Mod(3, 7) == Mod(10, 7)
81
assert Mod(3, 7) != Mod(4, 7)
82
83
def test_mod_hash():
84
s = {Mod(3, 7), Mod(10, 7), Mod(4, 7)}
85
assert len(s) == 2 # 3 and 10 are the same mod 7
86
87
def test_mod_eq_int():
88
assert Mod(3, 7) == 3
89
assert Mod(3, 7) == 10 # 10 % 7 = 3
90
91
92
# --- Mod group theory ---
93
94
def test_multiplicative_order():
95
# ord(3) in (Z/7Z)* = 6 (3 is a primitive root mod 7)
96
assert Mod(3, 7).multiplicative_order() == 6
97
# ord(2) in (Z/7Z)* = 3 (2^3 = 8 = 1 mod 7)
98
assert Mod(2, 7).multiplicative_order() == 3
99
100
def test_additive_order():
101
# additive order of 4 in Z/12Z = 12/gcd(4,12) = 12/4 = 3
102
assert Mod(4, 12).additive_order() == 3
103
assert Mod(1, 12).additive_order() == 12
104
assert Mod(0, 12).additive_order() == 1
105
106
def test_multiplicative_order_non_unit():
107
with pytest.raises(ValueError):
108
Mod(2, 4).multiplicative_order()
109
110
111
# --- ZmodRing ---
112
113
def test_zmod_creation():
114
R = Zmod(7)
115
assert R.order() == 7
116
117
def test_zmod_call():
118
R = Zmod(7)
119
a = R(10)
120
assert int(a) == 3
121
122
def test_zmod_iter():
123
R = Zmod(5)
124
elts = list(R)
125
assert len(elts) == 5
126
assert [int(x) for x in elts] == [0, 1, 2, 3, 4]
127
128
def test_zmod_list():
129
R = Zmod(4)
130
assert len(R.list()) == 4
131
132
def test_zmod_multiplicative_group():
133
R = Zmod(12)
134
units = R.list_of_elements_of_multiplicative_group()
135
assert [int(u) for u in units] == [1, 5, 7, 11]
136
137
def test_zmod_contains():
138
R = Zmod(7)
139
assert Mod(3, 7) in R
140
assert Mod(3, 5) not in R
141
142
143
# --- Operation tables ---
144
145
def test_addition_table_list():
146
R = Zmod(3)
147
table = R.addition_table(style='list')
148
# Row 0: [0+0, 0+1, 0+2] = [0, 1, 2]
149
assert table[0] == [0, 1, 2]
150
# Row 1: [1+0, 1+1, 1+2] = [1, 2, 0]
151
assert table[1] == [1, 2, 0]
152
153
def test_multiplication_table_list():
154
R = Zmod(4)
155
table = R.multiplication_table(style='list')
156
# Row 2: [2*0, 2*1, 2*2, 2*3] = [0, 2, 0, 2]
157
assert table[2] == [0, 2, 0, 2]
158
159