diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index 4c835d0..77a3a18 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -4414,6 +4414,29 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sig_off() return z + def _gcd(self, Integer n): + """ + Return the greatest common divisor of self and `n`. + + EXAMPLES:: + + sage: 1._gcd(-1) + 1 + sage: 0._gcd(1) + 1 + sage: 0._gcd(0) + 0 + sage: 2._gcd(2^6) + 2 + sage: 21._gcd(2^6) + 1 + """ + cdef Integer z = PY_NEW(Integer) + sig_on() + mpz_gcd(z.value, self.value, n.value) + sig_off() + return z + def denominator(self): """ Return the denominator of this integer, which of course is @@ -6736,33 +6759,6 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): raise ZeroDivisionError(f"inverse of Mod({self}, {m}) does not exist") return ans - def gcd(self, n): - """ - Return the greatest common divisor of self and `n`. - - EXAMPLES:: - - sage: gcd(-1,1) - 1 - sage: gcd(0,1) - 1 - sage: gcd(0,0) - 0 - sage: gcd(2,2^6) - 2 - sage: gcd(21,2^6) - 1 - """ - if not isinstance(n, Integer) and not isinstance(n, int): - left, right = coercion_model.canonical_coercion(self, n) - return left.gcd(right) - cdef Integer m = as_Integer(n) - cdef Integer g = PY_NEW(Integer) - sig_on() - mpz_gcd(g.value, self.value, m.value) - sig_off() - return g - def crt(self, y, m, n): """ Return the unique integer between `0` and `mn` that is congruent to diff --git a/src/sage/structure/element.pyx b/src/sage/structure/element.pyx index f145e66..1cf634e 100644 --- a/src/sage/structure/element.pyx +++ b/src/sage/structure/element.pyx @@ -3908,16 +3908,79 @@ def is_PrincipalIdealDomainElement(x): return isinstance(x, PrincipalIdealDomainElement) cdef class PrincipalIdealDomainElement(DedekindDomainElement): + def gcd(self, right): + r""" + Return the greatest common divisor of ``self`` and ``other``. + + TESTS: + + :trac:`30849`:: + + sage: 2.gcd(pari(3)) + 1 + sage: type(2.gcd(pari(3))) + + + sage: 2.gcd(pari('1/3')) + 1/3 + sage: type(2.gcd(pari('1/3'))) + + + sage: import gmpy2 + sage: 2.gcd(gmpy2.mpz(3)) + 1 + sage: type(2.gcd(gmpy2.mpz(3))) + + + sage: 2.gcd(gmpy2.mpq(1,3)) + 1/3 + sage: type(2.gcd(pari('1/3'))) + + """ + # NOTE: in order to handle nicely pari or gmpy2 integers we do not rely only on coercion + if not isinstance(right, Element): + right = py_scalar_to_element(right) + if not isinstance(right, Element): + right = right.sage() + if not ((right)._parent is self._parent): + from sage.arith.all import gcd + return coercion_model.bin_op(self, right, gcd) + return self._gcd(right) + def lcm(self, right): """ Return the least common multiple of ``self`` and ``right``. - """ - if not isinstance(right, Element) or not ((right)._parent is self._parent): + + TESTS: + + :trac:`30849`:: + + sage: 2.lcm(pari(3)) + 6 + sage: type(2.lcm(pari(3))) + + + sage: 2.lcm(pari('1/3')) + 2 + sage: type(2.lcm(pari('1/3'))) + + + sage: import gmpy2 + sage: 2.lcm(gmpy2.mpz(3)) + 6 + sage: type(2.lcm(gmpy2.mpz(3))) + + """ + # NOTE: in order to handle nicely pari or gmpy2 integers we do not rely only on coercion + if not isinstance(right, Element): + right = py_scalar_to_element(right) + if not isinstance(right, Element): + right = right.sage() + if not ((right)._parent is self._parent): from sage.arith.all import lcm return coercion_model.bin_op(self, right, lcm) return self._lcm(right) - # This is pretty nasty low level stuff. The idea is to speed up construction # of EuclideanDomainElements (in particular Integers) by skipping some tp_new # calls up the inheritance tree.