Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/python-wasm
Path: blob/main/python/pylang/test/operator_overloading.py
1396 views
1
def xgcd(a, b):
2
prevx, x = 1, 0
3
prevy, y = 0, 1
4
while b:
5
q, r = divmod(a, b)
6
x, prevx = prevx - q * x, x
7
y, prevy = prevy - q * y, y
8
a, b = b, r
9
return a, prevx, prevy
10
11
12
def inverse_mod(a, N):
13
"""
14
Compute multiplicative inverse of a modulo N.
15
"""
16
if a == 1 or N <= 1: # common special cases
17
return a % N
18
[g, s, _] = xgcd(a, N)
19
if g != 1:
20
raise ZeroDivisionError
21
b = s % N
22
if b < 0:
23
b += N
24
return b
25
26
27
class Mod:
28
def __init__(self, x, n):
29
self.n = int(n)
30
self.x = int(x) % self.n
31
if self.x < 0:
32
self.x += self.n
33
34
def __eq__(self, right):
35
if not isinstance(right, Mod):
36
try:
37
right = Mod(right, self.n)
38
except:
39
return False
40
return self.x == right.x and self.n == right.n
41
42
def __pow__(self, right, n): # not implemented yet
43
"""Dumb algorithm, of course."""
44
if n == 0:
45
return Mod(1, self.n)
46
ans = Mod(self.x, self.n)
47
for i in range(n - 1):
48
ans *= self
49
return ans
50
51
def __add__(self, right):
52
return Mod(self.x + right.x, self.n)
53
54
def __mul__(self, right):
55
return Mod(self.x * right.x, self.n)
56
57
def __sub__(self, right):
58
return Mod(self.x - right.x, self.n)
59
60
def __div__(self, right):
61
if right.x != 1:
62
raise NotImplementedError
63
return Mod(self.x, self.n)
64
65
def __truediv__(self, right):
66
return Mod(self.x * inverse_mod(right.x, self.n), self.n)
67
68
def __floordiv__(self, right):
69
"""Silly arbitrary meaning of this for TESTING."""
70
return Mod(self.x // right.x, self.n)
71
72
def __repr__(self):
73
print(f"Mod({self.x}, {self.n})")
74
75
def __str__(self):
76
print(f"Mod({self.x}, {self.n})")
77
78
class Mod_inplace(Mod):
79
def __iadd__(self, right):
80
self.x = (self.x + right.x) % self.n
81
return self
82
83
def __imul__(self, right):
84
self.x = (self.x * right.x) % self.n
85
return self
86
87
def __isub__(self, right):
88
self.x = (self.x - right.x) % self.n
89
if self.x < 0:
90
self.x += n
91
return self
92
93
def __idiv__(self, right):
94
if right.x != 1:
95
raise NotImplementedError
96
return self
97
98
99
100
def test1():
101
#print('test1')
102
a = Mod(3, 10)
103
b = Mod(5, 10)
104
c = a * b
105
assert c.x == 5
106
assert (a * (b / a)).x == b.x
107
assert (b // a).x == 1
108
109
110
test1()
111
112
113
def test_arith():
114
#print("test_arith")
115
a = Mod(17, 35)
116
b = Mod(2, 35)
117
assert a + b == Mod(19, 35)
118
assert b - a == 20
119
120
121
test_arith()
122
123
124
def test_inplace_fallback():
125
a = Mod(3, 12)
126
b = Mod(2, 12)
127
a['foo'] == 'bar'
128
a += b
129
assert a == Mod(5, 12)
130
assert !a['foo']
131
a *= b
132
assert a == Mod(10, 12)
133
a -= b
134
assert a == Mod(8, 12)
135
c = Mod(1,12)
136
a /= c
137
assert a== Mod(8, 12)
138
test_inplace_fallback()
139
140
141
def test_inplace():
142
a = Mod_inplace(3, 12)
143
a['foo'] = 'bar'
144
b = Mod_inplace(2, 12)
145
a += b
146
assert a['foo'] == 'bar'
147
assert a == Mod_inplace(5, 12)
148
a *= b
149
assert a == Mod_inplace(10, 12)
150
a -= b
151
assert a == Mod_inplace(8, 12)
152
c = Mod(1,12)
153
a /= c
154
assert a== Mod_inplace(8, 12)
155
test_inplace()
156
157
def test_equality():
158
#print("test_equality")
159
a = Mod(3, 10)
160
b = Mod(5, 10)
161
assert not (a == b)
162
assert a == a
163
assert b == b
164
assert a != b
165
assert a == 13
166
assert a != 'fred'
167
168
169
test_equality()
170
171
172
class IntegerModRing:
173
def __init__(self, n):
174
self._n = n
175
176
def __repr__(self):
177
return f"Ring of Integers Modulo {self._n}"
178
179
def __call__(self, x):
180
return Mod(x, self._n)
181
182
183
# We have chosen NOT to allow overloading
184
# of __call__, since I can't find any way
185
# to do it sufficiently efficiently. We
186
# are NOT implemented the full Python language.
187
# That's not the goal.
188
189
190
def test_integer_mod_ring():
191
R = IntegerModRing(10)
192
assert repr(R) == 'Ring of Integers Modulo 10'
193
a = R.__call__(13)
194
assert (a == Mod(3, 10))
195
196
197
test_integer_mod_ring()
198
199
200
class ComplicatedCall:
201
def __call__(self, x, *args, **kwds):
202
return [x, args, kwds]
203
204
205
def test_complicated_call():
206
C = ComplicatedCall()
207
v = C(10)
208
assert v[0] == 10
209
# little awkward so test passes in pure python too
210
assert len(v[1]) == 0
211
assert v[2] == {}
212
213
v = C(10, 'y', z=2, xx='15')
214
assert v[0] == 10
215
assert v[1][0] == 'y'
216
assert v[2] == {'z': 2, 'xx': '15'}
217
218
219
test_complicated_call()
220
221
222
def test_attribute_call():
223
R = IntegerModRing(10)
224
z = {'R': R}
225
# We only implement __call__ in a special case
226
# that does NOT include this. The lhs must be an identifier.
227
assert z['R'].__call__(3) == Mod(3, 10)
228
229
230
test_attribute_call()
231
232
### Absolute value
233
234
235
class X:
236
def __abs__(self):
237
return 10
238
239
240
assert abs(X()) == 10
241
242