# HG changeset patch
# User Julian Rueth <julian.rueth@gmail.com>
# Date 1353273189 0
# Node ID 7ffe38b585130075a207b9069d9f0d72c0e231d6
# Parent 698ec14c513f99fa5a3a7aeca982cc14fd249a89
Trac #13441: refactored gcd to not use _gcd calls anymore
diff --git a/doc/en/thematic_tutorials/tutorial-objects-and-classes.rst b/doc/en/thematic_tutorials/tutorial-objects-and-classes.rst
a
|
b
|
Some particular actions modify the data structure of ``el``:: |
296 | 296 | sage: type(e) |
297 | 297 | <type 'sage.rings.integer.Integer'> |
298 | 298 | sage: e.__dict__ |
299 | | dict_proxy({'__module__': 'sage.categories.euclidean_domains', |
300 | | '_reduction': (<built-in function getattr>, (Category of |
301 | | euclidean domains, 'element_class')), '__doc__': None, |
302 | | '_sage_src_lines_': <staticmethod object at 0x...>}) |
| 299 | dict_proxy({'__module__': 'sage.categories.euclidean_domains', |
| 300 | '__doc__': None, '_reduction': (<built-in function getattr>, (Category |
| 301 | of euclidean domains, 'element_class')), 'gcd': |
| 302 | <sage.structure.element.NamedBinopMethod object at 0x...>, |
| 303 | '_sage_src_lines_': <staticmethod object at 0x...>}) |
303 | 304 | sage: e.__dict__.keys() |
304 | | ['__module__', '_reduction', '__doc__', '_sage_src_lines_'] |
| 305 | ['__module__', '__doc__', '_reduction', 'gcd', '_sage_src_lines_'] |
305 | 306 | |
306 | 307 | sage: id4 = SymmetricGroup(4).one() |
307 | 308 | sage: type(id4) |
diff --git a/sage/categories/euclidean_domains.py b/sage/categories/euclidean_domains.py
a
|
b
|
from sage.categories.category import Category |
12 | 12 | from sage.categories.category_singleton import Category_singleton |
13 | 13 | from sage.categories.principal_ideal_domains import PrincipalIdealDomains |
14 | 14 | from sage.misc.cachefunc import cached_method |
| 15 | from sage.structure.element import coerce_binop |
15 | 16 | |
16 | 17 | class EuclideanDomains(Category_singleton): |
17 | 18 | """ |
… |
… |
class EuclideanDomains(Category_singleton): |
54 | 55 | return True |
55 | 56 | |
56 | 57 | class ElementMethods: |
57 | | pass |
| 58 | @coerce_binop |
| 59 | def gcd(self, other): |
| 60 | """ |
| 61 | Return the greatest common divisor of this element and ``other``. |
| 62 | |
| 63 | INPUT: |
| 64 | |
| 65 | - ``other`` -- an element in the same ring as ``self`` |
| 66 | |
| 67 | ALGORITHM: |
| 68 | |
| 69 | Algorithm 3.2.1 in [Coh1996]. |
| 70 | |
| 71 | REFERENCES: |
| 72 | |
| 73 | .. [Coh1996] Henri Cohen. A Course in Computational Algebraic Number Theory. Springer, 1996. |
| 74 | |
| 75 | EXAMPLES:: |
| 76 | |
| 77 | sage: EuclideanDomains().ElementMethods().gcd(6,4) |
| 78 | 2 |
| 79 | |
| 80 | """ |
| 81 | A = self |
| 82 | B = other |
| 83 | while not B.is_zero(): |
| 84 | Q, R = A.quo_rem(B) |
| 85 | A = B |
| 86 | B = R |
| 87 | return A |
diff --git a/sage/categories/quotient_fields.py b/sage/categories/quotient_fields.py
a
|
b
|
class QuotientFields(Category_singleton): |
107 | 107 | sage: gcd(R.1/1,0) |
108 | 108 | 1 |
109 | 109 | sage: gcd(R.zero(),0) |
110 | | 0 |
| 110 | 0 |
111 | 111 | |
112 | 112 | """ |
113 | 113 | try: |
diff --git a/sage/rings/polynomial/polynomial_element_generic.py b/sage/rings/polynomial/polynomial_element_generic.py
a
|
b
|
class Polynomial_generic_field(Polynomial_singular_repr, |
620 | 620 | R = R[:R.degree()] - (aaa*B[:B.degree()]).shift(diff_deg) |
621 | 621 | return (Q, R) |
622 | 622 | |
623 | | def _gcd(self, other): |
| 623 | @coerce_binop |
| 624 | def gcd(self, other): |
624 | 625 | """ |
625 | | Return the GCD of self and other, as a monic polynomial. |
| 626 | Return the greatest common divisor of this polynomial and ``other``, as |
| 627 | a monic polynomial. |
| 628 | |
| 629 | INPUT: |
| 630 | |
| 631 | - ``other`` -- a polynomial defined over the same ring as ``self`` |
| 632 | |
| 633 | EXAMPLES:: |
| 634 | |
| 635 | sage: R.<x> = QQbar[] |
| 636 | sage: (2*x).gcd(2*x^2) |
| 637 | x |
| 638 | |
626 | 639 | """ |
627 | | g = EuclideanDomainElement._gcd(self, other) |
| 640 | from sage.categories.euclidean_domains import EuclideanDomains |
| 641 | g = EuclideanDomains().ElementMethods().gcd(self, other) |
628 | 642 | c = g.leading_coefficient() |
629 | 643 | if c.is_unit(): |
630 | 644 | return (1/c)*g |
diff --git a/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx b/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx
a
|
b
|
cdef class Polynomial_dense_modn_ntl_ZZ(Polynomial_dense_mod_n): |
1765 | 1765 | |
1766 | 1766 | cdef class Polynomial_dense_mod_p(Polynomial_dense_mod_n): |
1767 | 1767 | """ |
1768 | | A dense polynomial over the integers modulo p, where p is prime. |
| 1768 | A dense polynomial over the integers modulo p, where p is prime. |
1769 | 1769 | """ |
1770 | 1770 | |
1771 | 1771 | @coerce_binop |
1772 | 1772 | def gcd(self, right): |
1773 | | return self._gcd(right) |
1774 | | |
1775 | | def _gcd(self, right): |
1776 | 1773 | """ |
1777 | | Return the GCD of self and other, as a monic polynomial. |
| 1774 | Return the greatest common divisor of this polynomial and ``other``, as |
| 1775 | a monic polynomial. |
| 1776 | |
| 1777 | INPUT: |
| 1778 | |
| 1779 | - ``other`` -- a polynomial defined over the same ring as ``self`` |
| 1780 | |
| 1781 | EXAMPLES:: |
| 1782 | |
| 1783 | sage: R.<x> = PolynomialRing(GF(3),implementation="NTL") |
| 1784 | sage: f,g = x + 2, x^2 - 1 |
| 1785 | sage: f.gcd(g) |
| 1786 | x + 2 |
| 1787 | |
1778 | 1788 | """ |
1779 | | if not isinstance(right, Polynomial_dense_mod_p): |
1780 | | right = self.parent()(right) |
1781 | | elif self.parent() != right.parent(): |
1782 | | raise TypeError |
1783 | 1789 | g = self.ntl_ZZ_pX().gcd(right.ntl_ZZ_pX()) |
1784 | 1790 | return self.parent()(g, construct=True) |
1785 | 1791 | |
diff --git a/sage/rings/rational.pyx b/sage/rings/rational.pyx
a
|
b
|
from sage.libs.pari.gen cimport gen as pari_gen, PariInstance |
63 | 63 | from integer_ring import ZZ |
64 | 64 | |
65 | 65 | from sage.structure.element cimport Element, RingElement, ModuleElement |
66 | | from sage.structure.element import bin_op |
| 66 | from sage.structure.element import bin_op, coerce_binop |
67 | 67 | from sage.categories.morphism cimport Morphism |
68 | 68 | from sage.categories.map cimport Map |
69 | 69 | |
… |
… |
cdef class Rational(sage.structure.element.FieldElement): |
893 | 893 | from sage.rings.arith import gcd, lcm |
894 | 894 | return gcd(nums) / lcm(denoms) |
895 | 895 | |
896 | | # def gcd_rational(self, other, **kwds): |
897 | | # """ |
898 | | # Return a gcd of the rational numbers self and other. |
899 | | # |
900 | | # If self = other = 0, this is by convention 0. In all other |
901 | | # cases it can (mathematically) be any nonzero rational number, |
902 | | # but for simplicity we choose to always return 1. |
903 | | # |
904 | | # EXAMPLES:: |
905 | | # |
906 | | # sage: (1/3).gcd_rational(2/1) |
907 | | # 1 |
908 | | # sage: (1/1).gcd_rational(0/1) |
909 | | # 1 |
910 | | # sage: (0/1).gcd_rational(0/1) |
911 | | # 0 |
912 | | # """ |
913 | | # if self == 0 and other == 0: |
914 | | # return Rational(0) |
915 | | # else: |
916 | | # return Rational(1) |
917 | | |
918 | 896 | def valuation(self, p): |
919 | 897 | r""" |
920 | 898 | Return the power of ``p`` in the factorization of self. |
… |
… |
cdef class Rational(sage.structure.element.FieldElement): |
2994 | 2972 | mpz_cmp_si(mpq_numref(other.value), 0) == 0: |
2995 | 2973 | return Rational(0) |
2996 | 2974 | return Rational(1) |
2997 | | |
2998 | | def _gcd(self, Rational other): |
2999 | | """ |
3000 | | Returns the least common multiple, in the rational numbers, of self |
3001 | | and other. This function returns either 0 or 1 (as a rational |
3002 | | number). |
3003 | | |
3004 | | INPUT: |
3005 | | |
3006 | | |
3007 | | - ``other`` - Rational |
3008 | | |
3009 | | |
3010 | | OUTPUT: |
3011 | | |
3012 | | |
3013 | | - ``Rational`` - 0 or 1 |
3014 | | |
3015 | | |
3016 | | EXAMPLES:: |
3017 | | |
3018 | | sage: (2/3)._gcd(3/5) |
3019 | | 1 |
3020 | | sage: (0/1)._gcd(0/1) |
3021 | | 0 |
3022 | | """ |
3023 | | if mpz_cmp_si(mpq_numref(self.value), 0) == 0 and \ |
3024 | | mpz_cmp_si(mpq_numref(other.value), 0) == 0: |
3025 | | return Rational(0) |
3026 | | return Rational(1) |
3027 | | |
3028 | 2975 | |
3029 | 2976 | def additive_order(self): |
3030 | 2977 | """ |
diff --git a/sage/structure/element.pyx b/sage/structure/element.pyx
a
|
b
|
cdef class PrincipalIdealDomainElement(DedekindDomainElement): |
2785 | 2785 | return coercion_model.bin_op(self, right, lcm) |
2786 | 2786 | return self._lcm(right) |
2787 | 2787 | |
2788 | | def gcd(self, right): |
2789 | | """ |
2790 | | Returns the gcd of self and right, or 0 if both are 0. |
2791 | | """ |
2792 | | if not PY_TYPE_CHECK(right, Element) or not ((<Element>right)._parent is self._parent): |
2793 | | return coercion_model.bin_op(self, right, gcd) |
2794 | | return self._gcd(right) |
2795 | | |
2796 | 2788 | def xgcd(self, right): |
2797 | 2789 | r""" |
2798 | 2790 | Return the extended gcd of self and other, i.e., elements `r, s, t` such that |
… |
… |
cdef class EuclideanDomainElement(PrincipalIdealDomainElement): |
2827 | 2819 | def degree(self): |
2828 | 2820 | raise NotImplementedError |
2829 | 2821 | |
2830 | | def _gcd(self, other): |
2831 | | """ |
2832 | | Return the greatest common divisor of self and other. |
2833 | | |
2834 | | Algorithm 3.2.1 in Cohen, GTM 138. |
2835 | | """ |
2836 | | A = self |
2837 | | B = other |
2838 | | while not B.is_zero(): |
2839 | | Q, R = A.quo_rem(B) |
2840 | | A = B |
2841 | | B = R |
2842 | | return A |
2843 | | |
2844 | 2822 | def leading_coefficient(self): |
2845 | 2823 | raise NotImplementedError |
2846 | 2824 | |
… |
… |
cdef class FieldElement(CommutativeRingElement): |
2924 | 2902 | True |
2925 | 2903 | """ |
2926 | 2904 | return not not self |
2927 | | |
2928 | | def _gcd(self, FieldElement other): |
2929 | | """ |
2930 | | Return the greatest common divisor of self and other. |
2931 | | """ |
2932 | | if self.is_zero() and other.is_zero(): |
2933 | | return self |
2934 | | else: |
2935 | | return self._parent(1) |
2936 | 2905 | |
2937 | 2906 | def _lcm(self, FieldElement other): |
2938 | 2907 | """ |