From e127f835319e4b5e6dcdc2f0ed9a111a47fcecdf Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Sat, 23 Nov 2019 23:39:21 +0000 Subject: [PATCH] catacomb/__init__.py: Prepare rational classes for upcoming changes. In the near future, we won't be able to guarantee that all rings allow implicit conversions of (integer) 0 and 1 to the additive and multiplicative ring identities, so: * define `ZERO' and `ONE' class attributes on the concrete classes to hold the respective ring identities; * make the `_split_rat' function into a private method of the `BaseRat' class and adjust callers to match; * compare against `ZERO' to detect an exact element of the base ring; and * return `ONE' as the implicit denominator for a base-ring element or foreign object to be converted. No functional change. --- catacomb/__init__.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/catacomb/__init__.py b/catacomb/__init__.py index d59d3f3..dc5ecbb 100644 --- a/catacomb/__init__.py +++ b/catacomb/__init__.py @@ -272,15 +272,12 @@ def secret_unbox(k, n, c): ###-------------------------------------------------------------------------- ### Multiprecision integers and binary polynomials. -def _split_rat(x): - if isinstance(x, BaseRat): return x._n, x._d - else: return x, 1 class BaseRat (object): """Base class implementing fields of fractions over Euclidean domains.""" def __new__(cls, a, b): a, b = cls.RING(a), cls.RING(b) q, r = divmod(a, b) - if r == 0: return q + if r == cls.ZERO: return q g = b.gcd(r) me = super(BaseRat, cls).__new__(cls) me._n = a//g @@ -294,31 +291,34 @@ class BaseRat (object): def __repr__(me): return '%s(%s, %s)' % (_clsname(me), me._n, me._d) _repr_pretty_ = _pp_str + def _split_rat(me, x): + if isinstance(x, me.__class__): return x._n, x._d + else: return x, me.ONE def __add__(me, you): - n, d = _split_rat(you) + n, d = me._split_rat(you) return type(me)(me._n*d + n*me._d, d*me._d) __radd__ = __add__ def __sub__(me, you): - n, d = _split_rat(you) + n, d = me._split_rat(you) return type(me)(me._n*d - n*me._d, d*me._d) def __rsub__(me, you): - n, d = _split_rat(you) + n, d = me._split_rat(you) return type(me)(n*me._d - me._n*d, d*me._d) def __mul__(me, you): - n, d = _split_rat(you) + n, d = me._split_rat(you) return type(me)(me._n*n, me._d*d) __rmul__ = __mul__ def __truediv__(me, you): - n, d = _split_rat(you) + n, d = me._split_rat(you) return type(me)(me._n*d, me._d*n) def __rtruediv__(me, you): - n, d = _split_rat(you) + n, d = me._split_rat(you) return type(me)(me._d*n, me._n*d) if _sys.version_info < (3,): __div__ = __truediv__ __rdiv__ = __rtruediv__ def _order(me, you, op): - n, d = _split_rat(you) + n, d = me._split_rat(you) return op(me._n*d, n*me._d) def __eq__(me, you): return me._order(you, lambda x, y: x == y) def __ne__(me, you): return me._order(you, lambda x, y: x != y) @@ -329,6 +329,7 @@ class BaseRat (object): class IntRat (BaseRat): RING = MP + ZERO, ONE = MP(0), MP(1) def __new__(cls, a, b): if isinstance(a, float) or isinstance(b, float): return a/b return super(IntRat, cls).__new__(cls, a, b) @@ -336,6 +337,7 @@ class IntRat (BaseRat): class GFRat (BaseRat): RING = GF + ZERO, ONE = GF(0), GF(1) class _tmp: def negp(x): return x < 0 -- 2.11.0