diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index 7d0e6f34464..1b4d3a1ff10 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -6975,11 +6975,9 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): def crt(self, y, m, n): """ - Return the unique integer between `0` and `mn` that is congruent to + Return the unique integer between `0` and `\\lcm(m,n)` that is congruent to the integer modulo `m` and to `y` modulo `n`. - We assume that `m` and `n` are coprime. - EXAMPLES:: sage: n = 17 @@ -6989,6 +6987,16 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): 17 sage: m%11 5 + + ``crt`` also works for some non-coprime moduli:: + + sage: 6.crt(0,10,4) + 16 + sage: 6.crt(0,10,10) + Traceback (most recent call last): + ... + ValueError: no solution to crt problem since gcd(10,10) does not + divide 6 - 0 """ cdef object g, s cdef Integer _y, _m, _n @@ -6997,7 +7005,9 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): _n = Integer(n) g, s, _ = _m.xgcd(_n) if not g.is_one(): - raise ArithmeticError("CRT requires that gcd of moduli is 1.") + if (self % g) != (_y % g): + raise ValueError(f"no solution to crt problem since gcd({_m},{_n}) does not divide {self} - {_y}") + return (self + g * Integer(0).crt((_y - self) // g, _m // g, _n // g)) % _m.lcm(_n) # Now s*m + t*n = 1, so the answer is x + (y-x)*s*m, where x=self. return (self + (_y - self) * s * _m) % (_m * _n)