diff --git a/src/flint/test/test_all.py b/src/flint/test/test_all.py index 3d64e712..66dba04c 100644 --- a/src/flint/test/test_all.py +++ b/src/flint/test/test_all.py @@ -841,6 +841,10 @@ def test_fmpq(): assert raises(lambda: Q(1,2) / Q(0), ZeroDivisionError) assert raises(lambda: Q(1,2) / 0, ZeroDivisionError) + assert Q(2,3).gcd(Q(4,9)) == Q(2,9) + assert Q(2,3).gcd(5) == Q(1,3) + assert raises(lambda: Q(2,3).gcd([]), TypeError) + assert Q(5,3).floor() == flint.fmpz(1) assert Q(-5,3).floor() == flint.fmpz(-2) assert Q(5,3).ceil() == flint.fmpz(2) diff --git a/src/flint/types/fmpq.pyx b/src/flint/types/fmpq.pyx index 4481f20f..6f64f85d 100644 --- a/src/flint/types/fmpq.pyx +++ b/src/flint/types/fmpq.pyx @@ -288,6 +288,24 @@ cdef class fmpq(flint_scalar): def __rtruediv__(s, t): return fmpq._div_(t, s) + def gcd(s, t): + """GCD of two rational numbers. + + >>> fmpq(1,2).gcd(fmpq(3,4)) + 1/4 + + The GCD is defined as the GCD of the numerators divided by the LCM of + the denominators. This is consistent with ``fmpz.gcd()`` but not with + ``fmpq_poly.gcd()``. + """ + cdef fmpq r + t = any_as_fmpq(t) + if t is NotImplemented: + raise TypeError("fmpq expected") + r = fmpq.__new__(fmpq) + fmpq_gcd(r.val, (s).val, (t).val) + return r + def next(s, bint signed=True, bint minimal=True): """ Returns the next rational number after *s* as ordered by