Elements#

AUTHORS:

  • David Harvey (2006-10-16): changed CommutativeAlgebraElement to derive from CommutativeRingElement instead of AlgebraElement

  • David Harvey (2006-10-29): implementation and documentation of new arithmetic architecture

  • William Stein (2006-11): arithmetic architecture – pushing it through to completion.

  • Gonzalo Tornaria (2007-06): recursive base extend for coercion – lots of tests

  • Robert Bradshaw (2007-2010): arithmetic operators and coercion

  • Maarten Derickx (2010-07): added architecture for is_square and sqrt

  • Jeroen Demeyer (2016-08): moved all coercion to the base class Element, see github issue #20767

The Abstract Element Class Hierarchy#

This is the abstract class hierarchy, i.e., these are all abstract base classes.

SageObject
    Element
        ModuleElement
            RingElement
                CommutativeRingElement
                    IntegralDomainElement
                        DedekindDomainElement
                            PrincipalIdealDomainElement
                                EuclideanDomainElement
                    FieldElement
                    CommutativeAlgebraElement
                    Expression
                AlgebraElement
                    Matrix
                InfinityElement
            AdditiveGroupElement
            Vector

        MonoidElement
            MultiplicativeGroupElement
    ElementWithCachedMethod

How to Define a New Element Class#

Elements typically define a method _new_c, e.g.,

cdef _new_c(self, defining data):
    cdef FreeModuleElement_generic_dense x
    x = FreeModuleElement_generic_dense.__new__(FreeModuleElement_generic_dense)
    x._parent = self._parent
    x._entries = v

that creates a new sibling very quickly from defining data with assumed properties.

Arithmetic for Elements#

Sage has a special system for handling arithmetic operations on Sage elements (that is instances of Element), in particular to manage uniformly mixed arithmetic operations using the coercion model. We describe here the rules that must be followed by both arithmetic implementers and callers.

A quick summary for the impatient#

To implement addition for any Element subclass, override the def _add_(self, other) method instead of the usual Python __add__ special method. Within _add_(self, other), you may assume that self and other have the same parent.

If the implementation is generic across all elements in a given category \(C\), then this method can be put in C.ElementMethods.

When writing Cython code, _add_ should be a cpdef method: cpdef _add_(self, other).

When doing arithmetic with two elements having different parents, the coercion model is responsible for “coercing” them to a common parent and performing arithmetic on the coerced elements.

Arithmetic in more detail#

The aims of this system are to provide (1) an efficient calling protocol from both Python and Cython, (2) uniform coercion semantics across Sage, (3) ease of use, (4) readability of code.

We will take addition as an example; all other operators are similar. There are two relevant functions, with differing names (single vs. double underscores).

  • def Element.__add__(left, right)

    This function is called by Python or Cython when the binary “+” operator is encountered. It assumes that at least one of its arguments is an Element.

    It has a fast pathway to deal with the most common case where both arguments have the same parent. Otherwise, it uses the coercion model to work out how to make them have the same parent. The coercion model then adds the coerced elements (technically, it calls operator.add). Note that the result of coercion is not required to be a Sage Element, it could be a plain Python type.

    Note that, although this function is declared as def, it doesn’t have the usual overheads associated with Python functions (either for the caller or for __add__ itself). This is because Python has optimised calling protocols for such special functions.

  • def Element._add_(self, other)

    This is the function that you should override to implement addition in a subclass of Element.

    The two arguments to this function are guaranteed to have the same parent, but not necessarily the same Python type.

    When implementing _add_ in a Cython extension type, use cpdef _add_ instead of def _add_.

    In Cython code, if you want to add two elements and you know that their parents are identical, you are encouraged to call this function directly, instead of using x + y. This only works if Cython knows that the left argument is an Element. You can always cast explicitly: (<Element>x)._add_(y) to force this. In plain Python, x + y is always the fastest way to add two elements because the special method __add__ is optimized unlike the normal method _add_.

The difference in the names of the arguments (left, right versus self, other) is intentional: self is guaranteed to be an instance of the class in which the method is defined. In Cython, we know that at least one of left or right is an instance of the class but we do not know a priori which one.

Powering is a special case: first of all, the 3-argument version of pow() is not supported. Second, the coercion model checks whether the exponent looks like an integer. If so, the function _pow_int is called. If the exponent is not an integer, the arguments are coerced to a common parent and _pow_ is called. So, if your type only supports powering to an integer exponent, you should implement only _pow_int. If you want to support arbitrary powering, implement both _pow_ and _pow_int.

For addition, multiplication and powering (not for other operators), there is a fast path for operations with a C long. For example, implement cdef _add_long(self, long n) with optimized code for self + n. The addition and multiplication are assumed to be commutative, so they are also called for n + self or n * self. From Cython code, you can also call _add_long or _mul_long directly. This is strictly an optimization: there is a default implementation falling back to the generic arithmetic function.

Examples#

We need some Parent to work with:

sage: from sage.structure.parent import Parent
sage: class ExampleParent(Parent):
....:     def __init__(self, name, **kwds):
....:         Parent.__init__(self, **kwds)
....:         self.rename(name)

We start with a very basic example of a Python class implementing _add_:

sage: from sage.structure.element import Element
sage: class MyElement(Element):
....:     def _add_(self, other):
....:         return 42
sage: p = ExampleParent("Some parent")
sage: x = MyElement(p)
sage: x + x
42

When two different parents are involved, this no longer works since there is no coercion:

sage: q = ExampleParent("Other parent")
sage: y = MyElement(q)
sage: x + y
Traceback (most recent call last):
...
TypeError: unsupported operand parent(s) for +: 'Some parent' and 'Other parent'

If _add_ is not defined, an error message is raised, referring to the parents:

sage: x = Element(p)
sage: x._add_(x)
Traceback (most recent call last):
...
AttributeError: 'sage.structure.element.Element' object has no attribute '_add_'...
sage: x + x
Traceback (most recent call last):
...
TypeError: unsupported operand parent(s) for +: 'Some parent' and 'Some parent'
sage: y = Element(q)
sage: x + y
Traceback (most recent call last):
...
TypeError: unsupported operand parent(s) for +: 'Some parent' and 'Other parent'

We can also implement arithmetic generically in categories:

sage: class MyCategory(Category):
....:     def super_categories(self):
....:         return [Sets()]
....:     class ElementMethods:
....:         def _add_(self, other):
....:             return 42
sage: p = ExampleParent("Parent in my category", category=MyCategory())
sage: x = Element(p)
sage: x + x
42

Implementation details#

Implementing the above features actually takes a bit of magic. Casual callers and implementers can safely ignore it, but here are the details for the curious.

To achieve fast arithmetic, it is critical to have a fast path in Cython to call the _add_ method of a Cython object. So we would like to declare _add_ as a cpdef method of class Element. Remember however that the abstract classes coming from categories come after Element in the method resolution order (or fake method resolution order in case of a Cython class). Hence any generic implementation of _add_ in such an abstract class would in principle be shadowed by Element._add_. This is worked around by defining Element._add_ as a cdef instead of a cpdef method. Concrete implementations in subclasses should be cpdef or def methods.

Let us now see what happens upon evaluating x + y when x and y are instances of a class that does not implement _add_ but where _add_ is implemented in the category. First, x.__add__(y) is called, where __add__ is implemented in Element. Assuming that x and y have the same parent, a Cython call to x._add_(y) will be done. The latter is implemented to trigger a Python level call to x._add_(y) which will succeed as desired.

In case that Python code calls x._add_(y) directly, Element._add_ will be invisible, and the method lookup will continue down the MRO and find the _add_ method in the category.

class sage.structure.element.AdditiveGroupElement#

Bases: ModuleElement

Generic element of an additive group.

order()#

Return additive order of element

class sage.structure.element.AlgebraElement#

Bases: RingElement

class sage.structure.element.CommutativeAlgebraElement#

Bases: CommutativeRingElement

class sage.structure.element.CommutativeRingElement#

Bases: RingElement

Base class for elements of commutative rings.

divides(x)#

Return True if self divides x.

EXAMPLES:

sage: P.<x> = PolynomialRing(QQ)
sage: x.divides(x^2)
True
sage: x.divides(x^2 + 2)
False
sage: (x^2 + 2).divides(x)
False
sage: P.<x> = PolynomialRing(ZZ)
sage: x.divides(x^2)
True
sage: x.divides(x^2 + 2)
False
sage: (x^2 + 2).divides(x)
False

github issue #5347 has been fixed:

sage: K = GF(7)
sage: K(3).divides(1)
True
sage: K(3).divides(K(1))
True
sage: R = Integers(128)
sage: R(0).divides(1)
False
sage: R(0).divides(0)
True
sage: R(0).divides(R(0))
True
sage: R(1).divides(0)
True
sage: R(121).divides(R(120))
True
sage: R(120).divides(R(121))
False

If x has different parent than self, they are first coerced to a common parent if possible. If this coercion fails, it returns a TypeError. This fixes github issue #5759.

sage: Zmod(2)(0).divides(Zmod(2)(0))
True
sage: Zmod(2)(0).divides(Zmod(2)(1))
False
sage: Zmod(5)(1).divides(Zmod(2)(1))
Traceback (most recent call last):
...
TypeError: no common canonical parent for objects with parents:
'Ring of integers modulo 5' and 'Ring of integers modulo 2'
sage: Zmod(35)(4).divides(Zmod(7)(1))
True
sage: Zmod(35)(7).divides(Zmod(7)(1))
False
inverse_mod(I)#

Return an inverse of self modulo the ideal \(I\), if defined, i.e., if \(I\) and self together generate the unit ideal.

EXAMPLES:

sage: # needs sage.rings.finite_rings
sage: F = GF(25)
sage: x = F.gen()
sage: z = F.zero()
sage: x.inverse_mod(F.ideal(z))
2*z2 + 3
sage: x.inverse_mod(F.ideal(1))
1
sage: z.inverse_mod(F.ideal(1))
1
sage: z.inverse_mod(F.ideal(z))
Traceback (most recent call last):
...
ValueError: an element of a proper ideal does not have an inverse modulo that ideal
is_square(root=False)#

Return whether or not the ring element self is a square.

If the optional argument root is True, then also return the square root (or None, if it is not a square).

INPUT:

  • root - whether or not to also return a square root (default: False)

OUTPUT:

  • bool – whether or not a square

  • object – (optional) an actual square root if found, and None otherwise.

EXAMPLES:

sage: R.<x> = PolynomialRing(QQ)
sage: f = 12*(x+1)^2 * (x+3)^2
sage: f.is_square()
False
sage: f.is_square(root=True)
(False, None)
sage: h = f/3
sage: h.is_square()
True
sage: h.is_square(root=True)
(True, 2*x^2 + 8*x + 6)

Note

This is the is_square implementation for general commutative ring elements. It’s implementation is to raise a NotImplementedError. The function definition is here to show what functionality is expected and provide a general framework.

mod(I)#

Return a representative for self modulo the ideal I (or the ideal generated by the elements of I if I is not an ideal.)

EXAMPLES: Integers Reduction of 5 modulo an ideal:

sage: n = 5
sage: n.mod(3*ZZ)
2

Reduction of 5 modulo the ideal generated by 3:

sage: n.mod(3)
2

Reduction of 5 modulo the ideal generated by 15 and 6, which is \((3)\).

sage: n.mod([15,6])
2

EXAMPLES: Univariate polynomials

sage: R.<x> = PolynomialRing(QQ)
sage: f = x^3 + x + 1
sage: f.mod(x + 1)
-1

Reduction for \(\ZZ[x]\):

sage: R.<x> = PolynomialRing(ZZ)
sage: f = x^3 + x + 1
sage: f.mod(x + 1)
-1

When little is implemented about a given ring, then mod may simply return \(f\).

EXAMPLES: Multivariate polynomials We reduce a polynomial in two variables modulo a polynomial and an ideal:

sage: R.<x,y,z> = PolynomialRing(QQ, 3)
sage: (x^2 + y^2 + z^2).mod(x + y + z)                                      # needs sage.libs.singular
2*y^2 + 2*y*z + 2*z^2

Notice above that \(x\) is eliminated. In the next example, both \(y\) and \(z\) are eliminated:

sage: (x^2 + y^2 + z^2).mod( (x - y, y - z) )                               # needs sage.libs.singular
3*z^2
sage: f = (x^2 + y^2 + z^2)^2; f
x^4 + 2*x^2*y^2 + y^4 + 2*x^2*z^2 + 2*y^2*z^2 + z^4
sage: f.mod( (x - y, y - z) )                                               # needs sage.libs.singular
9*z^4

In this example \(y\) is eliminated:

sage: (x^2 + y^2 + z^2).mod( (x^3, y - z) )                                 # needs sage.libs.singular
x^2 + 2*z^2
sqrt(extend=True, all=False, name=None)#

Compute the square root.

INPUT:

  • extend – boolean (default: True); whether to make a ring

    extension containing a square root if self is not a square

  • all – boolean (default: False); whether to return a list of

    all square roots or just a square root

  • name – required when extend=True and self is not a

    square. This will be the name of the generator of the extension.

OUTPUT:

  • if all=False, a square root; raises an error if extend=False and self is not a square

  • if all=True, a list of all the square roots (empty if extend=False and self is not a square)

ALGORITHM:

It uses is_square(root=true) for the hard part of the work, the rest is just wrapper code.

EXAMPLES:

sage: # needs sage.libs.pari
sage: R.<x> = ZZ[]
sage: (x^2).sqrt()
x
sage: f = x^2 - 4*x + 4; f.sqrt(all=True)
[x - 2, -x + 2]
sage: sqrtx = x.sqrt(name="y"); sqrtx
y
sage: sqrtx^2
x
sage: x.sqrt(all=true, name="y")
[y, -y]
sage: x.sqrt(extend=False, all=True)
[]
sage: x.sqrt()
Traceback (most recent call last):
...
TypeError: Polynomial is not a square. You must specify the name
of the square root when using the default extend = True
sage: x.sqrt(extend=False)
Traceback (most recent call last):
...
ValueError: trying to take square root of non-square x with extend = False
class sage.structure.element.DedekindDomainElement#

Bases: IntegralDomainElement

class sage.structure.element.Element#

Bases: SageObject

Generic element of a structure. All other types of elements (RingElement, ModuleElement, etc) derive from this type.

Subtypes must either call __init__() to set _parent, or may set _parent themselves if that would be more efficient.

_richcmp_(left, right, op)#

Basic default implementation of rich comparisons for elements with equal parents.

It does a comparison by id for == and !=. Calling this default method with <, <=, > or >= will return NotImplemented.

EXAMPLES:

sage: from sage.structure.parent import Parent
sage: from sage.structure.element import Element
sage: P = Parent()
sage: e1 = Element(P); e2 = Element(P)
sage: e1 == e1    # indirect doctest
True
sage: e1 == e2    # indirect doctest
False
sage: e1 < e2     # indirect doctest
Traceback (most recent call last):
...
TypeError: '<' not supported between instances of 'sage.structure.element.Element' and 'sage.structure.element.Element'

We now create an Element class where we define _richcmp_ and check that comparison works:

sage: # needs sage.misc.cython
sage: cython(
....: '''
....: from sage.structure.richcmp cimport rich_to_bool
....: from sage.structure.element cimport Element
....: cdef class FloatCmp(Element):
....:     cdef float x
....:     def __init__(self, float v):
....:         self.x = v
....:     cpdef _richcmp_(self, other, int op):
....:         cdef float x1 = (<FloatCmp>self).x
....:         cdef float x2 = (<FloatCmp>other).x
....:         return rich_to_bool(op, (x1 > x2) - (x1 < x2))
....: ''')
sage: a = FloatCmp(1)
sage: b = FloatCmp(2)
sage: a <= b, b <= a
(True, False)
__add__(left, right)#

Top-level addition operator for Element invoking the coercion model.

See Arithmetic for Elements.

EXAMPLES:

sage: from sage.structure.element import Element
sage: class MyElement(Element):
....:     def _add_(self, other):
....:         return 42
sage: e = MyElement(Parent())
sage: e + e
42
__sub__(left, right)#

Top-level subtraction operator for Element invoking the coercion model.

See Arithmetic for Elements.

EXAMPLES:

sage: from sage.structure.element import Element
sage: class MyElement(Element):
....:     def _sub_(self, other):
....:         return 42
sage: e = MyElement(Parent())
sage: e - e
42
__neg__()#

Top-level negation operator for Element.

EXAMPLES:

sage: from sage.structure.element import Element
sage: class MyElement(Element):
....:     def _neg_(self):
....:         return 42
sage: e = MyElement(Parent())
sage: -e
42
__mul__(left, right)#

Top-level multiplication operator for Element invoking the coercion model.

See Arithmetic for Elements.

EXAMPLES:

sage: from sage.structure.element import Element
sage: class MyElement(Element):
....:     def _mul_(self, other):
....:         return 42
sage: e = MyElement(Parent())
sage: e * e
42
__truediv__(left, right)#

Top-level true division operator for Element invoking the coercion model.

See Arithmetic for Elements.

EXAMPLES:

sage: operator.truediv(2, 3)
2/3
sage: operator.truediv(pi, 3)                                               # needs sage.symbolic
1/3*pi
sage: x = polygen(QQ, 'x')
sage: K.<i> = NumberField(x^2 + 1)                                          # needs sage.rings.number_field
sage: operator.truediv(2, K.ideal(i + 1))                                   # needs sage.rings.number_field
Fractional ideal (-i + 1)
sage: from sage.structure.element import Element
sage: class MyElement(Element):
....:     def _div_(self, other):
....:         return 42
sage: e = MyElement(Parent())
sage: operator.truediv(e, e)
42
__floordiv__(left, right)#

Top-level floor division operator for Element invoking the coercion model.

See Arithmetic for Elements.

EXAMPLES:

sage: 7 // 3
2
sage: 7 // int(3)
2
sage: int(7) // 3
2
sage: from sage.structure.element import Element
sage: class MyElement(Element):
....:     def _floordiv_(self, other):
....:         return 42
sage: e = MyElement(Parent())
sage: e // e
42
__mod__(left, right)#

Top-level modulo operator for Element invoking the coercion model.

See Arithmetic for Elements.

EXAMPLES:

sage: 7 % 3
1
sage: 7 % int(3)
1
sage: int(7) % 3
1
sage: from sage.structure.element import Element
sage: class MyElement(Element):
....:     def _mod_(self, other):
....:         return 42
sage: e = MyElement(Parent())
sage: e % e
42
base_extend(R)#
base_ring()#

Return the base ring of this element’s parent (if that makes sense).

category()#
is_zero()#

Return True if self equals self.parent()(0).

The default implementation is to fall back to not self.__bool__.

Warning

Do not re-implement this method in your subclass but implement __bool__ instead.

n(prec=None, digits=None, algorithm=None)#

Alias for numerical_approx().

EXAMPLES:

sage: (2/3).n()                                                             # needs sage.rings.real_mpfr
0.666666666666667
numerical_approx(prec=None, digits=None, algorithm=None)#

Return a numerical approximation of self with prec bits (or decimal digits) of precision.

No guarantee is made about the accuracy of the result.

INPUT:

  • prec – precision in bits

  • digits – precision in decimal digits (only used if prec is not given)

  • algorithm – which algorithm to use to compute this approximation (the accepted algorithms depend on the object)

If neither prec nor digits is given, the default precision is 53 bits (roughly 16 digits).

EXAMPLES:

sage: (2/3).numerical_approx()                                              # needs sage.rings.real_mpfr
0.666666666666667
sage: pi.n(digits=10)                                                       # needs sage.symbolic
3.141592654
sage: pi.n(prec=20)                                                         # needs sage.symbolic
3.1416
parent(x=None)#

Return the parent of this element; or, if the optional argument x is supplied, the result of coercing x into the parent of this element.

subs(in_dict=None, **kwds)#

Substitutes given generators with given values while not touching other generators. This is a generic wrapper around __call__. The syntax is meant to be compatible with the corresponding method for symbolic expressions.

INPUT:

  • in_dict - (optional) dictionary of inputs

  • **kwds - named parameters

OUTPUT:

  • new object if substitution is possible, otherwise self.

EXAMPLES:

sage: x, y = PolynomialRing(ZZ,2,'xy').gens()
sage: f = x^2 + y + x^2*y^2 + 5
sage: f((5,y))
25*y^2 + y + 30
sage: f.subs({x:5})
25*y^2 + y + 30
sage: f.subs(x=5)
25*y^2 + y + 30
sage: (1/f).subs(x=5)
1/(25*y^2 + y + 30)
sage: Integer(5).subs(x=4)
5
substitute(in_dict=None, **kwds)#

This is an alias for self.subs().

INPUT:

  • in_dict - (optional) dictionary of inputs

  • **kwds - named parameters

OUTPUT:

  • new object if substitution is possible, otherwise self.

EXAMPLES:

sage: x, y = PolynomialRing(ZZ, 2, 'xy').gens()
sage: f = x^2 + y + x^2*y^2 + 5
sage: f((5,y))
25*y^2 + y + 30
sage: f.substitute({x: 5})
25*y^2 + y + 30
sage: f.substitute(x=5)
25*y^2 + y + 30
sage: (1/f).substitute(x=5)
1/(25*y^2 + y + 30)
sage: Integer(5).substitute(x=4)
5
class sage.structure.element.ElementWithCachedMethod#

Bases: Element

An element class that fully supports cached methods.

NOTE:

The cached_method decorator provides a convenient way to automatically cache the result of a computation. Since github issue #11115, the cached method decorator applied to a method without optional arguments is faster than a hand-written cache in Python, and a cached method without any arguments (except self) is actually faster than a Python method that does nothing more but to return 1. A cached method can also be inherited from the parent or element class of a category.

However, this holds true only if attribute assignment is supported. If you write an extension class in Cython that does not accept attribute assignment then a cached method inherited from the category will be slower (for Parent) or the cache would even break (for Element).

This class should be used if you write an element class, cannot provide it with attribute assignment, but want that it inherits a cached method from the category. Under these conditions, your class should inherit from this class rather than Element. Then, the cache will work, but certainly slower than with attribute assignment. Lazy attributes work as well.

EXAMPLES:

We define three element extension classes. The first inherits from Element, the second from this class, and the third simply is a Python class. We also define a parent class and, in Python, a category whose element and parent classes define cached methods.

sage: # needs sage.misc.cython
sage: cython_code = ["from sage.structure.element cimport Element, ElementWithCachedMethod",
....:     "from sage.structure.richcmp cimport richcmp",
....:     "cdef class MyBrokenElement(Element):",
....:     "    cdef public object x",
....:     "    def __init__(self, P, x):",
....:     "        self.x = x",
....:     "        Element.__init__(self, P)",
....:     "    def __neg__(self):",
....:     "        return MyBrokenElement(self.parent(), -self.x)",
....:     "    def _repr_(self):",
....:     "        return '<%s>' % self.x",
....:     "    def __hash__(self):",
....:     "        return hash(self.x)",
....:     "    cpdef _richcmp_(left, right, int op):",
....:     "        return richcmp(left.x, right.x, op)",
....:     "    def raw_test(self):",
....:     "        return -self",
....:     "cdef class MyElement(ElementWithCachedMethod):",
....:     "    cdef public object x",
....:     "    def __init__(self, P, x):",
....:     "        self.x = x",
....:     "        Element.__init__(self, P)",
....:     "    def __neg__(self):",
....:     "        return MyElement(self.parent(), -self.x)",
....:     "    def _repr_(self):",
....:     "        return '<%s>' % self.x",
....:     "    def __hash__(self):",
....:     "        return hash(self.x)",
....:     "    cpdef _richcmp_(left, right, int op):",
....:     "        return richcmp(left.x, right.x, op)",
....:     "    def raw_test(self):",
....:     "        return -self",
....:     "class MyPythonElement(MyBrokenElement): pass",
....:     "from sage.structure.parent cimport Parent",
....:     "cdef class MyParent(Parent):",
....:     "    Element = MyElement"]
sage: cython('\n'.join(cython_code))
sage: cython_code = ["from sage.misc.cachefunc import cached_method",
....:     "from sage.misc.cachefunc import cached_in_parent_method",
....:     "from sage.categories.category import Category",
....:     "from sage.categories.objects import Objects",
....:     "class MyCategory(Category):",
....:     "    @cached_method",
....:     "    def super_categories(self):",
....:     "        return [Objects()]",
....:     "    class ElementMethods:",
....:     "        @cached_method",
....:     "        def element_cache_test(self):",
....:     "            return -self",
....:     "        @cached_in_parent_method",
....:     "        def element_via_parent_test(self):",
....:     "            return -self",
....:     "    class ParentMethods:",
....:     "        @cached_method",
....:     "        def one(self):",
....:     "            return self.element_class(self,1)",
....:     "        @cached_method",
....:     "        def invert(self, x):",
....:     "            return -x"]
sage: cython('\n'.join(cython_code))
sage: C = MyCategory()
sage: P = MyParent(category=C)
sage: ebroken = MyBrokenElement(P, 5)
sage: e = MyElement(P, 5)

The cached methods inherited by MyElement works:

sage: # needs sage.misc.cython
sage: e.element_cache_test()
<-5>
sage: e.element_cache_test() is e.element_cache_test()
True
sage: e.element_via_parent_test()
<-5>
sage: e.element_via_parent_test() is e.element_via_parent_test()
True

The other element class can only inherit a cached_in_parent_method, since the cache is stored in the parent. In fact, equal elements share the cache, even if they are of different types:

sage: e == ebroken                                                              # needs sage.misc.cython
True
sage: type(e) == type(ebroken)                                                  # needs sage.misc.cython
False
sage: ebroken.element_via_parent_test() is e.element_via_parent_test()          # needs sage.misc.cython
True

However, the cache of the other inherited method breaks, although the method as such works:

sage: ebroken.element_cache_test()                                              # needs sage.misc.cython
<-5>
sage: ebroken.element_cache_test() is ebroken.element_cache_test()              # needs sage.misc.cython
False

Since e and ebroken share the cache, when we empty it for one element it is empty for the other as well:

sage: b = ebroken.element_via_parent_test()                                     # needs sage.misc.cython
sage: e.element_via_parent_test.clear_cache()                                   # needs sage.misc.cython
sage: b is ebroken.element_via_parent_test()                                    # needs sage.misc.cython
False

Note that the cache only breaks for elements that do no allow attribute assignment. A Python version of MyBrokenElement therefore allows for cached methods:

sage: epython = MyPythonElement(P, 5)                                           # needs sage.misc.cython
sage: epython.element_cache_test()                                              # needs sage.misc.cython
<-5>
sage: epython.element_cache_test() is epython.element_cache_test()              # needs sage.misc.cython
True
class sage.structure.element.EuclideanDomainElement#

Bases: PrincipalIdealDomainElement

degree()#
leading_coefficient()#
quo_rem(other)#
class sage.structure.element.Expression#

Bases: CommutativeRingElement

Abstract base class for Expression.

This class is defined for the purpose of isinstance() tests. It should not be instantiated.

EXAMPLES:

sage: isinstance(SR.var('y'), sage.structure.element.Expression)                # needs sage.symbolic
True

By design, there is a unique direct subclass:

sage: len(sage.structure.element.Expression.__subclasses__()) <= 1
True
class sage.structure.element.FieldElement#

Bases: CommutativeRingElement

divides(other)#

Check whether self divides other, for field elements.

Since this is a field, all values divide all other values, except that zero does not divide any non-zero values.

EXAMPLES:

sage: # needs sage.rings.number_field sage.symbolic
sage: K.<rt3> = QQ[sqrt(3)]
sage: K(0).divides(rt3)
False
sage: rt3.divides(K(17))
True
sage: K(0).divides(K(0))
True
sage: rt3.divides(K(0))
True
is_unit()#

Return True if self is a unit in its parent ring.

EXAMPLES:

sage: a = 2/3; a.is_unit()
True

On the other hand, 2 is not a unit, since its parent is \(\ZZ\).

sage: a = 2; a.is_unit()
False
sage: parent(a)
Integer Ring

However, a is a unit when viewed as an element of QQ:

sage: a = QQ(2); a.is_unit()
True
quo_rem(right)#

Return the quotient and remainder obtained by dividing self by right. Since this element lives in a field, the remainder is always zero and the quotient is self/right.

class sage.structure.element.InfinityElement#

Bases: RingElement

class sage.structure.element.IntegralDomainElement#

Bases: CommutativeRingElement

is_nilpotent()#
class sage.structure.element.Matrix#

Bases: ModuleElement

class sage.structure.element.ModuleElement#

Bases: Element

Generic element of a module.

additive_order()#

Return the additive order of self.

order()#

Return the additive order of self.

class sage.structure.element.ModuleElementWithMutability#

Bases: ModuleElement

Generic element of a module with mutability.

is_immutable()#

Return True if this vector is immutable, i.e., the entries cannot be changed.

EXAMPLES:

sage: v = vector(QQ['x,y'], [1..5]); v.is_immutable()                       # needs sage.modules
False
sage: v.set_immutable()                                                     # needs sage.modules
sage: v.is_immutable()                                                      # needs sage.modules
True
is_mutable()#

Return True if this vector is mutable, i.e., the entries can be changed.

EXAMPLES:

sage: v = vector(QQ['x,y'], [1..5]); v.is_mutable()                         # needs sage.modules
True
sage: v.set_immutable()                                                     # needs sage.modules
sage: v.is_mutable()                                                        # needs sage.modules
False
set_immutable()#

Make this vector immutable. This operation can’t be undone.

EXAMPLES:

sage: # needs sage.modules
sage: v = vector([1..5]); v
(1, 2, 3, 4, 5)
sage: v[1] = 10
sage: v.set_immutable()
sage: v[1] = 10
Traceback (most recent call last):
...
ValueError: vector is immutable; please change a copy instead (use copy())
class sage.structure.element.MonoidElement#

Bases: Element

Generic element of a monoid.

multiplicative_order()#

Return the multiplicative order of self.

order()#

Return the multiplicative order of self.

powers(n)#

Return the list \([x^0, x^1, \ldots, x^{n-1}]\).

EXAMPLES:

sage: G = SymmetricGroup(4)                                                 # needs sage.groups
sage: g = G([2, 3, 4, 1])                                                   # needs sage.groups
sage: g.powers(4)                                                           # needs sage.groups
[(), (1,2,3,4), (1,3)(2,4), (1,4,3,2)]
class sage.structure.element.MultiplicativeGroupElement#

Bases: MonoidElement

Generic element of a multiplicative group.

order()#

Return the multiplicative order of self.

class sage.structure.element.PrincipalIdealDomainElement#

Bases: DedekindDomainElement

gcd(right)#

Return the greatest common divisor of self and other.

lcm(right)#

Return the least common multiple of self and right.

class sage.structure.element.RingElement#

Bases: ModuleElement

abs()#

Return the absolute value of self. (This just calls the __abs__ method, so it is equivalent to the abs() built-in function.)

EXAMPLES:

sage: RR(-1).abs()
1.00000000000000
sage: ZZ(-1).abs()
1
sage: CC(I).abs()
1.00000000000000
sage: Mod(-15, 37).abs()
Traceback (most recent call last):
...
ArithmeticError: absolute value not defined on integers modulo n.
additive_order()#

Return the additive order of self.

is_nilpotent()#

Return True if self is nilpotent, i.e., some power of self is 0.

is_one()#
is_prime()#

Is self a prime element?

A prime element is a non-zero, non-unit element \(p\) such that, whenever \(p\) divides \(ab\) for some \(a\) and \(b\), then \(p\) divides \(a\) or \(p\) divides \(b\).

EXAMPLES:

For polynomial rings, prime is the same as irreducible:

sage: # needs sage.libs.singular
sage: R.<x,y> = QQ[]
sage: x.is_prime()
True
sage: (x^2 + y^3).is_prime()
True
sage: (x^2 - y^2).is_prime()
False
sage: R(0).is_prime()
False
sage: R(2).is_prime()
False

For the Gaussian integers:

sage: # needs sage.rings.number_field
sage: K.<i> = QuadraticField(-1)
sage: ZI = K.ring_of_integers()
sage: ZI(3).is_prime()
True
sage: ZI(5).is_prime()
False
sage: ZI(2 + i).is_prime()
True
sage: ZI(0).is_prime()
False
sage: ZI(1).is_prime()
False

In fields, an element is never prime:

sage: RR(0).is_prime()
False
sage: RR(2).is_prime()
False

For integers, is_prime() redefines prime numbers to be positive:

sage: (-2).is_prime()
False
sage: RingElement.is_prime(-2)                                              # needs sage.libs.pari
True

Similarly, NumberField redefines is_prime() to determine primality in the ring of integers:

sage: # needs sage.rings.number_field
sage: (1 + i).is_prime()
True
sage: K(5).is_prime()
False
sage: K(7).is_prime()
True
sage: K(7/13).is_prime()
False

However, for rationals, is_prime() does follow the general definition of prime elements in a ring (i.e., always returns False) since the rationals are not a NumberField in Sage:

sage: QQ(7).is_prime()
False
multiplicative_order()#

Return the multiplicative order of self, if self is a unit, or raise ArithmeticError otherwise.

powers(n)#

Return the list \([x^0, x^1, \ldots, x^{n-1}]\).

EXAMPLES:

sage: 5.powers(3)
[1, 5, 25]
class sage.structure.element.Vector#

Bases: ModuleElementWithMutability

sage.structure.element.bin_op(x, y, op)#
sage.structure.element.canonical_coercion(x, y)#

canonical_coercion(x,y) is what is called before doing an arithmetic operation between x and y. It returns a pair (z,w) such that z is got from x and w from y via canonical coercion and the parents of z and w are identical.

EXAMPLES:

sage: A = Matrix([[0, 1], [1, 0]])                                              # needs sage.modules
sage: canonical_coercion(A, 1)                                                  # needs sage.modules
(
[0 1]  [1 0]
[1 0], [0 1]
)
sage.structure.element.coerce_binop(method)#

Decorator for a binary operator method for applying coercion to the arguments before calling the method.

Consider a parent class in the category framework, \(S\), whose element class expose a method \(binop\). If \(a\) and \(b\) are elements of \(S\), then \(a.binop(b)\) behaves as expected. If \(a\) and \(b\) are not elements of \(S\), but rather have a common parent \(T\) whose element class also exposes \(binop\), we would rather expect \(a.binop(b)\) to compute \(aa.binop(bb)\), where \(aa = T(a)\) and \(bb = T(b)\). This decorator ensures that behaviour without having to otherwise modify the implementation of \(binop\) on the element class of \(A\).

Since coercion will be attempted on the arguments of the decorated method, a \(TypeError\) will be thrown if there is no common parent between the elements. An \(AttributeError\) or \(NotImplementedError\) or similar will be thrown if there is a common parent of the arguments, but its element class does not implement a method of the same name as the decorated method.

EXAMPLES:

Sparse polynomial rings uses \(@coerce_binop\) on \(gcd\):

sage: S.<x> = PolynomialRing(ZZ, sparse=True)
sage: f = x^2
sage: g = x
sage: f.gcd(g)  #indirect doctest
x
sage: T = PolynomialRing(QQ, name='x', sparse=True)
sage: h = 1/2*T(x)
sage: u = f.gcd(h); u  #indirect doctest
x
sage: u.parent() == T
True

Another real example:

sage: R1 = QQ['x,y']
sage: R2 = QQ['x,y,z']
sage: f = R1(1)
sage: g = R1(2)
sage: h = R2(1)
sage: f.gcd(g)
1
sage: f.gcd(g, algorithm='modular')
1
sage: f.gcd(h)
1
sage: f.gcd(h, algorithm='modular')
1
sage: h.gcd(f)
1
sage: h.gcd(f, 'modular')
1

We demonstrate a small class using \(@coerce_binop\) on a method:

sage: from sage.structure.element import coerce_binop
sage: class MyRational(Rational):
....:     def __init__(self,value):
....:         self.v = value
....:     @coerce_binop
....:     def test_add(self, other, keyword='z'):
....:         return (self.v, other, keyword)

Calls func directly if the two arguments have the same parent:

sage: x = MyRational(1)
sage: x.test_add(1/2)
(1, 1/2, 'z')
sage: x.test_add(1/2, keyword=3)
(1, 1/2, 3)

Passes through coercion and does a method lookup if the left operand is not the same. If the common parent’s element class does not have a method of the same name, an exception is raised:

sage: x.test_add(2)
(1, 2, 'z')
sage: x.test_add(2, keyword=3)
(1, 2, 3)
sage: x.test_add(CC(2))
Traceback (most recent call last):
...
AttributeError: 'sage.rings.complex_mpfr.ComplexNumber' object has no attribute 'test_add'...
sage.structure.element.coercion_traceback(dump=True)#

This function is very helpful in debugging coercion errors. It prints the tracebacks of all the errors caught in the coercion detection. Note that failure is cached, so some errors may be omitted the second time around (as it remembers not to retry failed paths for speed reasons.

For performance and caching reasons, exception recording must be explicitly enabled before using this function.

EXAMPLES:

sage: cm = sage.structure.element.get_coercion_model()
sage: cm.record_exceptions()
sage: 1 + 1/5
6/5
sage: coercion_traceback()  # Should be empty, as all went well.
sage: 1/5 + GF(5).gen()
Traceback (most recent call last):
...
TypeError: unsupported operand parent(s) for +:
'Rational Field' and 'Finite Field of size 5'
sage: coercion_traceback()
Traceback (most recent call last):
...
TypeError: no common canonical parent for objects with parents:
'Rational Field' and 'Finite Field of size 5'
sage.structure.element.get_coercion_model()#

Return the global coercion model.

EXAMPLES:

sage: import sage.structure.element as e
sage: cm = e.get_coercion_model()
sage: cm
<sage.structure.coerce.CoercionModel object at ...>
sage: cm is coercion_model
True
sage.structure.element.have_same_parent(left, right)#

Return True if and only if left and right have the same parent.

Warning

This function assumes that at least one of the arguments is a Sage Element. When in doubt, use the slower parent(left) is parent(right) instead.

EXAMPLES:

sage: from sage.structure.element import have_same_parent
sage: have_same_parent(1, 3)
True
sage: have_same_parent(1, 1/2)
False
sage: have_same_parent(gap(1), gap(1/2))                                        # needs sage.libs.gap
True

These have different types but the same parent:

sage: a = RLF(2)
sage: b = exp(a)
sage: type(a)
<... 'sage.rings.real_lazy.LazyWrapper'>
sage: type(b)
<... 'sage.rings.real_lazy.LazyNamedUnop'>
sage: have_same_parent(a, b)
True
sage.structure.element.is_AdditiveGroupElement(x)#

Return True if x is of type AdditiveGroupElement.

sage.structure.element.is_AlgebraElement(x)#

Return True if x is of type AlgebraElement.

sage.structure.element.is_CommutativeAlgebraElement(x)#

Return True if x is of type CommutativeAlgebraElement.

sage.structure.element.is_CommutativeRingElement(x)#

Return True if x is of type CommutativeRingElement.

sage.structure.element.is_DedekindDomainElement(x)#

Return True if x is of type DedekindDomainElement.

sage.structure.element.is_Element(x)#

Return True if x is of type Element.

EXAMPLES:

sage: from sage.structure.element import is_Element
sage: is_Element(2/3)
True
sage: is_Element(QQ^3)                                                          # needs sage.modules
False
sage.structure.element.is_EuclideanDomainElement(x)#

Return True if x is of type EuclideanDomainElement.

sage.structure.element.is_FieldElement(x)#

Return True if x is of type FieldElement.

sage.structure.element.is_InfinityElement(x)#

Return True if x is of type InfinityElement.

sage.structure.element.is_IntegralDomainElement(x)#

Return True if x is of type IntegralDomainElement.

sage.structure.element.is_Matrix(x)#
sage.structure.element.is_ModuleElement(x)#

Return True if x is of type ModuleElement.

This is even faster than using isinstance inline.

EXAMPLES:

sage: from sage.structure.element import is_ModuleElement
sage: is_ModuleElement(2/3)
True
sage: is_ModuleElement((QQ^3).0)                                                # needs sage.modules
True
sage: is_ModuleElement('a')
False
sage.structure.element.is_MonoidElement(x)#

Return True if x is of type MonoidElement.

sage.structure.element.is_MultiplicativeGroupElement(x)#

Return True if x is of type MultiplicativeGroupElement.

sage.structure.element.is_PrincipalIdealDomainElement(x)#

Return True if x is of type PrincipalIdealDomainElement.

sage.structure.element.is_RingElement(x)#

Return True if x is of type RingElement.

sage.structure.element.is_Vector(x)#
sage.structure.element.make_element(_class, _dict, parent)#

This function is only here to support old pickles.

Pickling functionality is moved to Element.{__getstate__,__setstate__} functions.

sage.structure.element.parent(x)#

Return the parent of the element x.

Usually, this means the mathematical object of which x is an element.

INPUT:

  • x – an element

OUTPUT:

  • If x is a Sage Element, return x.parent().

  • Otherwise, return type(x).

See also

Parents, Conversion and Coercion Section in the Sage Tutorial

EXAMPLES:

sage: a = 42
sage: parent(a)
Integer Ring
sage: b = 42/1
sage: parent(b)
Rational Field
sage: c = 42.0
sage: parent(c)                                                                 # needs sage.rings.real_mpfr
Real Field with 53 bits of precision

Some more complicated examples:

sage: x = Partition([3,2,1,1,1])                                                # needs sage.combinat
sage: parent(x)                                                                 # needs sage.combinat
Partitions
sage: v = vector(RDF, [1,2,3])                                                  # needs sage.modules
sage: parent(v)                                                                 # needs sage.modules
Vector space of dimension 3 over Real Double Field

The following are not considered to be elements, so the type is returned:

sage: d = int(42)  # Python int
sage: parent(d)
<... 'int'>
sage: L = list(range(10))
sage: parent(L)
<... 'list'>