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 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 SageElement
, 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, usecpdef _add_
instead ofdef _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 anElement
. 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)
>>> from sage.all import *
>>> from sage.structure.parent import Parent
>>> 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
>>> from sage.all import *
>>> from sage.structure.element import Element
>>> class MyElement(Element):
... def _add_(self, other):
... return Integer(42)
>>> p = ExampleParent("Some parent")
>>> x = MyElement(p)
>>> 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'
>>> from sage.all import *
>>> q = ExampleParent("Other parent")
>>> y = MyElement(q)
>>> 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'
>>> from sage.all import *
>>> x = Element(p)
>>> x._add_(x)
Traceback (most recent call last):
...
AttributeError: 'sage.structure.element.Element' object has no attribute '_add_'...
>>> x + x
Traceback (most recent call last):
...
TypeError: unsupported operand parent(s) for +: 'Some parent' and 'Some parent'
>>> y = Element(q)
>>> 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
>>> from sage.all import *
>>> class MyCategory(Category):
... def super_categories(self):
... return [Sets()]
... class ElementMethods:
... def _add_(self, other):
... return Integer(42)
>>> p = ExampleParent("Parent in my category", category=MyCategory())
>>> x = Element(p)
>>> 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[source]¶
Bases:
ModuleElement
Generic element of an additive group.
- class sage.structure.element.AlgebraElement[source]¶
Bases:
RingElement
- class sage.structure.element.CommutativeAlgebraElement[source]¶
Bases:
CommutativeRingElement
- class sage.structure.element.CommutativeRingElement[source]¶
Bases:
RingElement
Base class for elements of commutative rings.
- divides(x)[source]¶
Return
True
ifself
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
>>> from sage.all import * >>> P = PolynomialRing(QQ, names=('x',)); (x,) = P._first_ngens(1) >>> x.divides(x**Integer(2)) True >>> x.divides(x**Integer(2) + Integer(2)) False >>> (x**Integer(2) + Integer(2)).divides(x) False >>> P = PolynomialRing(ZZ, names=('x',)); (x,) = P._first_ngens(1) >>> x.divides(x**Integer(2)) True >>> x.divides(x**Integer(2) + Integer(2)) False >>> (x**Integer(2) + Integer(2)).divides(x) False
Issue #5347 has been fixed:
sage: K = GF(7) sage: K(3).divides(1) True sage: K(3).divides(K(1)) True
>>> from sage.all import * >>> K = GF(Integer(7)) >>> K(Integer(3)).divides(Integer(1)) True >>> K(Integer(3)).divides(K(Integer(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
>>> from sage.all import * >>> R = Integers(Integer(128)) >>> R(Integer(0)).divides(Integer(1)) False >>> R(Integer(0)).divides(Integer(0)) True >>> R(Integer(0)).divides(R(Integer(0))) True >>> R(Integer(1)).divides(Integer(0)) True >>> R(Integer(121)).divides(R(Integer(120))) True >>> R(Integer(120)).divides(R(Integer(121))) False
If
x
has different parent thanself
, they are first coerced to a common parent if possible. If this coercion fails, it returns aTypeError
. This fixes 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
>>> from sage.all import * >>> Zmod(Integer(2))(Integer(0)).divides(Zmod(Integer(2))(Integer(0))) True >>> Zmod(Integer(2))(Integer(0)).divides(Zmod(Integer(2))(Integer(1))) False >>> Zmod(Integer(5))(Integer(1)).divides(Zmod(Integer(2))(Integer(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' >>> Zmod(Integer(35))(Integer(4)).divides(Zmod(Integer(7))(Integer(1))) True >>> Zmod(Integer(35))(Integer(7)).divides(Zmod(Integer(7))(Integer(1))) False
- inverse_mod(I)[source]¶
Return an inverse of
self
modulo the ideal \(I\), if defined, i.e., if \(I\) andself
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
>>> from sage.all import * >>> # needs sage.rings.finite_rings >>> F = GF(Integer(25)) >>> x = F.gen() >>> z = F.zero() >>> x.inverse_mod(F.ideal(z)) 2*z2 + 3 >>> x.inverse_mod(F.ideal(Integer(1))) 1 >>> z.inverse_mod(F.ideal(Integer(1))) 1 >>> 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)[source]¶
Return whether or not the ring element
self
is a square.If the optional argument root is
True
, then also return the square root (orNone
, if it is not a square).INPUT:
root
– boolean (default:False
); whether or not to also return a square root
OUTPUT:
boolean; 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)
>>> from sage.all import * >>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1) >>> f = Integer(12)*(x+Integer(1))**Integer(2) * (x+Integer(3))**Integer(2) >>> f.is_square() False >>> f.is_square(root=True) (False, None) >>> h = f/Integer(3) >>> h.is_square() True >>> 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)[source]¶
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
>>> from sage.all import * >>> n = Integer(5) >>> n.mod(Integer(3)*ZZ) 2
Reduction of 5 modulo the ideal generated by 3:
sage: n.mod(3) 2
>>> from sage.all import * >>> n.mod(Integer(3)) 2
Reduction of 5 modulo the ideal generated by 15 and 6, which is \((3)\).
sage: n.mod([15,6]) 2
>>> from sage.all import * >>> n.mod([Integer(15),Integer(6)]) 2
EXAMPLES: Univariate polynomials
sage: R.<x> = PolynomialRing(QQ) sage: f = x^3 + x + 1 sage: f.mod(x + 1) -1
>>> from sage.all import * >>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1) >>> f = x**Integer(3) + x + Integer(1) >>> f.mod(x + Integer(1)) -1
Reduction for \(\ZZ[x]\):
sage: R.<x> = PolynomialRing(ZZ) sage: f = x^3 + x + 1 sage: f.mod(x + 1) -1
>>> from sage.all import * >>> R = PolynomialRing(ZZ, names=('x',)); (x,) = R._first_ngens(1) >>> f = x**Integer(3) + x + Integer(1) >>> f.mod(x + Integer(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
>>> from sage.all import * >>> R = PolynomialRing(QQ, Integer(3), names=('x', 'y', 'z',)); (x, y, z,) = R._first_ngens(3) >>> (x**Integer(2) + y**Integer(2) + z**Integer(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
>>> from sage.all import * >>> (x**Integer(2) + y**Integer(2) + z**Integer(2)).mod( (x - y, y - z) ) # needs sage.libs.singular 3*z^2 >>> f = (x**Integer(2) + y**Integer(2) + z**Integer(2))**Integer(2); f x^4 + 2*x^2*y^2 + y^4 + 2*x^2*z^2 + 2*y^2*z^2 + z^4 >>> 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
>>> from sage.all import * >>> (x**Integer(2) + y**Integer(2) + z**Integer(2)).mod( (x**Integer(3), y - z) ) # needs sage.libs.singular x^2 + 2*z^2
- sqrt(extend=True, all=False, name=None)[source]¶
Compute the square root.
INPUT:
extend
– boolean (default:True
); whether to make a ring extension containing a square root ifself
is not a squareall
– boolean (default:False
); whether to return a list of all square roots or just a square rootname
– required whenextend=True
andself
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 ifextend=False
andself
is not a squareif
all=True
, a list of all the square roots (empty ifextend=False
andself
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
>>> from sage.all import * >>> # needs sage.libs.pari >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> (x**Integer(2)).sqrt() x >>> f = x**Integer(2) - Integer(4)*x + Integer(4); f.sqrt(all=True) [x - 2, -x + 2] >>> sqrtx = x.sqrt(name='y'); sqrtx y >>> sqrtx**Integer(2) x >>> x.sqrt(all=true, name='y') [y, -y] >>> x.sqrt(extend=False, all=True) [] >>> 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 >>> 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[source]¶
Bases:
IntegralDomainElement
- class sage.structure.element.Element[source]¶
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)[source]¶
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 returnNotImplemented
.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'
>>> from sage.all import * >>> from sage.structure.parent import Parent >>> from sage.structure.element import Element >>> P = Parent() >>> e1 = Element(P); e2 = Element(P) >>> e1 == e1 # indirect doctest True >>> e1 == e2 # indirect doctest False >>> 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)
>>> from sage.all import * >>> # needs sage.misc.cython >>> 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)) ... ''') >>> a = FloatCmp(Integer(1)) >>> b = FloatCmp(Integer(2)) >>> a <= b, b <= a (True, False)
- __add__(left, right)[source]¶
Top-level addition operator for
Element
invoking the coercion model.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
>>> from sage.all import * >>> from sage.structure.element import Element >>> class MyElement(Element): ... def _add_(self, other): ... return Integer(42) >>> e = MyElement(Parent()) >>> e + e 42
- __sub__(left, right)[source]¶
Top-level subtraction operator for
Element
invoking the coercion model.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
>>> from sage.all import * >>> from sage.structure.element import Element >>> class MyElement(Element): ... def _sub_(self, other): ... return Integer(42) >>> e = MyElement(Parent()) >>> e - e 42
- __neg__()[source]¶
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
>>> from sage.all import * >>> from sage.structure.element import Element >>> class MyElement(Element): ... def _neg_(self): ... return Integer(42) >>> e = MyElement(Parent()) >>> -e 42
- __mul__(left, right)[source]¶
Top-level multiplication operator for
Element
invoking the coercion model.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
>>> from sage.all import * >>> from sage.structure.element import Element >>> class MyElement(Element): ... def _mul_(self, other): ... return Integer(42) >>> e = MyElement(Parent()) >>> e * e 42
- __truediv__(left, right)[source]¶
Top-level true division operator for
Element
invoking the coercion model.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)
>>> from sage.all import * >>> operator.truediv(Integer(2), Integer(3)) 2/3 >>> operator.truediv(pi, Integer(3)) # needs sage.symbolic 1/3*pi >>> x = polygen(QQ, 'x') >>> K = NumberField(x**Integer(2) + Integer(1), names=('i',)); (i,) = K._first_ngens(1)# needs sage.rings.number_field >>> operator.truediv(Integer(2), K.ideal(i + Integer(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
>>> from sage.all import * >>> from sage.structure.element import Element >>> class MyElement(Element): ... def _div_(self, other): ... return Integer(42) >>> e = MyElement(Parent()) >>> operator.truediv(e, e) 42
- __floordiv__(left, right)[source]¶
Top-level floor division operator for
Element
invoking the coercion model.EXAMPLES:
sage: 7 // 3 2 sage: 7 // int(3) 2 sage: int(7) // 3 2
>>> from sage.all import * >>> Integer(7) // Integer(3) 2 >>> Integer(7) // int(Integer(3)) 2 >>> int(Integer(7)) // Integer(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
>>> from sage.all import * >>> from sage.structure.element import Element >>> class MyElement(Element): ... def _floordiv_(self, other): ... return Integer(42) >>> e = MyElement(Parent()) >>> e // e 42
- __mod__(left, right)[source]¶
Top-level modulo operator for
Element
invoking the coercion model.EXAMPLES:
sage: 7 % 3 1 sage: 7 % int(3) 1 sage: int(7) % 3 1
>>> from sage.all import * >>> Integer(7) % Integer(3) 1 >>> Integer(7) % int(Integer(3)) 1 >>> int(Integer(7)) % Integer(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
>>> from sage.all import * >>> from sage.structure.element import Element >>> class MyElement(Element): ... def _mod_(self, other): ... return Integer(42) >>> e = MyElement(Parent()) >>> e % e 42
- is_zero()[source]¶
Return
True
ifself
equalsself.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)[source]¶
Alias for
numerical_approx()
.EXAMPLES:
sage: (2/3).n() # needs sage.rings.real_mpfr 0.666666666666667
>>> from sage.all import * >>> (Integer(2)/Integer(3)).n() # needs sage.rings.real_mpfr 0.666666666666667
- numerical_approx(prec=None, digits=None, algorithm=None)[source]¶
Return a numerical approximation of
self
withprec
bits (or decimaldigits
) of precision.No guarantee is made about the accuracy of the result.
INPUT:
prec
– precision in bitsdigits
– precision in decimal digits (only used ifprec
is not given)algorithm
– which algorithm to use to compute this approximation (the accepted algorithms depend on the object)
If neither
prec
nordigits
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
>>> from sage.all import * >>> (Integer(2)/Integer(3)).numerical_approx() # needs sage.rings.real_mpfr 0.666666666666667 >>> pi.n(digits=Integer(10)) # needs sage.symbolic 3.141592654 >>> pi.n(prec=Integer(20)) # needs sage.symbolic 3.1416
- parent(x=None)[source]¶
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)[source]¶
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
>>> from sage.all import * >>> x, y = PolynomialRing(ZZ,Integer(2),'xy').gens() >>> f = x**Integer(2) + y + x**Integer(2)*y**Integer(2) + Integer(5) >>> f((Integer(5),y)) 25*y^2 + y + 30 >>> f.subs({x:Integer(5)}) 25*y^2 + y + 30 >>> f.subs(x=Integer(5)) 25*y^2 + y + 30 >>> (Integer(1)/f).subs(x=Integer(5)) 1/(25*y^2 + y + 30) >>> Integer(Integer(5)).subs(x=Integer(4)) 5
- substitute(*args, **kwds)[source]¶
This calls
self.subs()
.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
>>> from sage.all import * >>> x, y = PolynomialRing(ZZ, Integer(2), 'xy').gens() >>> f = x**Integer(2) + y + x**Integer(2)*y**Integer(2) + Integer(5) >>> f((Integer(5),y)) 25*y^2 + y + 30 >>> f.substitute({x: Integer(5)}) 25*y^2 + y + 30 >>> f.substitute(x=Integer(5)) 25*y^2 + y + 30 >>> (Integer(1)/f).substitute(x=Integer(5)) 1/(25*y^2 + y + 30) >>> Integer(Integer(5)).substitute(x=Integer(4)) 5
- class sage.structure.element.ElementWithCachedMethod[source]¶
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 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 (exceptself
) is actually faster than a Python method that does nothing more but to return1
. 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 (forElement
).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)
>>> from sage.all import * >>> # needs sage.misc.cython >>> 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"] >>> cython('\n'.join(cython_code)) >>> 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"] >>> cython('\n'.join(cython_code)) >>> C = MyCategory() >>> P = MyParent(category=C) >>> ebroken = MyBrokenElement(P, Integer(5)) >>> e = MyElement(P, Integer(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
>>> from sage.all import * >>> # needs sage.misc.cython >>> e.element_cache_test() <-5> >>> e.element_cache_test() is e.element_cache_test() True >>> e.element_via_parent_test() <-5> >>> 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
>>> from sage.all import * >>> e == ebroken # needs sage.misc.cython True >>> type(e) == type(ebroken) # needs sage.misc.cython False >>> 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
>>> from sage.all import * >>> ebroken.element_cache_test() # needs sage.misc.cython <-5> >>> ebroken.element_cache_test() is ebroken.element_cache_test() # needs sage.misc.cython False
Since
e
andebroken
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
>>> from sage.all import * >>> b = ebroken.element_via_parent_test() # needs sage.misc.cython >>> e.element_via_parent_test.clear_cache() # needs sage.misc.cython >>> 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
>>> from sage.all import * >>> epython = MyPythonElement(P, Integer(5)) # needs sage.misc.cython >>> epython.element_cache_test() # needs sage.misc.cython <-5> >>> epython.element_cache_test() is epython.element_cache_test() # needs sage.misc.cython True
- class sage.structure.element.EuclideanDomainElement[source]¶
Bases:
PrincipalIdealDomainElement
- class sage.structure.element.Expression[source]¶
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
>>> from sage.all import * >>> 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
>>> from sage.all import * >>> len(sage.structure.element.Expression.__subclasses__()) <= Integer(1) True
- class sage.structure.element.FieldElement[source]¶
Bases:
CommutativeRingElement
- divides(other)[source]¶
Check whether
self
dividesother
, for field elements.Since this is a field, all values divide all other values, except that zero does not divide any nonzero 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
>>> from sage.all import * >>> # needs sage.rings.number_field sage.symbolic >>> K = QQ[sqrt(Integer(3))]; (rt3,) = K._first_ngens(1) >>> K(Integer(0)).divides(rt3) False >>> rt3.divides(K(Integer(17))) True >>> K(Integer(0)).divides(K(Integer(0))) True >>> rt3.divides(K(Integer(0))) True
- is_unit()[source]¶
Return
True
ifself
is a unit in its parent ring.EXAMPLES:
sage: a = 2/3; a.is_unit() True
>>> from sage.all import * >>> a = Integer(2)/Integer(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
>>> from sage.all import * >>> a = Integer(2); a.is_unit() False >>> parent(a) Integer Ring
However, a is a unit when viewed as an element of QQ:
sage: a = QQ(2); a.is_unit() True
>>> from sage.all import * >>> a = QQ(Integer(2)); a.is_unit() True
- class sage.structure.element.InfinityElement[source]¶
Bases:
RingElement
- class sage.structure.element.IntegralDomainElement[source]¶
Bases:
CommutativeRingElement
- class sage.structure.element.Matrix[source]¶
Bases:
ModuleElement
- class sage.structure.element.ModuleElementWithMutability[source]¶
Bases:
ModuleElement
Generic element of a module with mutability.
- is_immutable()[source]¶
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
>>> from sage.all import * >>> v = vector(QQ['x,y'], (ellipsis_range(Integer(1),Ellipsis,Integer(5)))); v.is_immutable() # needs sage.modules False >>> v.set_immutable() # needs sage.modules >>> v.is_immutable() # needs sage.modules True
- is_mutable()[source]¶
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
>>> from sage.all import * >>> v = vector(QQ['x,y'], (ellipsis_range(Integer(1),Ellipsis,Integer(5)))); v.is_mutable() # needs sage.modules True >>> v.set_immutable() # needs sage.modules >>> v.is_mutable() # needs sage.modules False
- set_immutable()[source]¶
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())
>>> from sage.all import * >>> # needs sage.modules >>> v = vector((ellipsis_range(Integer(1),Ellipsis,Integer(5)))); v (1, 2, 3, 4, 5) >>> v[Integer(1)] = Integer(10) >>> v.set_immutable() >>> v[Integer(1)] = Integer(10) Traceback (most recent call last): ... ValueError: vector is immutable; please change a copy instead (use copy())
- class sage.structure.element.MonoidElement[source]¶
Bases:
Element
Generic element of a monoid.
- powers(n)[source]¶
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)]
>>> from sage.all import * >>> G = SymmetricGroup(Integer(4)) # needs sage.groups >>> g = G([Integer(2), Integer(3), Integer(4), Integer(1)]) # needs sage.groups >>> g.powers(Integer(4)) # needs sage.groups [(), (1,2,3,4), (1,3)(2,4), (1,4,3,2)]
- class sage.structure.element.MultiplicativeGroupElement[source]¶
Bases:
MonoidElement
Generic element of a multiplicative group.
- class sage.structure.element.PrincipalIdealDomainElement[source]¶
Bases:
DedekindDomainElement
- class sage.structure.element.RingElement[source]¶
Bases:
ModuleElement
- abs()[source]¶
Return the absolute value of
self
. (This just calls the__abs__
method, so it is equivalent to theabs()
built-in function.)EXAMPLES:
sage: RR(-1).abs() # needs sage.rings.real_mpfr 1.00000000000000 sage: ZZ(-1).abs() 1 sage: CC(I).abs() # needs sage.rings.real_mpfr sage.symbolic 1.00000000000000 sage: Mod(-15, 37).abs() Traceback (most recent call last): ... ArithmeticError: absolute value not defined on integers modulo n.
>>> from sage.all import * >>> RR(-Integer(1)).abs() # needs sage.rings.real_mpfr 1.00000000000000 >>> ZZ(-Integer(1)).abs() 1 >>> CC(I).abs() # needs sage.rings.real_mpfr sage.symbolic 1.00000000000000 >>> Mod(-Integer(15), Integer(37)).abs() Traceback (most recent call last): ... ArithmeticError: absolute value not defined on integers modulo n.
- is_prime()[source]¶
Check whether
self
is a prime element.A prime element is a nonzero, 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
>>> from sage.all import * >>> # needs sage.libs.singular >>> R = QQ['x, y']; (x, y,) = R._first_ngens(2) >>> x.is_prime() True >>> (x**Integer(2) + y**Integer(3)).is_prime() True >>> (x**Integer(2) - y**Integer(2)).is_prime() False >>> R(Integer(0)).is_prime() False >>> R(Integer(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
>>> from sage.all import * >>> # needs sage.rings.number_field >>> K = QuadraticField(-Integer(1), names=('i',)); (i,) = K._first_ngens(1) >>> ZI = K.ring_of_integers() >>> ZI(Integer(3)).is_prime() True >>> ZI(Integer(5)).is_prime() False >>> ZI(Integer(2) + i).is_prime() True >>> ZI(Integer(0)).is_prime() False >>> ZI(Integer(1)).is_prime() False
In fields, an element is never prime:
sage: RR(0).is_prime() False sage: RR(2).is_prime() False
>>> from sage.all import * >>> RR(Integer(0)).is_prime() False >>> RR(Integer(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
>>> from sage.all import * >>> (-Integer(2)).is_prime() False >>> RingElement.is_prime(-Integer(2)) # needs sage.libs.pari True
Similarly,
NumberField
redefinesis_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
>>> from sage.all import * >>> # needs sage.rings.number_field >>> (Integer(1) + i).is_prime() True >>> K(Integer(5)).is_prime() False >>> K(Integer(7)).is_prime() True >>> K(Integer(7)/Integer(13)).is_prime() False
However, for rationals,
is_prime()
does follow the general definition of prime elements in a ring (i.e., always returnsFalse
) since the rationals are not aNumberField
in Sage:sage: QQ(7).is_prime() False
>>> from sage.all import * >>> QQ(Integer(7)).is_prime() False
- multiplicative_order()[source]¶
Return the multiplicative order of
self
, ifself
is a unit.This raises an
ArithmeticError
otherwise.
- class sage.structure.element.Vector[source]¶
Bases:
ModuleElementWithMutability
- sage.structure.element.canonical_coercion(x, y)[source]¶
canonical_coercion(x,y)
is what is called before doing an arithmetic operation betweenx
andy
. It returns a pair(z,w)
such thatz
is got fromx
andw
fromy
via canonical coercion and the parents ofz
andw
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] )
>>> from sage.all import * >>> A = Matrix([[Integer(0), Integer(1)], [Integer(1), Integer(0)]]) # needs sage.modules >>> canonical_coercion(A, Integer(1)) # needs sage.modules ( [0 1] [1 0] [1 0], [0 1] )
- sage.structure.element.coerce_binop(method)[source]¶
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
ongcd
: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
>>> from sage.all import * >>> S = PolynomialRing(ZZ, sparse=True, names=('x',)); (x,) = S._first_ngens(1) >>> f = x**Integer(2) >>> g = x >>> f.gcd(g) #indirect doctest x >>> T = PolynomialRing(QQ, name='x', sparse=True) >>> h = Integer(1)/Integer(2)*T(x) >>> u = f.gcd(h); u #indirect doctest x >>> 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
>>> from sage.all import * >>> R1 = QQ['x,y'] >>> R2 = QQ['x,y,z'] >>> f = R1(Integer(1)) >>> g = R1(Integer(2)) >>> h = R2(Integer(1)) >>> f.gcd(g) 1 >>> f.gcd(g, algorithm='modular') 1 >>> f.gcd(h) 1 >>> f.gcd(h, algorithm='modular') 1 >>> h.gcd(f) 1 >>> 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)
>>> from sage.all import * >>> from sage.structure.element import coerce_binop >>> 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)
>>> from sage.all import * >>> x = MyRational(Integer(1)) >>> x.test_add(Integer(1)/Integer(2)) (1, 1/2, 'z') >>> x.test_add(Integer(1)/Integer(2), keyword=Integer(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'...
>>> from sage.all import * >>> x.test_add(Integer(2)) (1, 2, 'z') >>> x.test_add(Integer(2), keyword=Integer(3)) (1, 2, 3) >>> x.test_add(CC(Integer(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)[source]¶
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'
>>> from sage.all import * >>> cm = sage.structure.element.get_coercion_model() >>> cm.record_exceptions() >>> Integer(1) + Integer(1)/Integer(5) 6/5 >>> coercion_traceback() # Should be empty, as all went well. >>> Integer(1)/Integer(5) + GF(Integer(5)).gen() Traceback (most recent call last): ... TypeError: unsupported operand parent(s) for +: 'Rational Field' and 'Finite Field of size 5' >>> 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()[source]¶
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
>>> from sage.all import * >>> import sage.structure.element as e >>> cm = e.get_coercion_model() >>> cm <sage.structure.coerce.CoercionModel object at ...> >>> cm is coercion_model True
- sage.structure.element.have_same_parent(left, right)[source]¶
Return
True
if and only ifleft
andright
have the same parent.Warning
This function assumes that at least one of the arguments is a Sage
Element
. When in doubt, use the slowerparent(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
>>> from sage.all import * >>> from sage.structure.element import have_same_parent >>> have_same_parent(Integer(1), Integer(3)) True >>> have_same_parent(Integer(1), Integer(1)/Integer(2)) False >>> have_same_parent(gap(Integer(1)), gap(Integer(1)/Integer(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
>>> from sage.all import * >>> a = RLF(Integer(2)) >>> b = exp(a) >>> type(a) <... 'sage.rings.real_lazy.LazyWrapper'> >>> type(b) <... 'sage.rings.real_lazy.LazyNamedUnop'> >>> have_same_parent(a, b) True
- sage.structure.element.is_AdditiveGroupElement(x)[source]¶
Return
True
if x is of type AdditiveGroupElement.
- sage.structure.element.is_CommutativeAlgebraElement(x)[source]¶
Return
True
if x is of type CommutativeAlgebraElement.
- sage.structure.element.is_CommutativeRingElement(x)[source]¶
Return
True
if x is of type CommutativeRingElement.
- sage.structure.element.is_DedekindDomainElement(x)[source]¶
Return
True
if x is of type DedekindDomainElement.
- sage.structure.element.is_Element(x)[source]¶
Return
True
if x is of type Element.EXAMPLES:
sage: from sage.structure.element import is_Element sage: is_Element(2/3) doctest:warning... DeprecationWarning: The function is_Element is deprecated; use 'isinstance(..., Element)' instead. See https://github.com/sagemath/sage/issues/38077 for details. True sage: is_Element(QQ^3) # needs sage.modules False
>>> from sage.all import * >>> from sage.structure.element import is_Element >>> is_Element(Integer(2)/Integer(3)) doctest:warning... DeprecationWarning: The function is_Element is deprecated; use 'isinstance(..., Element)' instead. See https://github.com/sagemath/sage/issues/38077 for details. True >>> is_Element(QQ**Integer(3)) # needs sage.modules False
- sage.structure.element.is_EuclideanDomainElement(x)[source]¶
Return
True
if x is of type EuclideanDomainElement.
- sage.structure.element.is_IntegralDomainElement(x)[source]¶
Return
True
if x is of type IntegralDomainElement.
- sage.structure.element.is_ModuleElement(x)[source]¶
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) doctest:warning... DeprecationWarning: The function is_ModuleElement is deprecated; use 'isinstance(..., ModuleElement)' instead. See https://github.com/sagemath/sage/issues/38077 for details. True sage: is_ModuleElement((QQ^3).0) # needs sage.modules True sage: is_ModuleElement('a') False
>>> from sage.all import * >>> from sage.structure.element import is_ModuleElement >>> is_ModuleElement(Integer(2)/Integer(3)) doctest:warning... DeprecationWarning: The function is_ModuleElement is deprecated; use 'isinstance(..., ModuleElement)' instead. See https://github.com/sagemath/sage/issues/38077 for details. True >>> is_ModuleElement((QQ**Integer(3)).gen(0)) # needs sage.modules True >>> is_ModuleElement('a') False
- sage.structure.element.is_MultiplicativeGroupElement(x)[source]¶
Return
True
if x is of type MultiplicativeGroupElement.
- sage.structure.element.is_PrincipalIdealDomainElement(x)[source]¶
Return
True
if x is of type PrincipalIdealDomainElement.
- sage.structure.element.make_element(_class, _dict, parent)[source]¶
This function is only here to support old pickles.
Pickling functionality is moved to Element.{__getstate__,__setstate__} functions.
- sage.structure.element.parent(x)[source]¶
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 SageElement
, returnx.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
>>> from sage.all import * >>> a = Integer(42) >>> parent(a) Integer Ring >>> b = Integer(42)/Integer(1) >>> parent(b) Rational Field >>> c = RealNumber('42.0') >>> 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
>>> from sage.all import * >>> x = Partition([Integer(3),Integer(2),Integer(1),Integer(1),Integer(1)]) # needs sage.combinat >>> parent(x) # needs sage.combinat Partitions >>> v = vector(RDF, [Integer(1),Integer(2),Integer(3)]) # needs sage.modules >>> 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'>
>>> from sage.all import * >>> d = int(Integer(42)) # Python int >>> parent(d) <... 'int'> >>> L = list(range(Integer(10))) >>> parent(L) <... 'list'>