From 83c77564338b3e410eb2ca2db3d35173dd6666cc Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Wed, 13 May 2015 11:39:25 +0100 Subject: [PATCH 1/1] catacomb/__init__.py: Generalize rationals to fields of fractions. Now we can have ratios of binary polynomials too. --- catacomb/__init__.py | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/catacomb/__init__.py b/catacomb/__init__.py index 19a973b..b50c99a 100644 --- a/catacomb/__init__.py +++ b/catacomb/__init__.py @@ -100,15 +100,16 @@ bytes = ByteString.fromhex ### Multiprecision integers and binary polynomials. def _split_rat(x): - if isinstance(x, Rat): return x._n, x._d + if isinstance(x, BaseRat): return x._n, x._d else: return x, 1 -class Rat (object): +class BaseRat (object): + """Base class implementing fields of fractions over Euclidean domains.""" def __new__(cls, a, b): - a, b = MP(a), MP(b) + a, b = cls.RING(a), cls.RING(b) q, r = divmod(a, b) if r == 0: return q g = b.gcd(r) - me = super(Rat, cls).__new__(cls) + me = super(BaseRat, cls).__new__(cls) me._n = a//g me._d = b//g return me @@ -117,34 +118,40 @@ class Rat (object): @property def denom(me): return me._d def __str__(me): return '%s/%s' % (me._n, me._d) - def __repr__(me): return 'Rat(%s, %s)' % (me._n, me._d) + def __repr__(me): return '%s(%s, %s)' % (type(me).__name__, me._n, me._d) def __add__(me, you): n, d = _split_rat(you) - return Rat(me._n*d + n*me._d, d*me._d) + return type(me)(me._n*d + n*me._d, d*me._d) __radd__ = __add__ def __sub__(me, you): n, d = _split_rat(you) - return Rat(me._n*d - n*me._d, d*me._d) + return type(me)(me._n*d - n*me._d, d*me._d) def __rsub__(me, you): n, d = _split_rat(you) - return Rat(n*me._d - me._n*d, d*me._d) + return type(me)(n*me._d - me._n*d, d*me._d) def __mul__(me, you): n, d = _split_rat(you) - return Rat(me._n*n, me._d*d) + return type(me)(me._n*n, me._d*d) def __div__(me, you): n, d = _split_rat(you) - return Rat(me._n*d, me._d*n) + return type(me)(me._n*d, me._d*n) def __rdiv__(me, you): n, d = _split_rat(you) - return Rat(me._d*n, me._n*d) + return type(me)(me._d*n, me._n*d) def __cmp__(me, you): n, d = _split_rat(you) - return cmp(me._n*d, n*me._d) + return type(me)(me._n*d, n*me._d) def __rcmp__(me, you): n, d = _split_rat(you) return cmp(n*me._d, me._n*d) +class IntRat (BaseRat): + RING = MP + +class GFRat (BaseRat): + RING = GF + class _tmp: def negp(x): return x < 0 def posp(x): return x > 0 @@ -154,8 +161,8 @@ class _tmp: def mont(x): return MPMont(x) def barrett(x): return MPBarrett(x) def reduce(x): return MPReduce(x) - def __div__(me, you): return Rat(me, you) - def __rdiv__(me, you): return Rat(you, me) + def __div__(me, you): return IntRat(me, you) + def __rdiv__(me, you): return IntRat(you, me) _augment(MP, _tmp) class _tmp: @@ -165,6 +172,8 @@ class _tmp: def halftrace(x, y): return x.reduce().halftrace(y) def modsqrt(x, y): return x.reduce().sqrt(y) def quadsolve(x, y): return x.reduce().quadsolve(y) + def __div__(me, you): return GFRat(me, you) + def __rdiv__(me, you): return GFRat(you, me) _augment(GF, _tmp) class _tmp: -- 2.11.0