from .euclidean import * from .numbertype import * # so all IntegersModP are instances of the same base class class _Modular(FieldElement): pass @memoize def IntegersModP(p): # assume p is prime class IntegerModP(_Modular): def __init__(self, n): try: self.n = int(n) % IntegerModP.p except: raise TypeError("Can't cast type %s to %s in __init__" % (type(n).__name__, type(self).__name__)) self.field = IntegerModP @typecheck def __add__(self, other): return IntegerModP(self.n + other.n) @typecheck def __sub__(self, other): return IntegerModP(self.n - other.n) @typecheck def __mul__(self, other): return IntegerModP(self.n * other.n) def __neg__(self): return IntegerModP(-self.n) @typecheck def __eq__(self, other): return isinstance(other, IntegerModP) and self.n == other.n @typecheck def __ne__(self, other): return isinstance(other, IntegerModP) is False or self.n != other.n @typecheck def __divmod__(self, divisor): q,r = divmod(self.n, divisor.n) return (IntegerModP(q), IntegerModP(r)) def inverse(self): # need to use the division algorithm *as integers* because we're # doing it on the modulus itself (which would otherwise be zero) x,y,d = extendedEuclideanAlgorithm(self.n, self.p) if d != 1: raise Exception("Error: p is not prime in %s!" % (self.__name__)) return IntegerModP(x) def __abs__(self): return abs(self.n) def __str__(self): return str(self.n) def __repr__(self): return '%d (mod %d)' % (self.n, self.p) def __int__(self): return self.n def __hash__(self): return hash((self.n, self.p)) IntegerModP.p = p IntegerModP.__name__ = 'Z/%d' % (p) IntegerModP.englishName = 'IntegersMod%d' % (p) return IntegerModP if __name__ == "__main__": mod7 = IntegersModP(7)