Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
r""" Rings """ #***************************************************************************** # Copyright (C) 2005 David Kohel <kohel@maths.usyd.edu> # William Stein <wstein@math.ucsd.edu> # 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr> # 2008-2011 Nicolas M. Thiery <nthiery at users.sf.net> # # Distributed under the terms of the GNU General Public License (GPL) # http://www.gnu.org/licenses/ #******************************************************************************
from sage.misc.cachefunc import cached_method from sage.misc.lazy_import import LazyImport from sage.categories.category_with_axiom import CategoryWithAxiom from sage.categories.rngs import Rngs from sage.structure.element import Element from functools import reduce from sage.misc.cachefunc import cached_method
class Rings(CategoryWithAxiom): """ The category of rings
Associative rings with unit, not necessarily commutative
EXAMPLES::
sage: Rings() Category of rings sage: sorted(Rings().super_categories(), key=str) [Category of rngs, Category of semirings]
sage: sorted(Rings().axioms()) ['AdditiveAssociative', 'AdditiveCommutative', 'AdditiveInverse', 'AdditiveUnital', 'Associative', 'Distributive', 'Unital']
sage: Rings() is (CommutativeAdditiveGroups() & Monoids()).Distributive() True sage: Rings() is Rngs().Unital() True sage: Rings() is Semirings().AdditiveInverse() True
TESTS::
sage: TestSuite(Rings()).run()
.. TODO::
(see: http://trac.sagemath.org/sage_trac/wiki/CategoriesRoadMap)
- Make Rings() into a subcategory or alias of Algebras(ZZ);
- A parent P in the category ``Rings()`` should automatically be in the category ``Algebras(P)``. """
_base_category_class_and_axiom = (Rngs, "Unital")
class MorphismMethods: @cached_method def is_injective(self): """ Return whether or not this morphism is injective.
EXAMPLES:
This often raises a ``NotImplementedError`` as many homomorphisms do not implement this method::
sage: R.<x> = QQ[] sage: f = R.hom([x + 1]); f Ring endomorphism of Univariate Polynomial Ring in x over Rational Field Defn: x |--> x + 1 sage: f.is_injective() Traceback (most recent call last): ... NotImplementedError
If the domain is a field, the homomorphism is injective::
sage: K.<x> = FunctionField(QQ) sage: L.<y> = FunctionField(QQ) sage: f = K.hom([y]); f Function Field morphism: From: Rational function field in x over Rational Field To: Rational function field in y over Rational Field Defn: x |--> y sage: f.is_injective() True
Unless the codomain is the zero ring::
sage: codomain = Integers(1) sage: f = QQ.hom([Zmod(1)(0)], check=False) sage: f.is_injective() False
Homomorphism from rings of characteristic zero to rings of positive characteristic can not be injective::
sage: R.<x> = ZZ[] sage: f = R.hom([GF(3)(1)]); f Ring morphism: From: Univariate Polynomial Ring in x over Integer Ring To: Finite Field of size 3 Defn: x |--> 1 sage: f.is_injective() False
A morphism whose domain is an order in a number field is injective if the codomain has characteristic zero::
sage: K.<x> = FunctionField(QQ) sage: f = ZZ.hom(K); f Composite map: From: Integer Ring To: Rational function field in x over Rational Field Defn: Conversion via FractionFieldElement_1poly_field map: From: Integer Ring To: Fraction Field of Univariate Polynomial Ring in x over Rational Field then Isomorphism morphism: From: Fraction Field of Univariate Polynomial Ring in x over Rational Field To: Rational function field in x over Rational Field sage: f.is_injective() True
A coercion to the fraction field is injective::
sage: R = ZpFM(3) sage: R.fraction_field().coerce_map_from(R).is_injective() True
""" return True # the only map to the zero ring that is injective is the map from itself
# A ring homomorphism from a field to a ring is injective # (unless the codomain is the zero ring.) Note that ring # homomorphism must send the 1 element to the 1 element
else: # if all elements of the domain are algebraic over ZZ, # then the homomorphism must be injective (in # particular if the domain is ZZ)
except (TypeError, AttributeError, ValueError): pass else:
return False
def _is_nonzero(self): r""" Return whether this is not the zero morphism.
.. NOTE::
We can not override ``is_zero()`` from the category framework and we can not implement ``__nonzero__`` because it is a special method. That this is why this has a cumbersome name.
EXAMPLES::
sage: ZZ.hom(ZZ)._is_nonzero() True sage: ZZ.hom(Zmod(1))._is_nonzero() False
"""
class SubcategoryMethods:
def NoZeroDivisors(self): """ Return the full subcategory of the objects of ``self`` having no nonzero zero divisors.
A *zero divisor* in a ring `R` is an element `x \in R` such that there exists a nonzero element `y \in R` such that `x \cdot y = 0` or `y \cdot x = 0` (see :wikipedia:`Zero_divisor`).
EXAMPLES::
sage: Rings().NoZeroDivisors() Category of domains
.. NOTE::
This could be generalized to :class:`MagmasAndAdditiveMagmas.Distributive.AdditiveUnital`.
TESTS::
sage: TestSuite(Rings().NoZeroDivisors()).run() sage: Algebras(QQ).NoZeroDivisors.__module__ 'sage.categories.rings' """
def Division(self): """ Return the full subcategory of the division objects of ``self``.
A ring satisfies the *division axiom* if all non-zero elements have multiplicative inverses.
.. NOTE::
This could be generalized to :class:`MagmasAndAdditiveMagmas.Distributive.AdditiveUnital`.
EXAMPLES::
sage: Rings().Division() Category of division rings sage: Rings().Commutative().Division() Category of fields
TESTS::
sage: TestSuite(Rings().Division()).run() sage: Algebras(QQ).Division.__module__ 'sage.categories.rings' """
NoZeroDivisors = LazyImport('sage.categories.domains', 'Domains', at_startup=True) Division = LazyImport('sage.categories.division_rings', 'DivisionRings', at_startup=True) Commutative = LazyImport('sage.categories.commutative_rings', 'CommutativeRings', at_startup=True)
class ParentMethods: def is_ring(self): """ Return True, since this in an object of the category of rings.
EXAMPLES::
sage: Parent(QQ,category=Rings()).is_ring() True
"""
def is_zero(self): """ Return ``True`` if this is the zero ring.
EXAMPLES::
sage: Integers(1).is_zero() True sage: Integers(2).is_zero() False sage: QQ.is_zero() False sage: R.<x> = ZZ[] sage: R.quo(1).is_zero() True sage: R.<x> = GF(101)[] sage: R.quo(77).is_zero() True sage: R.quo(x^2+1).is_zero() False """
def bracket(self, x, y): """ Returns the Lie bracket `[x, y] = x y - y x` of `x` and `y`.
INPUT:
- ``x``, ``y`` -- elements of ``self``
EXAMPLES::
sage: F = AlgebrasWithBasis(QQ).example() sage: F An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field sage: a,b,c = F.algebra_generators() sage: F.bracket(a,b) B[word: ab] - B[word: ba]
This measures the default of commutation between `x` and `y`. `F` endowed with the bracket operation is a Lie algebra; in particular, it satisfies Jacobi's identity::
sage: F.bracket( F.bracket(a,b), c) + F.bracket(F.bracket(b,c),a) + F.bracket(F.bracket(c,a),b) 0 """
def _Hom_(self, Y, category): r""" Returns the homset from ``self`` to ``Y`` in the category ``category``
INPUT:
- ``Y`` -- a ring - ``category`` -- a subcategory of :class:`Rings`() or None
The sole purpose of this method is to construct the homset as a :class:`~sage.rings.homset.RingHomset`. If ``category`` is specified and is not a subcategory of :class:`Rings`, a ``TypeError`` is raised instead
This method is not meant to be called directly. Please use :func:`sage.categories.homset.Hom` instead.
EXAMPLES::
sage: H = QQ._Hom_(QQ, category = Rings()); H Set of Homomorphisms from Rational Field to Rational Field sage: H.__class__ <class 'sage.rings.homset.RingHomset_generic_with_category'>
TESTS::
sage: Hom(QQ, QQ, category = Rings()).__class__ <class 'sage.rings.homset.RingHomset_generic_with_category'>
sage: Hom(CyclotomicField(3), QQ, category = Rings()).__class__ <class 'sage.rings.number_field.morphism.CyclotomicFieldHomset_with_category'>
sage: TestSuite(Hom(QQ, QQ, category = Rings())).run() # indirect doctest
""" raise TypeError("%s is not a ring"%Y)
# this is already in sage.rings.ring.Ring, # but not all rings descend from that class, # e.g., matrix spaces. def _mul_(self, x, switch_sides=False): """ Multiplication of rings with, e.g., lists.
NOTE:
This method is used to create ideals. It is the same as the multiplication method for :class:`~sage.rings.ring.Ring`. However, not all parents that belong to the category of rings also inherits from the base class of rings. Therefore, we implemented a ``__mul__`` method for parents, that calls a ``_mul_`` method implemented here. See :trac:`7797`.
INPUT:
- `x`, an object to multiply with. - `switch_sides` (optional bool): If ``False``, the product is ``self*x``; if ``True``, the product is ``x*self``.
EXAMPLES:
As we mentioned above, this method is called when a ring is involved that does not inherit from the base class of rings. This is the case, e.g., for matrix algebras::
sage: MS = MatrixSpace(QQ,2,2) sage: isinstance(MS,Ring) False sage: MS in Rings() True sage: MS*2 # indirect doctest Left Ideal ( [2 0] [0 2] ) of Full MatrixSpace of 2 by 2 dense matrices over Rational Field
In the next example, the ring and the other factor switch sides in the product::
sage: [MS.2]*MS Right Ideal ( [0 0] [1 0] ) of Full MatrixSpace of 2 by 2 dense matrices over Rational Field
AUTHOR:
- Simon King (2011-03-22)
""" return self.ideal(x) except (AttributeError,NotImplementedError): pass # presumably x is an ideal... try: x = x.gens() except (AttributeError, NotImplementedError): pass # ... not an ideal if switch_sides: if side in ['right','twosided']: return self.ideal(x,side=side) elif side=='left': return self.ideal(x,side='twosided') else: if side in ['left','twosided']: return self.ideal(x,side=side) elif side=='right': return self.ideal(x,side='twosided') # duck typing failed raise TypeError("Don't know how to transform %s into an ideal of %s"%(x,self))
@cached_method def ideal_monoid(self): """ The monoid of the ideals of this ring.
NOTE:
The code is copied from the base class of rings. This is since there are rings that do not inherit from that class, such as matrix algebras. See :trac:`7797`.
EXAMPLES::
sage: MS = MatrixSpace(QQ,2,2) sage: isinstance(MS,Ring) False sage: MS in Rings() True sage: MS.ideal_monoid() Monoid of ideals of Full MatrixSpace of 2 by 2 dense matrices over Rational Field
Note that the monoid is cached::
sage: MS.ideal_monoid() is MS.ideal_monoid() True
""" except TypeError: from sage.rings.noncommutative_ideals import IdealMonoid_nc return IdealMonoid_nc(self)
def characteristic(self): """ Return the characteristic of this ring.
EXAMPLES::
sage: QQ.characteristic() 0 sage: GF(19).characteristic() 19 sage: Integers(8).characteristic() 8 sage: Zp(5).characteristic() 0 """
def _test_characteristic(self, **options): """ Run generic tests on the method :meth:`characteristic`.
See also: :class:`TestSuite`.
EXAMPLES::
sage: ZZ._test_characteristic() """
# test that #12988 is fixed
def ideal(self, *args, **kwds): """ Create an ideal of this ring.
NOTE:
The code is copied from the base class :class:`~sage.rings.ring.Ring`. This is because there are rings that do not inherit from that class, such as matrix algebras. See :trac:`7797`.
INPUT:
- An element or a list/tuple/sequence of elements. - ``coerce`` (optional bool, default ``True``): First coerce the elements into this ring. - ``side``, optional string, one of ``"twosided"`` (default), ``"left"``, ``"right"``: determines whether the resulting ideal is twosided, a left ideal or a right ideal.
EXAMPLES::
sage: MS = MatrixSpace(QQ,2,2) sage: isinstance(MS,Ring) False sage: MS in Rings() True sage: MS.ideal(2) Twosided Ideal ( [2 0] [0 2] ) of Full MatrixSpace of 2 by 2 dense matrices over Rational Field sage: MS.ideal([MS.0,MS.1],side='right') Right Ideal ( [1 0] [0 0], <BLANKLINE> [0 1] [0 0] ) of Full MatrixSpace of 2 by 2 dense matrices over Rational Field
""" coerce = kwds['coerce'] del kwds['coerce'] else:
gens = [self(0)] else: R = first.ring() m = self.convert_map_from(R) if m is not None: gens = [m(g) for g in first.gens()] coerce = False else: m = R.convert_map_from(self) if m is not None: raise NotImplementedError else: raise TypeError break else: gens = first.gens() # we have a ring as argument else: raise ArithmeticError("There is no coercion from %s to %s"%(first,self)) except TypeError: # first may be a ring element pass # Use GCD algorithm to obtain a principal ideal g = gens[0] if len(gens) == 1: try: g = g.gcd(g) # note: we set g = gcd(g, g) to "canonicalize" the generator: make polynomials monic, etc. except (AttributeError, NotImplementedError): pass else: for h in gens[1:]: g = g.gcd(h) gens = [g] C = kwds['ideal_class'] del kwds['ideal_class'] else: gens = gens[0]
def _ideal_class_(self,n=0): """ Return the class that is used to implement ideals of this ring.
NOTE:
We copy the code from :class:`~sage.rings.ring.Ring`. This is necessary because not all rings inherit from that class, such as matrix algebras.
INPUT:
- ``n`` (optional integer, default 0): The number of generators of the ideal to be created.
OUTPUT:
The class that is used to implement ideals of this ring with ``n`` generators.
NOTE:
Often principal ideals (``n==1``) are implemented via a different class.
EXAMPLES::
sage: MS = MatrixSpace(QQ,2,2) sage: MS._ideal_class_() <class 'sage.rings.noncommutative_ideals.Ideal_nc'>
We don't know of a commutative ring in Sage that does not inherit from the base class of rings. So, we need to cheat in the next example::
sage: super(Ring,QQ)._ideal_class_.__module__ 'sage.categories.rings' sage: super(Ring,QQ)._ideal_class_() <class 'sage.rings.ideal.Ideal_generic'> sage: super(Ring,QQ)._ideal_class_(1) <class 'sage.rings.ideal.Ideal_principal'> sage: super(Ring,QQ)._ideal_class_(2) <class 'sage.rings.ideal.Ideal_generic'>
""" except (NotImplementedError,AttributeError): return Ideal_nc else:
## # Quotient rings # Again, this is defined in sage.rings.ring.pyx def quotient(self, I, names=None): """ Quotient of a ring by a two-sided ideal.
INPUT:
- ``I``: A twosided ideal of this ring. - ``names``: a list of strings to be used as names for the variables in the quotient ring.
EXAMPLES:
Usually, a ring inherits a method :meth:`sage.rings.ring.Ring.quotient`. So, we need a bit of effort to make the following example work with the category framework::
sage: F.<x,y,z> = FreeAlgebra(QQ) sage: from sage.rings.noncommutative_ideals import Ideal_nc sage: from itertools import product sage: class PowerIdeal(Ideal_nc): ....: def __init__(self, R, n): ....: self._power = n ....: Ideal_nc.__init__(self, R, [R.prod(m) for m in product(R.gens(), repeat=n)]) ....: def reduce(self, x): ....: R = self.ring() ....: return add([c*R(m) for m,c in x if len(m) < self._power], R(0)) ....: sage: I = PowerIdeal(F,3) sage: Q = Rings().parent_class.quotient(F, I); Q Quotient of Free Algebra on 3 generators (x, y, z) over Rational Field by the ideal (x^3, x^2*y, x^2*z, x*y*x, x*y^2, x*y*z, x*z*x, x*z*y, x*z^2, y*x^2, y*x*y, y*x*z, y^2*x, y^3, y^2*z, y*z*x, y*z*y, y*z^2, z*x^2, z*x*y, z*x*z, z*y*x, z*y^2, z*y*z, z^2*x, z^2*y, z^3) sage: Q.0 xbar sage: Q.1 ybar sage: Q.2 zbar sage: Q.0*Q.1 xbar*ybar sage: Q.0*Q.1*Q.0 0 """
def quo(self, I, names=None): """ Quotient of a ring by a two-sided ideal.
NOTE:
This is a synonym for :meth:`quotient`.
EXAMPLES::
sage: MS = MatrixSpace(QQ,2) sage: I = MS*MS.gens()*MS
``MS`` is not an instance of :class:`~sage.rings.ring.Ring`.
However it is an instance of the parent class of the category of rings. The quotient method is inherited from there::
sage: isinstance(MS,sage.rings.ring.Ring) False sage: isinstance(MS,Rings().parent_class) True sage: MS.quo(I,names = ['a','b','c','d']) Quotient of Full MatrixSpace of 2 by 2 dense matrices over Rational Field by the ideal ( [1 0] [0 0], <BLANKLINE> [0 1] [0 0], <BLANKLINE> [0 0] [1 0], <BLANKLINE> [0 0] [0 1] )
"""
def quotient_ring(self, I, names=None): """ Quotient of a ring by a two-sided ideal.
NOTE:
This is a synonyme for :meth:`quotient`.
EXAMPLES::
sage: MS = MatrixSpace(QQ,2) sage: I = MS*MS.gens()*MS
``MS`` is not an instance of :class:`~sage.rings.ring.Ring`, but it is an instance of the parent class of the category of rings. The quotient method is inherited from there::
sage: isinstance(MS,sage.rings.ring.Ring) False sage: isinstance(MS,Rings().parent_class) True sage: MS.quotient_ring(I,names = ['a','b','c','d']) Quotient of Full MatrixSpace of 2 by 2 dense matrices over Rational Field by the ideal ( [1 0] [0 0], <BLANKLINE> [0 1] [0 0], <BLANKLINE> [0 0] [1 0], <BLANKLINE> [0 0] [0 1] )
"""
def __truediv__(self, I): """ Since assigning generator names would not work properly, the construction of a quotient ring using division syntax is not supported.
EXAMPLES::
sage: MS = MatrixSpace(QQ,2) sage: I = MS*MS.gens()*MS sage: MS/I Traceback (most recent call last): ... TypeError: Use self.quo(I) or self.quotient(I) to construct the quotient ring. """
def __getitem__(self, arg): """ Extend this ring by one or several elements to create a polynomial ring, a power series ring, or an algebraic extension.
This is a convenience method intended primarily for interactive use.
.. SEEALSO::
:func:`~sage.rings.polynomial.polynomial_ring_constructor.PolynomialRing`, :func:`~sage.rings.power_series_ring.PowerSeriesRing`, :meth:`~sage.rings.ring.Ring.extension`, :meth:`sage.rings.integer_ring.IntegerRing_class.__getitem__`, :meth:`sage.rings.matrix_space.MatrixSpace.__getitem__`, :meth:`sage.structure.parent.Parent.__getitem__`
EXAMPLES:
We create several polynomial rings::
sage: ZZ['x'] Univariate Polynomial Ring in x over Integer Ring sage: QQ['x'] Univariate Polynomial Ring in x over Rational Field sage: GF(17)['abc'] Univariate Polynomial Ring in abc over Finite Field of size 17 sage: GF(17)['a,b,c'] Multivariate Polynomial Ring in a, b, c over Finite Field of size 17 sage: GF(17)['a']['b'] Univariate Polynomial Ring in b over Univariate Polynomial Ring in a over Finite Field of size 17
We can create skew polynomial rings::
sage: k.<t> = GF(5^3) sage: Frob = k.frobenius_endomorphism() sage: k['x',Frob] Skew Polynomial Ring in x over Finite Field in t of size 5^3 twisted by t |--> t^5
We can also create power series rings by using double brackets::
sage: QQ[['t']] Power Series Ring in t over Rational Field sage: ZZ[['W']] Power Series Ring in W over Integer Ring
sage: ZZ[['x,y,z']] Multivariate Power Series Ring in x, y, z over Integer Ring sage: ZZ[['x','T']] Multivariate Power Series Ring in x, T over Integer Ring
Use :func:`~sage.rings.fraction_field.Frac` or :meth:`~sage.rings.ring.CommutativeRing.fraction_field` to obtain the fields of rational functions and Laurent series::
sage: Frac(QQ['t']) Fraction Field of Univariate Polynomial Ring in t over Rational Field sage: Frac(QQ[['t']]) Laurent Series Ring in t over Rational Field sage: QQ[['t']].fraction_field() Laurent Series Ring in t over Rational Field
Note that the same syntax can be used to create number fields::
sage: QQ[I] Number Field in I with defining polynomial x^2 + 1 sage: QQ[I].coerce_embedding() Generic morphism: From: Number Field in I with defining polynomial x^2 + 1 To: Complex Lazy Field Defn: I -> 1*I
::
sage: QQ[sqrt(2)] Number Field in sqrt2 with defining polynomial x^2 - 2 sage: QQ[sqrt(2)].coerce_embedding() Generic morphism: From: Number Field in sqrt2 with defining polynomial x^2 - 2 To: Real Lazy Field Defn: sqrt2 -> 1.414213562373095?
::
sage: QQ[sqrt(2),sqrt(3)] Number Field in sqrt2 with defining polynomial x^2 - 2 over its base field
and orders in number fields::
sage: ZZ[I] Order in Number Field in I with defining polynomial x^2 + 1 sage: ZZ[sqrt(5)] Order in Number Field in sqrt5 with defining polynomial x^2 - 5 sage: ZZ[sqrt(2)+sqrt(3)] Order in Number Field in a with defining polynomial x^4 - 10*x^2 + 1
Embeddings are found for simple extensions (when that makes sense)::
sage: QQi.<i> = QuadraticField(-1, 'i') sage: QQ[i].coerce_embedding() Generic morphism: From: Number Field in i with defining polynomial x^2 + 1 To: Complex Lazy Field Defn: i -> 1*I
TESTS:
A few corner cases::
sage: QQ[()] Multivariate Polynomial Ring in no variables over Rational Field
sage: QQ[[]] Traceback (most recent call last): ... TypeError: power series rings must have at least one variable
These kind of expressions do not work::
sage: QQ['a,b','c'] Traceback (most recent call last): ... ValueError: variable name 'a,b' is not alphanumeric sage: QQ[['a,b','c']] Traceback (most recent call last): ... ValueError: variable name 'a,b' is not alphanumeric
sage: QQ[[['x']]] Traceback (most recent call last): ... TypeError: expected R[...] or R[[...]], not R[[[...]]]
Extension towers are built as follows and use distinct generator names::
sage: K = QQ[2^(1/3), 2^(1/2), 3^(1/3)] sage: K Number Field in a with defining polynomial x^3 - 2 over its base field sage: K.base_field() Number Field in sqrt2 with defining polynomial x^2 - 2 over its base field sage: K.base_field().base_field() Number Field in b with defining polynomial x^3 - 3
Embeddings::
sage: QQ[I](I.pyobject()) I sage: a = 10^100; expr = (2*a + sqrt(2))/(2*a^2-1) sage: QQ[expr].coerce_embedding() is None False sage: QQ[sqrt(5)].gen() > 0 True sage: expr = sqrt(2) + I*(cos(pi/4, hold=True) - sqrt(2)/2) sage: QQ[expr].coerce_embedding() Generic morphism: From: Number Field in a with defining polynomial x^2 - 2 To: Real Lazy Field Defn: a -> 1.414213562373095? """ # Allowing arbitrary iterables would create confusion, but we # may want to support a few more. else:
# 1. If arg is a list, try to return a power series ring.
# R[["a,b"]], R[[(a,b)]]... else:
# 2. Otherwise, if all specified elements are algebraic, try to # return an algebraic extension
# how to pass in names? except (TypeError, ValueError): emb = None else: # First try creating an ANRoot manually, because # extension(..., embedding=CLF(expr)) (or # ...QQbar(expr)) would normalize the expression in # QQbar, which currently is VERY slow in many cases. # This may fail when minpoly has close roots or elt is # a complicated symbolic expression. # TODO: Rewrite using #19362 and/or #17886 and/or # #15600 once those issues are solved. # Force a real embedding when possible, to get the # right ordered ring structure. and elt.imag().is_zero()): else: # Doing the extension all at once is best, if possible... except (TypeError, ValueError): # ...but we can also construct it iteratively return reduce(lambda R, ext: R.extension(*ext), zip(minpolys, names), self)
# 2. Otherwise, try to return a polynomial ring
class ElementMethods: def is_unit(self): r""" Return whether this element is a unit in the ring.
.. NOTE::
This is a generic implementation for (non-commutative) rings which only works for the one element, its additive inverse, and the zero element. Most rings should provide a more specialized implementation.
EXAMPLES::
sage: MS = MatrixSpace(ZZ, 2) sage: MS.one().is_unit() True sage: MS.zero().is_unit() False sage: MS([1,2,3,4]).is_unit() False """ if self.is_one() or (-self).is_one(): return True if self.is_zero(): # now 0 != 1 return False raise NotImplementedError
def inverse_of_unit(self): r""" Return the inverse of this element if it is a unit.
OUTPUT:
An element in the same ring as this element.
EXAMPLES::
sage: R.<x> = ZZ[] sage: S = R.quo(x^2 + x + 1) sage: S(1).inverse_of_unit() 1
This method fails when the element is not a unit::
sage: 2.inverse_of_unit() Traceback (most recent call last): ... ArithmeticError: inverse does not exist
The inverse returned is in the same ring as this element::
sage: a = -1 sage: a.parent() Integer Ring sage: a.inverse_of_unit().parent() Integer Ring
Note that this is often not the case when computing inverses in other ways::
sage: (~a).parent() Rational Field sage: (1/a).parent() Rational Field
""" raise ArithmeticError("element is not a unit") except NotImplementedError: # if an element does not implement is_unit, we just try to # invert it anyway; if the result is in the ring again, it was # a unit pass
raise ArithmeticError("element is not a unit")
# return the inverse (with the correct parent)
def _divide_if_possible(self, y): """ Divide ``self`` by ``y`` if possible and raise a ``ValueError`` otherwise.
EXAMPLES::
sage: 4._divide_if_possible(2) 2 sage: _.parent() Integer Ring
::
sage: 4._divide_if_possible(3) Traceback (most recent call last): ... ValueError: 4 is not divisible by 3 """
def _gen_names(elts): r""" Used to find a name for a generator when rings are created using the ``__getitem__`` syntax, e.g. ``ZZ['x']``, ``ZZ[sqrt(2)]``.
EXAMPLES::
sage: from sage.categories.rings import _gen_names sage: list(_gen_names([sqrt(5)])) ['sqrt5'] sage: list(_gen_names([sqrt(-17), 2^(1/3)])) ['a', 'b'] sage: list(_gen_names((1..27)))[-1] 'aa' """ |