diff --git a/src/sage/arith/misc.py b/src/sage/arith/misc.py index 6969cf26cc5..a88df6e6cc5 100644 --- a/src/sage/arith/misc.py +++ b/src/sage/arith/misc.py @@ -1887,11 +1887,8 @@ def __GCD_sequence(v, **kwargs): """ if len(v) == 0: return ZZ.zero() - if hasattr(v, 'universe'): - g = v.universe()(0) - else: - g = ZZ.zero() - for vi in v: + g = v[0] + for vi in v[1:]: g = vi.gcd(g, **kwargs) return g diff --git a/src/sage/categories/rings.py b/src/sage/categories/rings.py index deb6219274b..64d7d25a893 100644 --- a/src/sage/categories/rings.py +++ b/src/sage/categories/rings.py @@ -1000,7 +1000,7 @@ def _test_characteristic(self, **options): from sage.rings.integer import Integer tester.assertIsInstance(characteristic, Integer) - def ideal(self, *args, **kwds): + def ideal(self, *args, coerce=True, ideal_class=None, **kwds): """ Create an ideal of this ring. @@ -1096,15 +1096,9 @@ def ideal(self, *args, **kwds): sage: type(ZZ.ideal((), ideal_class=CustomIdealClass)) """ - if 'coerce' in kwds: - coerce = kwds['coerce'] - del kwds['coerce'] - else: - coerce = True - from sage.rings.ideal import Ideal_generic if not args: - gens = [self(0)] + gens = [] else: gens = args while isinstance(gens, (list, tuple, GeneratorType)) and len(gens) == 1: @@ -1132,29 +1126,30 @@ def ideal(self, *args, **kwds): elif coerce: gens = [self(g) for g in gens] - from sage.categories.principal_ideal_domains import PrincipalIdealDomains - if self in PrincipalIdealDomains(): - # Use GCD algorithm to obtain a principal ideal - g = gens[0] - if len(gens) == 1: - try: - # note: we set g = gcd(g, g) to "canonicalize" the generator: - # make polynomials monic, etc. - g = g.gcd(g) - except (AttributeError, NotImplementedError, IndexError): - pass - else: - for h in gens[1:]: - g = g.gcd(h) - gens = [g] - if 'ideal_class' in kwds: - C = kwds['ideal_class'] - del kwds['ideal_class'] - else: - C = self._ideal_class_(len(gens)) + # Parent classes may define eagerly_reduce_gens_by_gcd = False to opt out of this + # either because gcd() is expensive, checking whether self is PID is expensive, + # or because ideal_class constructor already have a more efficient gcd() + if getattr(self, 'eagerly_reduce_ideal_gens_by_gcd', True): + from sage.categories.principal_ideal_domains import PrincipalIdealDomains + if self in PrincipalIdealDomains(): + from sage.arith.misc import gcd + # Use GCD algorithm to obtain a principal ideal + if len(gens) == 1: + try: + # note: we set g = gcd(g, g) to "canonicalize" the generator: + # make polynomials monic, etc. + g = gens[0] + gens = g.gcd(g), + except (AttributeError, NotImplementedError, IndexError): + pass + else: + gens = gcd(gens), + + if ideal_class is None: + ideal_class = self._ideal_class_(len(gens)) if len(gens) == 1 and isinstance(gens[0], (list, tuple)): gens = gens[0] - return C(self, gens, **kwds) + return ideal_class(self, gens, **kwds) # Quotient rings def quotient(self, I, names=None, **kwds): diff --git a/src/sage/rings/ideal.py b/src/sage/rings/ideal.py index 752ad05c35f..cf48dca3c1c 100644 --- a/src/sage/rings/ideal.py +++ b/src/sage/rings/ideal.py @@ -28,6 +28,7 @@ from types import GeneratorType +from sage.misc.cachefunc import cached_method from sage.categories.rings import Rings from sage.categories.fields import Fields from sage.structure.element import MonoidElement @@ -702,6 +703,7 @@ def ngens(self): """ return len(self.__gens) + @cached_method def gens_reduced(self): r""" Same as :meth:`gens()` for this ideal, since there is currently no @@ -715,6 +717,11 @@ def gens_reduced(self): sage: ZZ.ideal(5).gens_reduced() (5,) """ + if not getattr(self.__ring, 'eagerly_reduce_ideal_gens_by_gcd', True): + from sage.categories.principal_ideal_domains import PrincipalIdealDomains + if self.__ring in PrincipalIdealDomains(): + from sage.arith.misc import gcd + return gcd(self.gens()), return self.gens() def is_maximal(self): diff --git a/src/sage/rings/polynomial/polynomial_ring.py b/src/sage/rings/polynomial/polynomial_ring.py index 0da5acc6908..8e0bf04fde1 100644 --- a/src/sage/rings/polynomial/polynomial_ring.py +++ b/src/sage/rings/polynomial/polynomial_ring.py @@ -241,6 +241,7 @@ class PolynomialRing_generic(Ring): """ Univariate polynomial ring over a ring. """ + eagerly_reduce_ideal_gens_by_gcd = False def __init__(self, base_ring, name=None, sparse=False, implementation=None, element_class=None, category=None):