passagemath-objects 10.6.44__cp314-cp314t-macosx_13_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_objects/.dylibs/libgmp.10.dylib +0 -0
- passagemath_objects/__init__.py +3 -0
- passagemath_objects-10.6.44.dist-info/METADATA +115 -0
- passagemath_objects-10.6.44.dist-info/RECORD +280 -0
- passagemath_objects-10.6.44.dist-info/WHEEL +6 -0
- passagemath_objects-10.6.44.dist-info/top_level.txt +3 -0
- sage/all__sagemath_objects.py +37 -0
- sage/arith/all__sagemath_objects.py +5 -0
- sage/arith/long.pxd +411 -0
- sage/arith/numerical_approx.cpython-314t-darwin.so +0 -0
- sage/arith/numerical_approx.pxd +35 -0
- sage/arith/numerical_approx.pyx +75 -0
- sage/arith/power.cpython-314t-darwin.so +0 -0
- sage/arith/power.pxd +31 -0
- sage/arith/power.pyx +127 -0
- sage/categories/action.cpython-314t-darwin.so +0 -0
- sage/categories/action.pxd +29 -0
- sage/categories/action.pyx +641 -0
- sage/categories/algebra_functor.py +745 -0
- sage/categories/all__sagemath_objects.py +33 -0
- sage/categories/basic.py +62 -0
- sage/categories/cartesian_product.py +295 -0
- sage/categories/category.py +3401 -0
- sage/categories/category_cy_helper.cpython-314t-darwin.so +0 -0
- sage/categories/category_cy_helper.pxd +8 -0
- sage/categories/category_cy_helper.pyx +322 -0
- sage/categories/category_singleton.cpython-314t-darwin.so +0 -0
- sage/categories/category_singleton.pxd +3 -0
- sage/categories/category_singleton.pyx +342 -0
- sage/categories/category_types.py +637 -0
- sage/categories/category_with_axiom.py +2876 -0
- sage/categories/covariant_functorial_construction.py +703 -0
- sage/categories/facade_sets.py +228 -0
- sage/categories/functor.cpython-314t-darwin.so +0 -0
- sage/categories/functor.pxd +7 -0
- sage/categories/functor.pyx +691 -0
- sage/categories/homset.py +1338 -0
- sage/categories/homsets.py +364 -0
- sage/categories/isomorphic_objects.py +73 -0
- sage/categories/map.cpython-314t-darwin.so +0 -0
- sage/categories/map.pxd +34 -0
- sage/categories/map.pyx +2106 -0
- sage/categories/morphism.cpython-314t-darwin.so +0 -0
- sage/categories/morphism.pxd +14 -0
- sage/categories/morphism.pyx +895 -0
- sage/categories/objects.py +167 -0
- sage/categories/primer.py +1696 -0
- sage/categories/pushout.py +4834 -0
- sage/categories/quotients.py +64 -0
- sage/categories/realizations.py +200 -0
- sage/categories/sets_cat.py +3290 -0
- sage/categories/sets_with_partial_maps.py +52 -0
- sage/categories/subobjects.py +64 -0
- sage/categories/subquotients.py +21 -0
- sage/categories/with_realizations.py +311 -0
- sage/cpython/__init__.py +19 -0
- sage/cpython/_py2_random.py +619 -0
- sage/cpython/all.py +3 -0
- sage/cpython/atexit.cpython-314t-darwin.so +0 -0
- sage/cpython/atexit.pyx +269 -0
- sage/cpython/builtin_types.cpython-314t-darwin.so +0 -0
- sage/cpython/builtin_types.pyx +7 -0
- sage/cpython/cython_metaclass.cpython-314t-darwin.so +0 -0
- sage/cpython/cython_metaclass.h +117 -0
- sage/cpython/cython_metaclass.pxd +3 -0
- sage/cpython/cython_metaclass.pyx +130 -0
- sage/cpython/debug.cpython-314t-darwin.so +0 -0
- sage/cpython/debug.pyx +302 -0
- sage/cpython/dict_del_by_value.cpython-314t-darwin.so +0 -0
- sage/cpython/dict_del_by_value.pxd +9 -0
- sage/cpython/dict_del_by_value.pyx +191 -0
- sage/cpython/dict_internal.h +245 -0
- sage/cpython/getattr.cpython-314t-darwin.so +0 -0
- sage/cpython/getattr.pxd +9 -0
- sage/cpython/getattr.pyx +439 -0
- sage/cpython/pycore_long.h +97 -0
- sage/cpython/pycore_long.pxd +10 -0
- sage/cpython/python_debug.h +44 -0
- sage/cpython/python_debug.pxd +47 -0
- sage/cpython/pyx_visit.h +13 -0
- sage/cpython/string.cpython-314t-darwin.so +0 -0
- sage/cpython/string.pxd +76 -0
- sage/cpython/string.pyx +34 -0
- sage/cpython/string_impl.h +60 -0
- sage/cpython/type.cpython-314t-darwin.so +0 -0
- sage/cpython/type.pxd +2 -0
- sage/cpython/type.pyx +40 -0
- sage/cpython/wrapperdescr.pxd +67 -0
- sage/ext/all__sagemath_objects.py +3 -0
- sage/ext/ccobject.h +64 -0
- sage/ext/cplusplus.pxd +17 -0
- sage/ext/mod_int.h +30 -0
- sage/ext/mod_int.pxd +24 -0
- sage/ext/stdsage.pxd +39 -0
- sage/groups/all__sagemath_objects.py +1 -0
- sage/groups/group.cpython-314t-darwin.so +0 -0
- sage/groups/group.pxd +14 -0
- sage/groups/group.pyx +322 -0
- sage/groups/old.cpython-314t-darwin.so +0 -0
- sage/groups/old.pxd +14 -0
- sage/groups/old.pyx +219 -0
- sage/libs/all__sagemath_objects.py +3 -0
- sage/libs/gmp/__init__.py +1 -0
- sage/libs/gmp/all.pxd +6 -0
- sage/libs/gmp/binop.pxd +23 -0
- sage/libs/gmp/misc.pxd +8 -0
- sage/libs/gmp/mpf.pxd +88 -0
- sage/libs/gmp/mpn.pxd +57 -0
- sage/libs/gmp/mpq.pxd +57 -0
- sage/libs/gmp/mpz.pxd +202 -0
- sage/libs/gmp/pylong.cpython-314t-darwin.so +0 -0
- sage/libs/gmp/pylong.pxd +12 -0
- sage/libs/gmp/pylong.pyx +150 -0
- sage/libs/gmp/random.pxd +25 -0
- sage/libs/gmp/randomize.pxd +59 -0
- sage/libs/gmp/types.pxd +53 -0
- sage/libs/gmpxx.pxd +19 -0
- sage/misc/abstract_method.py +276 -0
- sage/misc/all__sagemath_objects.py +43 -0
- sage/misc/bindable_class.py +253 -0
- sage/misc/c3_controlled.cpython-314t-darwin.so +0 -0
- sage/misc/c3_controlled.pxd +2 -0
- sage/misc/c3_controlled.pyx +1402 -0
- sage/misc/cachefunc.cpython-314t-darwin.so +0 -0
- sage/misc/cachefunc.pxd +43 -0
- sage/misc/cachefunc.pyx +3781 -0
- sage/misc/call.py +188 -0
- sage/misc/classcall_metaclass.cpython-314t-darwin.so +0 -0
- sage/misc/classcall_metaclass.pxd +14 -0
- sage/misc/classcall_metaclass.pyx +599 -0
- sage/misc/constant_function.cpython-314t-darwin.so +0 -0
- sage/misc/constant_function.pyx +130 -0
- sage/misc/decorators.py +747 -0
- sage/misc/fast_methods.cpython-314t-darwin.so +0 -0
- sage/misc/fast_methods.pxd +20 -0
- sage/misc/fast_methods.pyx +351 -0
- sage/misc/flatten.py +90 -0
- sage/misc/fpickle.cpython-314t-darwin.so +0 -0
- sage/misc/fpickle.pyx +177 -0
- sage/misc/function_mangling.cpython-314t-darwin.so +0 -0
- sage/misc/function_mangling.pxd +11 -0
- sage/misc/function_mangling.pyx +308 -0
- sage/misc/inherit_comparison.cpython-314t-darwin.so +0 -0
- sage/misc/inherit_comparison.pxd +5 -0
- sage/misc/inherit_comparison.pyx +105 -0
- sage/misc/instancedoc.cpython-314t-darwin.so +0 -0
- sage/misc/instancedoc.pyx +331 -0
- sage/misc/lazy_attribute.cpython-314t-darwin.so +0 -0
- sage/misc/lazy_attribute.pyx +607 -0
- sage/misc/lazy_format.py +135 -0
- sage/misc/lazy_import.cpython-314t-darwin.so +0 -0
- sage/misc/lazy_import.pyx +1299 -0
- sage/misc/lazy_import_cache.py +36 -0
- sage/misc/lazy_list.cpython-314t-darwin.so +0 -0
- sage/misc/lazy_list.pxd +19 -0
- sage/misc/lazy_list.pyx +1187 -0
- sage/misc/lazy_string.cpython-314t-darwin.so +0 -0
- sage/misc/lazy_string.pxd +7 -0
- sage/misc/lazy_string.pyx +546 -0
- sage/misc/misc.py +1066 -0
- sage/misc/misc_c.cpython-314t-darwin.so +0 -0
- sage/misc/misc_c.pxd +3 -0
- sage/misc/misc_c.pyx +766 -0
- sage/misc/namespace_package.py +37 -0
- sage/misc/nested_class.cpython-314t-darwin.so +0 -0
- sage/misc/nested_class.pxd +3 -0
- sage/misc/nested_class.pyx +394 -0
- sage/misc/persist.cpython-314t-darwin.so +0 -0
- sage/misc/persist.pyx +1251 -0
- sage/misc/prandom.py +418 -0
- sage/misc/randstate.cpython-314t-darwin.so +0 -0
- sage/misc/randstate.pxd +30 -0
- sage/misc/randstate.pyx +1059 -0
- sage/misc/repr.py +203 -0
- sage/misc/reset.cpython-314t-darwin.so +0 -0
- sage/misc/reset.pyx +196 -0
- sage/misc/sage_ostools.cpython-314t-darwin.so +0 -0
- sage/misc/sage_ostools.pyx +323 -0
- sage/misc/sage_timeit.py +275 -0
- sage/misc/sage_timeit_class.cpython-314t-darwin.so +0 -0
- sage/misc/sage_timeit_class.pyx +120 -0
- sage/misc/sage_unittest.py +637 -0
- sage/misc/sageinspect.py +2768 -0
- sage/misc/session.cpython-314t-darwin.so +0 -0
- sage/misc/session.pyx +392 -0
- sage/misc/superseded.py +557 -0
- sage/misc/test_nested_class.py +228 -0
- sage/misc/timing.py +264 -0
- sage/misc/unknown.py +222 -0
- sage/misc/verbose.py +253 -0
- sage/misc/weak_dict.cpython-314t-darwin.so +0 -0
- sage/misc/weak_dict.pxd +15 -0
- sage/misc/weak_dict.pyx +1231 -0
- sage/modules/all__sagemath_objects.py +1 -0
- sage/modules/module.cpython-314t-darwin.so +0 -0
- sage/modules/module.pxd +5 -0
- sage/modules/module.pyx +329 -0
- sage/rings/all__sagemath_objects.py +3 -0
- sage/rings/integer_fake.h +22 -0
- sage/rings/integer_fake.pxd +55 -0
- sage/sets/all__sagemath_objects.py +3 -0
- sage/sets/pythonclass.cpython-314t-darwin.so +0 -0
- sage/sets/pythonclass.pxd +9 -0
- sage/sets/pythonclass.pyx +247 -0
- sage/structure/__init__.py +4 -0
- sage/structure/all.py +30 -0
- sage/structure/category_object.cpython-314t-darwin.so +0 -0
- sage/structure/category_object.pxd +28 -0
- sage/structure/category_object.pyx +1087 -0
- sage/structure/coerce.cpython-314t-darwin.so +0 -0
- sage/structure/coerce.pxd +44 -0
- sage/structure/coerce.pyx +2107 -0
- sage/structure/coerce_actions.cpython-314t-darwin.so +0 -0
- sage/structure/coerce_actions.pxd +27 -0
- sage/structure/coerce_actions.pyx +988 -0
- sage/structure/coerce_dict.cpython-314t-darwin.so +0 -0
- sage/structure/coerce_dict.pxd +51 -0
- sage/structure/coerce_dict.pyx +1557 -0
- sage/structure/coerce_exceptions.py +23 -0
- sage/structure/coerce_maps.cpython-314t-darwin.so +0 -0
- sage/structure/coerce_maps.pxd +28 -0
- sage/structure/coerce_maps.pyx +718 -0
- sage/structure/debug_options.cpython-314t-darwin.so +0 -0
- sage/structure/debug_options.pxd +6 -0
- sage/structure/debug_options.pyx +54 -0
- sage/structure/dynamic_class.py +541 -0
- sage/structure/element.cpython-314t-darwin.so +0 -0
- sage/structure/element.pxd +272 -0
- sage/structure/element.pyx +4772 -0
- sage/structure/element_wrapper.cpython-314t-darwin.so +0 -0
- sage/structure/element_wrapper.pxd +12 -0
- sage/structure/element_wrapper.pyx +582 -0
- sage/structure/factorization.py +1422 -0
- sage/structure/factorization_integer.py +105 -0
- sage/structure/factory.cpython-314t-darwin.so +0 -0
- sage/structure/factory.pyx +786 -0
- sage/structure/formal_sum.py +489 -0
- sage/structure/gens_py.py +73 -0
- sage/structure/global_options.py +1743 -0
- sage/structure/indexed_generators.py +863 -0
- sage/structure/list_clone.cpython-314t-darwin.so +0 -0
- sage/structure/list_clone.pxd +65 -0
- sage/structure/list_clone.pyx +1867 -0
- sage/structure/list_clone_demo.cpython-314t-darwin.so +0 -0
- sage/structure/list_clone_demo.pyx +248 -0
- sage/structure/list_clone_timings.py +179 -0
- sage/structure/list_clone_timings_cy.cpython-314t-darwin.so +0 -0
- sage/structure/list_clone_timings_cy.pyx +86 -0
- sage/structure/mutability.cpython-314t-darwin.so +0 -0
- sage/structure/mutability.pxd +21 -0
- sage/structure/mutability.pyx +348 -0
- sage/structure/nonexact.py +69 -0
- sage/structure/parent.cpython-314t-darwin.so +0 -0
- sage/structure/parent.pxd +112 -0
- sage/structure/parent.pyx +3093 -0
- sage/structure/parent_base.cpython-314t-darwin.so +0 -0
- sage/structure/parent_base.pxd +13 -0
- sage/structure/parent_base.pyx +44 -0
- sage/structure/parent_gens.cpython-314t-darwin.so +0 -0
- sage/structure/parent_gens.pxd +22 -0
- sage/structure/parent_gens.pyx +377 -0
- sage/structure/parent_old.cpython-314t-darwin.so +0 -0
- sage/structure/parent_old.pxd +25 -0
- sage/structure/parent_old.pyx +294 -0
- sage/structure/proof/__init__.py +1 -0
- sage/structure/proof/all.py +243 -0
- sage/structure/proof/proof.py +300 -0
- sage/structure/richcmp.cpython-314t-darwin.so +0 -0
- sage/structure/richcmp.pxd +213 -0
- sage/structure/richcmp.pyx +495 -0
- sage/structure/sage_object.cpython-314t-darwin.so +0 -0
- sage/structure/sage_object.pxd +3 -0
- sage/structure/sage_object.pyx +988 -0
- sage/structure/sage_object_test.py +19 -0
- sage/structure/sequence.py +937 -0
- sage/structure/set_factories.py +1178 -0
- sage/structure/set_factories_example.py +527 -0
- sage/structure/support_view.py +179 -0
- sage/structure/test_factory.py +56 -0
- sage/structure/unique_representation.py +1359 -0
|
@@ -0,0 +1,4772 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-objects
|
|
2
|
+
# Compile this with -Os because it works around a bug with
|
|
3
|
+
# GCC-4.7.3 + Cython 0.19 on Itanium, see Issue #14452. Moreover, it
|
|
4
|
+
# actually results in faster code than -O3.
|
|
5
|
+
#
|
|
6
|
+
# distutils: extra_compile_args = -Os
|
|
7
|
+
|
|
8
|
+
r"""
|
|
9
|
+
Elements
|
|
10
|
+
|
|
11
|
+
AUTHORS:
|
|
12
|
+
|
|
13
|
+
- David Harvey (2006-10-16): changed CommutativeAlgebraElement to
|
|
14
|
+
derive from CommutativeRingElement instead of AlgebraElement
|
|
15
|
+
|
|
16
|
+
- David Harvey (2006-10-29): implementation and documentation of new
|
|
17
|
+
arithmetic architecture
|
|
18
|
+
|
|
19
|
+
- William Stein (2006-11): arithmetic architecture -- pushing it
|
|
20
|
+
through to completion.
|
|
21
|
+
|
|
22
|
+
- Gonzalo Tornaria (2007-06): recursive base extend for coercion --
|
|
23
|
+
lots of tests
|
|
24
|
+
|
|
25
|
+
- Robert Bradshaw (2007-2010): arithmetic operators and coercion
|
|
26
|
+
|
|
27
|
+
- Maarten Derickx (2010-07): added architecture for is_square and sqrt
|
|
28
|
+
|
|
29
|
+
- Jeroen Demeyer (2016-08): moved all coercion to the base class
|
|
30
|
+
:class:`Element`, see :issue:`20767`
|
|
31
|
+
|
|
32
|
+
The Abstract Element Class Hierarchy
|
|
33
|
+
====================================
|
|
34
|
+
|
|
35
|
+
This is the abstract class hierarchy, i.e., these are all
|
|
36
|
+
abstract base classes.
|
|
37
|
+
|
|
38
|
+
::
|
|
39
|
+
|
|
40
|
+
SageObject
|
|
41
|
+
Element
|
|
42
|
+
ModuleElement
|
|
43
|
+
RingElement
|
|
44
|
+
CommutativeRingElement
|
|
45
|
+
IntegralDomainElement
|
|
46
|
+
DedekindDomainElement
|
|
47
|
+
PrincipalIdealDomainElement
|
|
48
|
+
EuclideanDomainElement
|
|
49
|
+
FieldElement
|
|
50
|
+
CommutativeAlgebraElement
|
|
51
|
+
Expression
|
|
52
|
+
AlgebraElement
|
|
53
|
+
Matrix
|
|
54
|
+
InfinityElement
|
|
55
|
+
AdditiveGroupElement
|
|
56
|
+
Vector
|
|
57
|
+
|
|
58
|
+
MonoidElement
|
|
59
|
+
MultiplicativeGroupElement
|
|
60
|
+
ElementWithCachedMethod
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
How to Define a New Element Class
|
|
64
|
+
=================================
|
|
65
|
+
|
|
66
|
+
Elements typically define a method ``_new_c``, e.g.,
|
|
67
|
+
|
|
68
|
+
.. code-block:: cython
|
|
69
|
+
|
|
70
|
+
cdef _new_c(self, defining data):
|
|
71
|
+
cdef FreeModuleElement_generic_dense x
|
|
72
|
+
x = FreeModuleElement_generic_dense.__new__(FreeModuleElement_generic_dense)
|
|
73
|
+
x._parent = self._parent
|
|
74
|
+
x._entries = v
|
|
75
|
+
|
|
76
|
+
that creates a new sibling very quickly from defining data
|
|
77
|
+
with assumed properties.
|
|
78
|
+
|
|
79
|
+
.. _element_arithmetic:
|
|
80
|
+
|
|
81
|
+
Arithmetic for Elements
|
|
82
|
+
-----------------------
|
|
83
|
+
|
|
84
|
+
Sage has a special system for handling arithmetic operations on Sage
|
|
85
|
+
elements (that is instances of :class:`Element`), in particular to
|
|
86
|
+
manage uniformly mixed arithmetic operations using the :mod:`coercion
|
|
87
|
+
model <sage.structure.coerce>`. We describe here the rules that must
|
|
88
|
+
be followed by both arithmetic implementers and callers.
|
|
89
|
+
|
|
90
|
+
A quick summary for the impatient
|
|
91
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
92
|
+
|
|
93
|
+
To implement addition for any :class:`Element` subclass, override the
|
|
94
|
+
``def _add_(self, other)`` method instead of the usual Python
|
|
95
|
+
``__add__`` :python:`special method <reference/datamodel.html#special-method-names>`.
|
|
96
|
+
Within ``_add_(self, other)``, you may assume that ``self`` and
|
|
97
|
+
``other`` have the same parent.
|
|
98
|
+
|
|
99
|
+
If the implementation is generic across all elements in a given
|
|
100
|
+
category `C`, then this method can be put in ``C.ElementMethods``.
|
|
101
|
+
|
|
102
|
+
When writing *Cython* code, ``_add_`` should be a cpdef method:
|
|
103
|
+
``cpdef _add_(self, other)``.
|
|
104
|
+
|
|
105
|
+
When doing arithmetic with two elements having different parents,
|
|
106
|
+
the :mod:`coercion model <sage.structure.coerce>` is responsible for
|
|
107
|
+
"coercing" them to a common parent and performing arithmetic on the
|
|
108
|
+
coerced elements.
|
|
109
|
+
|
|
110
|
+
Arithmetic in more detail
|
|
111
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
112
|
+
|
|
113
|
+
The aims of this system are to provide (1) an efficient calling protocol
|
|
114
|
+
from both Python and Cython, (2) uniform coercion semantics across Sage,
|
|
115
|
+
(3) ease of use, (4) readability of code.
|
|
116
|
+
|
|
117
|
+
We will take addition as an example; all other operators are similar.
|
|
118
|
+
There are two relevant functions, with differing names
|
|
119
|
+
(single vs. double underscores).
|
|
120
|
+
|
|
121
|
+
- **def Element.__add__(left, right)**
|
|
122
|
+
|
|
123
|
+
This function is called by Python or Cython when the binary "+"
|
|
124
|
+
operator is encountered. It assumes that at least one of its
|
|
125
|
+
arguments is an :class:`Element`.
|
|
126
|
+
|
|
127
|
+
It has a fast pathway to deal with the most common case where both
|
|
128
|
+
arguments have the same parent. Otherwise, it uses the coercion
|
|
129
|
+
model to work out how to make them have the same parent. The
|
|
130
|
+
coercion model then adds the coerced elements (technically, it calls
|
|
131
|
+
``operator.add``). Note that the result of coercion is not required
|
|
132
|
+
to be a Sage :class:`Element`, it could be a plain Python type.
|
|
133
|
+
|
|
134
|
+
Note that, although this function is declared as ``def``, it doesn't
|
|
135
|
+
have the usual overheads associated with Python functions (either
|
|
136
|
+
for the caller or for ``__add__`` itself). This is because Python
|
|
137
|
+
has optimised calling protocols for such special functions.
|
|
138
|
+
|
|
139
|
+
- **def Element._add_(self, other)**
|
|
140
|
+
|
|
141
|
+
This is the function that you should override to implement addition
|
|
142
|
+
in a subclass of :class:`Element`.
|
|
143
|
+
|
|
144
|
+
The two arguments to this function are guaranteed to have the **same
|
|
145
|
+
parent**, but not necessarily the same Python type.
|
|
146
|
+
|
|
147
|
+
When implementing ``_add_`` in a Cython extension type, use
|
|
148
|
+
``cpdef _add_`` instead of ``def _add_``.
|
|
149
|
+
|
|
150
|
+
In Cython code, if you want to add two elements and you know that
|
|
151
|
+
their parents are identical, you are encouraged to call this
|
|
152
|
+
function directly, instead of using ``x + y``. This only works if
|
|
153
|
+
Cython knows that the left argument is an ``Element``. You can
|
|
154
|
+
always cast explicitly: ``(<Element>x)._add_(y)`` to force this.
|
|
155
|
+
In plain Python, ``x + y`` is always the fastest way to add two
|
|
156
|
+
elements because the special method ``__add__`` is optimized
|
|
157
|
+
unlike the normal method ``_add_``.
|
|
158
|
+
|
|
159
|
+
The difference in the names of the arguments (``left, right``
|
|
160
|
+
versus ``self, other``) is intentional: ``self`` is guaranteed to be an
|
|
161
|
+
instance of the class in which the method is defined. In Cython, we know
|
|
162
|
+
that at least one of ``left`` or ``right`` is an instance of the class
|
|
163
|
+
but we do not know a priori which one.
|
|
164
|
+
|
|
165
|
+
Powering is a special case: first of all, the 3-argument version of
|
|
166
|
+
``pow()`` is not supported. Second, the coercion model checks whether
|
|
167
|
+
the exponent looks like an integer. If so, the function ``_pow_int``
|
|
168
|
+
is called. If the exponent is not an integer, the arguments are coerced
|
|
169
|
+
to a common parent and ``_pow_`` is called. So, if your type only
|
|
170
|
+
supports powering to an integer exponent, you should implement only
|
|
171
|
+
``_pow_int``. If you want to support arbitrary powering, implement both
|
|
172
|
+
``_pow_`` and ``_pow_int``.
|
|
173
|
+
|
|
174
|
+
For addition, multiplication and powering (not for other operators),
|
|
175
|
+
there is a fast path for operations with a C ``long``. For example,
|
|
176
|
+
implement ``cdef _add_long(self, long n)`` with optimized code for
|
|
177
|
+
``self + n``. The addition and multiplication are assumed to be
|
|
178
|
+
commutative, so they are also called for ``n + self`` or ``n * self``.
|
|
179
|
+
From Cython code, you can also call ``_add_long`` or ``_mul_long``
|
|
180
|
+
directly. This is strictly an optimization: there is a default
|
|
181
|
+
implementation falling back to the generic arithmetic function.
|
|
182
|
+
|
|
183
|
+
Examples
|
|
184
|
+
^^^^^^^^
|
|
185
|
+
|
|
186
|
+
We need some :class:`Parent` to work with::
|
|
187
|
+
|
|
188
|
+
sage: from sage.structure.parent import Parent
|
|
189
|
+
sage: class ExampleParent(Parent):
|
|
190
|
+
....: def __init__(self, name, **kwds):
|
|
191
|
+
....: Parent.__init__(self, **kwds)
|
|
192
|
+
....: self.rename(name)
|
|
193
|
+
|
|
194
|
+
We start with a very basic example of a Python class implementing
|
|
195
|
+
``_add_``::
|
|
196
|
+
|
|
197
|
+
sage: from sage.structure.element import Element
|
|
198
|
+
sage: class MyElement(Element):
|
|
199
|
+
....: def _add_(self, other):
|
|
200
|
+
....: return 42
|
|
201
|
+
sage: p = ExampleParent("Some parent")
|
|
202
|
+
sage: x = MyElement(p)
|
|
203
|
+
sage: x + x
|
|
204
|
+
42
|
|
205
|
+
|
|
206
|
+
When two different parents are involved, this no longer works since
|
|
207
|
+
there is no coercion::
|
|
208
|
+
|
|
209
|
+
sage: q = ExampleParent("Other parent")
|
|
210
|
+
sage: y = MyElement(q)
|
|
211
|
+
sage: x + y
|
|
212
|
+
Traceback (most recent call last):
|
|
213
|
+
...
|
|
214
|
+
TypeError: unsupported operand parent(s) for +: 'Some parent' and 'Other parent'
|
|
215
|
+
|
|
216
|
+
If ``_add_`` is not defined, an error message is raised, referring to
|
|
217
|
+
the parents::
|
|
218
|
+
|
|
219
|
+
sage: x = Element(p)
|
|
220
|
+
sage: x._add_(x)
|
|
221
|
+
Traceback (most recent call last):
|
|
222
|
+
...
|
|
223
|
+
AttributeError: 'sage.structure.element.Element' object has no attribute '_add_'...
|
|
224
|
+
sage: x + x
|
|
225
|
+
Traceback (most recent call last):
|
|
226
|
+
...
|
|
227
|
+
TypeError: unsupported operand parent(s) for +: 'Some parent' and 'Some parent'
|
|
228
|
+
sage: y = Element(q)
|
|
229
|
+
sage: x + y
|
|
230
|
+
Traceback (most recent call last):
|
|
231
|
+
...
|
|
232
|
+
TypeError: unsupported operand parent(s) for +: 'Some parent' and 'Other parent'
|
|
233
|
+
|
|
234
|
+
We can also implement arithmetic generically in categories::
|
|
235
|
+
|
|
236
|
+
sage: class MyCategory(Category):
|
|
237
|
+
....: def super_categories(self):
|
|
238
|
+
....: return [Sets()]
|
|
239
|
+
....: class ElementMethods:
|
|
240
|
+
....: def _add_(self, other):
|
|
241
|
+
....: return 42
|
|
242
|
+
sage: p = ExampleParent("Parent in my category", category=MyCategory())
|
|
243
|
+
sage: x = Element(p)
|
|
244
|
+
sage: x + x
|
|
245
|
+
42
|
|
246
|
+
|
|
247
|
+
Implementation details
|
|
248
|
+
^^^^^^^^^^^^^^^^^^^^^^
|
|
249
|
+
|
|
250
|
+
Implementing the above features actually takes a bit of magic. Casual
|
|
251
|
+
callers and implementers can safely ignore it, but here are the
|
|
252
|
+
details for the curious.
|
|
253
|
+
|
|
254
|
+
To achieve fast arithmetic, it is critical to have a fast path in Cython
|
|
255
|
+
to call the ``_add_`` method of a Cython object. So we would like
|
|
256
|
+
to declare ``_add_`` as a ``cpdef`` method of class :class:`Element`.
|
|
257
|
+
Remember however that the abstract classes coming
|
|
258
|
+
from categories come after :class:`Element` in the method resolution
|
|
259
|
+
order (or fake method resolution order in case of a Cython
|
|
260
|
+
class). Hence any generic implementation of ``_add_`` in such an
|
|
261
|
+
abstract class would in principle be shadowed by ``Element._add_``.
|
|
262
|
+
This is worked around by defining ``Element._add_`` as a ``cdef``
|
|
263
|
+
instead of a ``cpdef`` method. Concrete implementations in subclasses
|
|
264
|
+
should be ``cpdef`` or ``def`` methods.
|
|
265
|
+
|
|
266
|
+
Let us now see what happens upon evaluating ``x + y`` when ``x`` and ``y``
|
|
267
|
+
are instances of a class that does not implement ``_add_`` but where
|
|
268
|
+
``_add_`` is implemented in the category.
|
|
269
|
+
First, ``x.__add__(y)`` is called, where ``__add__`` is implemented
|
|
270
|
+
in :class:`Element`.
|
|
271
|
+
Assuming that ``x`` and ``y`` have the same parent, a Cython call to
|
|
272
|
+
``x._add_(y)`` will be done.
|
|
273
|
+
The latter is implemented to trigger a Python level call to ``x._add_(y)``
|
|
274
|
+
which will succeed as desired.
|
|
275
|
+
|
|
276
|
+
In case that Python code calls ``x._add_(y)`` directly,
|
|
277
|
+
``Element._add_`` will be invisible, and the method lookup will
|
|
278
|
+
continue down the MRO and find the ``_add_`` method in the category.
|
|
279
|
+
"""
|
|
280
|
+
|
|
281
|
+
# ****************************************************************************
|
|
282
|
+
# Copyright (C) 2006-2016 ...
|
|
283
|
+
# Copyright (C) 2016 Jeroen Demeyer <jdemeyer@cage.ugent.be>
|
|
284
|
+
#
|
|
285
|
+
# This program is free software: you can redistribute it and/or modify
|
|
286
|
+
# it under the terms of the GNU General Public License as published by
|
|
287
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
288
|
+
# (at your option) any later version.
|
|
289
|
+
# https://www.gnu.org/licenses/
|
|
290
|
+
# ****************************************************************************
|
|
291
|
+
|
|
292
|
+
cimport cython
|
|
293
|
+
from cpython cimport *
|
|
294
|
+
|
|
295
|
+
from sage.ext.stdsage cimport *
|
|
296
|
+
|
|
297
|
+
cdef add, sub, mul, truediv, floordiv, mod, matmul, pow
|
|
298
|
+
from operator import (add, sub, mul, truediv, floordiv, mod, matmul, pow)
|
|
299
|
+
|
|
300
|
+
cdef dict _coerce_op_symbols = dict(
|
|
301
|
+
add='+', sub='-', mul='*', truediv='/', floordiv='//', mod='%', matmul='@', pow='^',
|
|
302
|
+
iadd='+', isub='-', imul='*', itruediv='/', ifloordiv='//', imod='%', imatmul='@', ipow='^')
|
|
303
|
+
|
|
304
|
+
from sage.structure.richcmp cimport rich_to_bool
|
|
305
|
+
from sage.structure.coerce cimport py_scalar_to_element, coercion_model
|
|
306
|
+
from sage.structure.parent cimport Parent
|
|
307
|
+
from sage.cpython.type cimport can_assign_class
|
|
308
|
+
from sage.cpython.getattr cimport getattr_from_other_class
|
|
309
|
+
from sage.misc.lazy_format import LazyFormat
|
|
310
|
+
from sage.arith.long cimport integer_check_long_py
|
|
311
|
+
from sage.arith.power cimport generic_power as arith_generic_power
|
|
312
|
+
from sage.arith.numerical_approx cimport digits_to_bits
|
|
313
|
+
from sage.misc.decorators import sage_wraps
|
|
314
|
+
from sage.misc.superseded import deprecation
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def make_element(_class, _dict, parent):
|
|
318
|
+
"""
|
|
319
|
+
This function is only here to support old pickles.
|
|
320
|
+
|
|
321
|
+
Pickling functionality is moved to Element.{__getstate__,__setstate__}
|
|
322
|
+
functions.
|
|
323
|
+
"""
|
|
324
|
+
from sage.misc.pickle_old import make_element_old
|
|
325
|
+
return make_element_old(_class, _dict, parent)
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
cdef unary_op_exception(op, x):
|
|
329
|
+
try:
|
|
330
|
+
op = op.__name__
|
|
331
|
+
op = _coerce_op_symbols[op]
|
|
332
|
+
except (AttributeError, KeyError):
|
|
333
|
+
pass
|
|
334
|
+
px = parent(x)
|
|
335
|
+
return TypeError(f"unsupported operand parent for {op}: '{px}'")
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
cdef bin_op_exception(op, x, y):
|
|
339
|
+
try:
|
|
340
|
+
op = op.__name__
|
|
341
|
+
op = _coerce_op_symbols[op]
|
|
342
|
+
except (AttributeError, KeyError):
|
|
343
|
+
pass
|
|
344
|
+
px = parent(x)
|
|
345
|
+
py = parent(y)
|
|
346
|
+
return TypeError(f"unsupported operand parent(s) for {op}: '{px}' and '{py}'")
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def is_Element(x):
|
|
350
|
+
"""
|
|
351
|
+
Return ``True`` if x is of type Element.
|
|
352
|
+
|
|
353
|
+
EXAMPLES::
|
|
354
|
+
|
|
355
|
+
sage: from sage.structure.element import is_Element
|
|
356
|
+
sage: is_Element(2/3)
|
|
357
|
+
doctest:warning...
|
|
358
|
+
DeprecationWarning: The function is_Element is deprecated; use 'isinstance(..., Element)' instead.
|
|
359
|
+
See https://github.com/sagemath/sage/issues/38077 for details.
|
|
360
|
+
True
|
|
361
|
+
sage: is_Element(QQ^3) # needs sage.modules
|
|
362
|
+
False
|
|
363
|
+
"""
|
|
364
|
+
from sage.misc.superseded import deprecation_cython
|
|
365
|
+
deprecation_cython(38077, "The function is_Element is deprecated; use 'isinstance(..., Element)' instead.")
|
|
366
|
+
return isinstance(x, Element)
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
cdef class Element(SageObject):
|
|
370
|
+
"""
|
|
371
|
+
Generic element of a structure. All other types of elements
|
|
372
|
+
(:class:`RingElement`, :class:`ModuleElement`, etc)
|
|
373
|
+
derive from this type.
|
|
374
|
+
|
|
375
|
+
Subtypes must either call ``__init__()`` to set ``_parent``, or may
|
|
376
|
+
set ``_parent`` themselves if that would be more efficient.
|
|
377
|
+
|
|
378
|
+
.. automethod:: _richcmp_
|
|
379
|
+
.. automethod:: __add__
|
|
380
|
+
.. automethod:: __sub__
|
|
381
|
+
.. automethod:: __neg__
|
|
382
|
+
.. automethod:: __mul__
|
|
383
|
+
.. automethod:: __truediv__
|
|
384
|
+
.. automethod:: __floordiv__
|
|
385
|
+
.. automethod:: __mod__
|
|
386
|
+
"""
|
|
387
|
+
@cython.binding(False)
|
|
388
|
+
@cython.always_allow_keywords(False)
|
|
389
|
+
def __getmetaclass__(_):
|
|
390
|
+
from sage.misc.inherit_comparison import InheritComparisonMetaclass
|
|
391
|
+
return InheritComparisonMetaclass
|
|
392
|
+
|
|
393
|
+
def __init__(self, parent):
|
|
394
|
+
r"""
|
|
395
|
+
INPUT:
|
|
396
|
+
|
|
397
|
+
- ``parent`` -- a SageObject
|
|
398
|
+
"""
|
|
399
|
+
self._parent = parent
|
|
400
|
+
|
|
401
|
+
def _set_parent(self, parent):
|
|
402
|
+
r"""
|
|
403
|
+
Set the parent of ``self`` to ``parent``.
|
|
404
|
+
|
|
405
|
+
INPUT:
|
|
406
|
+
|
|
407
|
+
- ``parent`` -- a :class:`Parent`
|
|
408
|
+
|
|
409
|
+
.. WARNING::
|
|
410
|
+
|
|
411
|
+
Changing the parent of an object is not something you
|
|
412
|
+
should normally need. It is mainly meant for constructing a
|
|
413
|
+
new element from scratch, when ``__new__`` or ``__init__``
|
|
414
|
+
did not set the right parent. Using this method incorrectly
|
|
415
|
+
can break things badly.
|
|
416
|
+
|
|
417
|
+
EXAMPLES::
|
|
418
|
+
|
|
419
|
+
sage: q = 3/5
|
|
420
|
+
sage: parent(q)
|
|
421
|
+
Rational Field
|
|
422
|
+
sage: q._set_parent(CC) # needs sage.rings.real_mpfr
|
|
423
|
+
sage: parent(q) # needs sage.rings.real_mpfr
|
|
424
|
+
Complex Field with 53 bits of precision
|
|
425
|
+
sage: q._set_parent(float) # needs sage.rings.real_mpfr
|
|
426
|
+
Traceback (most recent call last):
|
|
427
|
+
...
|
|
428
|
+
TypeError: Cannot convert type to sage.structure.parent.Parent
|
|
429
|
+
"""
|
|
430
|
+
self._parent = <Parent?>parent
|
|
431
|
+
|
|
432
|
+
def __getattr__(self, name):
|
|
433
|
+
"""
|
|
434
|
+
Lookup a method or attribute from the category abstract classes.
|
|
435
|
+
|
|
436
|
+
Let ``P`` be a parent in a category ``C``. Usually the methods
|
|
437
|
+
of ``C.element_class`` are made directly available to elements
|
|
438
|
+
of ``P`` via standard class inheritance. This is not the case
|
|
439
|
+
any more if the elements of ``P`` are instances of an
|
|
440
|
+
extension type. See :class:`Category` for details.
|
|
441
|
+
|
|
442
|
+
The purpose of this method is to emulate this inheritance: for
|
|
443
|
+
``e`` and element of ``P``, if an attribute or method
|
|
444
|
+
``e.foo`` is not found in the super classes of ``e``, it's
|
|
445
|
+
looked up manually in ``C.element_class`` and bound to ``e``.
|
|
446
|
+
|
|
447
|
+
.. NOTE::
|
|
448
|
+
|
|
449
|
+
- The attribute or method is actually looked up in
|
|
450
|
+
``P._abstract_element_class``. In most cases this is
|
|
451
|
+
just an alias for ``C.element_class``, but some parents,
|
|
452
|
+
notably homsets, customizes this to let elements also
|
|
453
|
+
inherit from other abstract classes. See
|
|
454
|
+
:meth:`Parent._abstract_element_class` and
|
|
455
|
+
:meth:`Homset._abstract_element_class` for details.
|
|
456
|
+
|
|
457
|
+
- This mechanism may also enter into action when the
|
|
458
|
+
category of `P` is refined on the fly, leaving
|
|
459
|
+
previously constructed elements in an outdated element
|
|
460
|
+
class.
|
|
461
|
+
|
|
462
|
+
See :class:`~sage.rings.polynomial.polynomial_quotient_ring.PolynomialQuotientRing_generic`
|
|
463
|
+
for an example.
|
|
464
|
+
|
|
465
|
+
EXAMPLES:
|
|
466
|
+
|
|
467
|
+
We test that ``1`` (an instance of the extension type
|
|
468
|
+
``Integer``) inherits the methods from the categories of
|
|
469
|
+
``ZZ``, that is from ``CommutativeRings().element_class``::
|
|
470
|
+
|
|
471
|
+
sage: 1.is_idempotent(), 2.is_idempotent()
|
|
472
|
+
(True, False)
|
|
473
|
+
|
|
474
|
+
This method is actually provided by the ``Magmas()`` super
|
|
475
|
+
category of ``CommutativeRings()``::
|
|
476
|
+
|
|
477
|
+
sage: 1.is_idempotent
|
|
478
|
+
<bound method Magmas.ElementMethods.is_idempotent of 1>
|
|
479
|
+
sage: 1.is_idempotent.__module__
|
|
480
|
+
'sage.categories.magmas'
|
|
481
|
+
|
|
482
|
+
TESTS::
|
|
483
|
+
|
|
484
|
+
sage: 1.blah_blah
|
|
485
|
+
Traceback (most recent call last):
|
|
486
|
+
...
|
|
487
|
+
AttributeError: 'sage.rings.integer.Integer' object has no attribute 'blah_blah'...
|
|
488
|
+
sage: Semigroups().example().an_element().is_idempotent
|
|
489
|
+
<bound method LeftZeroSemigroup.Element.is_idempotent of 42>
|
|
490
|
+
sage: Semigroups().example().an_element().blah_blah
|
|
491
|
+
Traceback (most recent call last):
|
|
492
|
+
...
|
|
493
|
+
AttributeError: 'LeftZeroSemigroup_with_category.element_class' object has no attribute 'blah_blah'...
|
|
494
|
+
"""
|
|
495
|
+
return self.getattr_from_category(name)
|
|
496
|
+
|
|
497
|
+
cdef getattr_from_category(self, name):
|
|
498
|
+
# Lookup a method or attribute from the category abstract classes.
|
|
499
|
+
# See __getattr__ above for documentation.
|
|
500
|
+
cdef Parent P = self._parent
|
|
501
|
+
if P is None:
|
|
502
|
+
# This is highly unlikely but we deal with it anyway...
|
|
503
|
+
# Usually, this will just raise AttributeError in
|
|
504
|
+
# getattr_from_other_class().
|
|
505
|
+
cls = type
|
|
506
|
+
else:
|
|
507
|
+
cls = P._abstract_element_class
|
|
508
|
+
return getattr_from_other_class(self, cls, name)
|
|
509
|
+
|
|
510
|
+
def __dir__(self):
|
|
511
|
+
"""
|
|
512
|
+
Emulate ``__dir__`` for elements with dynamically attached methods.
|
|
513
|
+
|
|
514
|
+
Let cat be the category of the parent of ``self``. This method
|
|
515
|
+
emulates ``self`` being an instance of both ``Element`` and
|
|
516
|
+
``cat.element_class`` (and the corresponding ``morphism_class`` in the
|
|
517
|
+
case of a morphism), in that order, for attribute directory.
|
|
518
|
+
|
|
519
|
+
EXAMPLES::
|
|
520
|
+
|
|
521
|
+
sage: dir(1/2)
|
|
522
|
+
[..., 'is_idempotent', 'is_integer', 'is_integral', ...]
|
|
523
|
+
|
|
524
|
+
Caveat: dir on Integer's and some other extension types seem to ignore __dir__::
|
|
525
|
+
|
|
526
|
+
sage: 1.__dir__()
|
|
527
|
+
[..., 'is_idempotent', 'is_integer', 'is_integral', ...]
|
|
528
|
+
sage: dir(1) # todo: not implemented
|
|
529
|
+
[..., 'is_idempotent', 'is_integer', 'is_integral', ...]
|
|
530
|
+
|
|
531
|
+
TESTS:
|
|
532
|
+
|
|
533
|
+
Check that morphism classes are handled correctly (:issue:`29776`)::
|
|
534
|
+
|
|
535
|
+
sage: R.<x,y> = QQ[]
|
|
536
|
+
sage: f = R.hom([x, y+1], R)
|
|
537
|
+
sage: 'cartesian_product' in dir(f)
|
|
538
|
+
True
|
|
539
|
+
sage: 'extend_to_fraction_field' in dir(f)
|
|
540
|
+
True
|
|
541
|
+
"""
|
|
542
|
+
from sage.cpython.getattr import dir_with_other_class
|
|
543
|
+
ec = self.parent().category().element_class
|
|
544
|
+
try:
|
|
545
|
+
mc = self.category_for().morphism_class
|
|
546
|
+
except AttributeError:
|
|
547
|
+
return dir_with_other_class(self, ec)
|
|
548
|
+
else:
|
|
549
|
+
return dir_with_other_class(self, ec, mc)
|
|
550
|
+
|
|
551
|
+
def _repr_(self):
|
|
552
|
+
return "Generic element of a structure"
|
|
553
|
+
|
|
554
|
+
def __getstate__(self):
|
|
555
|
+
"""
|
|
556
|
+
Return a tuple describing the state of your object.
|
|
557
|
+
|
|
558
|
+
This should return all information that will be required to unpickle
|
|
559
|
+
the object. The functionality for unpickling is implemented in
|
|
560
|
+
__setstate__().
|
|
561
|
+
|
|
562
|
+
TESTS::
|
|
563
|
+
|
|
564
|
+
sage: R.<x,y> = QQ[]
|
|
565
|
+
sage: i = ideal(x^2 - y^2 + 1)
|
|
566
|
+
sage: i.__getstate__()
|
|
567
|
+
(Monoid of ideals of Multivariate Polynomial Ring in x, y over Rational Field,
|
|
568
|
+
{'_Ideal_generic__gens': (x^2 - y^2 + 1,),
|
|
569
|
+
'_Ideal_generic__ring': Multivariate Polynomial Ring in x, y over Rational Field,
|
|
570
|
+
'_gb_by_ordering': {}})
|
|
571
|
+
"""
|
|
572
|
+
return (self._parent, self.__dict__)
|
|
573
|
+
|
|
574
|
+
def __setstate__(self, state):
|
|
575
|
+
"""
|
|
576
|
+
Initialize the state of the object from data saved in a pickle.
|
|
577
|
+
|
|
578
|
+
During unpickling ``__init__`` methods of classes are not called, the
|
|
579
|
+
saved data is passed to the class via this function instead.
|
|
580
|
+
|
|
581
|
+
TESTS::
|
|
582
|
+
|
|
583
|
+
sage: R.<x,y> = QQ[]
|
|
584
|
+
sage: i = ideal(x); i
|
|
585
|
+
Ideal (x) of Multivariate Polynomial Ring in x, y over Rational Field
|
|
586
|
+
sage: S.<x,y,z> = ZZ[]
|
|
587
|
+
sage: i.__setstate__((R,{'_Ideal_generic__ring':S,'_Ideal_generic__gens': (S(x^2 - y^2 + 1),)}))
|
|
588
|
+
sage: i
|
|
589
|
+
Ideal (x^2 - y^2 + 1) of Multivariate Polynomial Ring in x, y, z over Integer Ring
|
|
590
|
+
"""
|
|
591
|
+
self._set_parent(state[0])
|
|
592
|
+
self.__dict__ = state[1]
|
|
593
|
+
|
|
594
|
+
def __copy__(self):
|
|
595
|
+
"""
|
|
596
|
+
Return a copy of ``self``.
|
|
597
|
+
|
|
598
|
+
OUTPUT: a new object which is a copy of ``self``
|
|
599
|
+
|
|
600
|
+
This implementation ensures that ``self.__dict__`` is properly copied
|
|
601
|
+
when it exists (typically for instances of classes deriving from
|
|
602
|
+
:class:`Element`).
|
|
603
|
+
|
|
604
|
+
TESTS::
|
|
605
|
+
|
|
606
|
+
sage: from sage.structure.element import Element
|
|
607
|
+
sage: el = Element(parent = ZZ)
|
|
608
|
+
sage: el1 = copy(el)
|
|
609
|
+
sage: el1 is el
|
|
610
|
+
False
|
|
611
|
+
|
|
612
|
+
sage: class Demo(Element): pass
|
|
613
|
+
sage: el = Demo(parent = ZZ)
|
|
614
|
+
sage: el.x = [1,2,3]
|
|
615
|
+
sage: el1 = copy(el)
|
|
616
|
+
sage: el1 is el
|
|
617
|
+
False
|
|
618
|
+
sage: el1.__dict__ is el.__dict__
|
|
619
|
+
False
|
|
620
|
+
"""
|
|
621
|
+
cls = self.__class__
|
|
622
|
+
cdef Element res = cls.__new__(cls)
|
|
623
|
+
res._parent = self._parent
|
|
624
|
+
try:
|
|
625
|
+
D = self.__dict__
|
|
626
|
+
except AttributeError:
|
|
627
|
+
return res
|
|
628
|
+
for k, v in D.iteritems():
|
|
629
|
+
try:
|
|
630
|
+
setattr(res, k, v)
|
|
631
|
+
except AttributeError:
|
|
632
|
+
pass
|
|
633
|
+
return res
|
|
634
|
+
|
|
635
|
+
def _im_gens_(self, codomain, im_gens, base_map=None):
|
|
636
|
+
"""
|
|
637
|
+
Return the image of ``self`` in codomain under the map that sends
|
|
638
|
+
the images of the generators of the parent of ``self`` to the
|
|
639
|
+
tuple of elements of im_gens.
|
|
640
|
+
"""
|
|
641
|
+
raise NotImplementedError
|
|
642
|
+
|
|
643
|
+
cpdef base_extend(self, R):
|
|
644
|
+
cdef Parent V
|
|
645
|
+
V = self._parent.base_extend(R)
|
|
646
|
+
return V.coerce(self)
|
|
647
|
+
|
|
648
|
+
def base_ring(self):
|
|
649
|
+
"""
|
|
650
|
+
Return the base ring of this element's parent (if that makes sense).
|
|
651
|
+
|
|
652
|
+
TESTS::
|
|
653
|
+
|
|
654
|
+
sage: QQ.base_ring()
|
|
655
|
+
Rational Field
|
|
656
|
+
sage: identity_matrix(3).base_ring() # needs sage.modules
|
|
657
|
+
Integer Ring
|
|
658
|
+
"""
|
|
659
|
+
return self._parent.base_ring()
|
|
660
|
+
|
|
661
|
+
def category(self):
|
|
662
|
+
from sage.categories.category_types import Elements
|
|
663
|
+
return Elements(self._parent)
|
|
664
|
+
|
|
665
|
+
def _test_new(self, **options):
|
|
666
|
+
"""
|
|
667
|
+
Check that ``cls.__new__(cls)`` and
|
|
668
|
+
``cls.__new__(cls, parent)`` do not crash Python,
|
|
669
|
+
where ``cls = type(self)`` and ``parent = parent(self)``.
|
|
670
|
+
|
|
671
|
+
It is perfectly legal for ``__new__`` to raise ordinary
|
|
672
|
+
exceptions.
|
|
673
|
+
|
|
674
|
+
EXAMPLES::
|
|
675
|
+
|
|
676
|
+
sage: from sage.structure.element import Element
|
|
677
|
+
sage: p = Parent()
|
|
678
|
+
sage: e = Element(p)
|
|
679
|
+
sage: e._test_new()
|
|
680
|
+
"""
|
|
681
|
+
cdef type cls = type(self)
|
|
682
|
+
try:
|
|
683
|
+
cls.__new__(cls)
|
|
684
|
+
except Exception:
|
|
685
|
+
pass
|
|
686
|
+
try:
|
|
687
|
+
cls.__new__(cls, self._parent)
|
|
688
|
+
except Exception:
|
|
689
|
+
pass
|
|
690
|
+
|
|
691
|
+
def _test_category(self, **options):
|
|
692
|
+
"""
|
|
693
|
+
Run generic tests on the method :meth:`.category`.
|
|
694
|
+
|
|
695
|
+
See also: :class:`TestSuite`.
|
|
696
|
+
|
|
697
|
+
EXAMPLES::
|
|
698
|
+
|
|
699
|
+
sage: 3._test_category()
|
|
700
|
+
|
|
701
|
+
Let us now write a broken :meth:`.category` method::
|
|
702
|
+
|
|
703
|
+
sage: from sage.categories.examples.sets_cat import PrimeNumbers
|
|
704
|
+
sage: class CCls(PrimeNumbers):
|
|
705
|
+
....: def an_element(self):
|
|
706
|
+
....: return 18
|
|
707
|
+
sage: CC = CCls()
|
|
708
|
+
sage: CC._test_an_element()
|
|
709
|
+
Traceback (most recent call last):
|
|
710
|
+
...
|
|
711
|
+
AssertionError: self.an_element() is not in self
|
|
712
|
+
"""
|
|
713
|
+
tester = self._tester(**options)
|
|
714
|
+
SageObject._test_category(self, tester=tester)
|
|
715
|
+
# Tests that self inherits methods from the categories
|
|
716
|
+
if can_assign_class(self):
|
|
717
|
+
# For usual Python classes, that should be done with
|
|
718
|
+
# standard inheritance
|
|
719
|
+
tester.assertTrue(isinstance(self, self.parent().category().element_class))
|
|
720
|
+
else:
|
|
721
|
+
# For extension types we just check that inheritance
|
|
722
|
+
# occurs on a dummy attribute of Sets().ElementMethods
|
|
723
|
+
tester.assertTrue(hasattr(self, "_dummy_attribute"))
|
|
724
|
+
|
|
725
|
+
def _test_eq(self, **options):
|
|
726
|
+
"""
|
|
727
|
+
Test that ``self`` is equal to ``self`` and different to ``None``.
|
|
728
|
+
|
|
729
|
+
See also: :class:`TestSuite`.
|
|
730
|
+
|
|
731
|
+
TESTS::
|
|
732
|
+
|
|
733
|
+
sage: from sage.structure.element import Element
|
|
734
|
+
sage: O = Element(Parent())
|
|
735
|
+
sage: O._test_eq()
|
|
736
|
+
|
|
737
|
+
Let us now write a broken class method::
|
|
738
|
+
|
|
739
|
+
sage: class CCls(Element):
|
|
740
|
+
....: def __eq__(self, other):
|
|
741
|
+
....: return True
|
|
742
|
+
sage: CCls(Parent())._test_eq()
|
|
743
|
+
Traceback (most recent call last):
|
|
744
|
+
...
|
|
745
|
+
AssertionError: broken equality: Generic element of a structure == None
|
|
746
|
+
|
|
747
|
+
Let us now break inequality::
|
|
748
|
+
|
|
749
|
+
sage: class CCls(Element):
|
|
750
|
+
....: def __ne__(self, other):
|
|
751
|
+
....: return True
|
|
752
|
+
sage: CCls(Parent())._test_eq()
|
|
753
|
+
Traceback (most recent call last):
|
|
754
|
+
...
|
|
755
|
+
AssertionError: broken non-equality: Generic element of a structure != itself
|
|
756
|
+
"""
|
|
757
|
+
tester = self._tester(**options)
|
|
758
|
+
# We don't use assertEqual / assertNonEqual in order to be
|
|
759
|
+
# 100% sure we indeed call the operators == and !=, whatever
|
|
760
|
+
# the version of Python is (see #11236)
|
|
761
|
+
tester.assertTrue(self == self,
|
|
762
|
+
LazyFormat("broken equality: %s == itself is False") % self)
|
|
763
|
+
tester.assertFalse(self == None,
|
|
764
|
+
LazyFormat("broken equality: %s == None") % self)
|
|
765
|
+
tester.assertFalse(self != self,
|
|
766
|
+
LazyFormat("broken non-equality: %s != itself") % self)
|
|
767
|
+
tester.assertTrue(self != None,
|
|
768
|
+
LazyFormat("broken non-equality: %s is not != None") % self)
|
|
769
|
+
|
|
770
|
+
def parent(self, x=None):
|
|
771
|
+
"""
|
|
772
|
+
Return the parent of this element; or, if the optional argument x is
|
|
773
|
+
supplied, the result of coercing x into the parent of this element.
|
|
774
|
+
"""
|
|
775
|
+
if x is None:
|
|
776
|
+
return self._parent
|
|
777
|
+
else:
|
|
778
|
+
return self._parent(x)
|
|
779
|
+
|
|
780
|
+
def subs(self, in_dict=None, **kwds):
|
|
781
|
+
"""
|
|
782
|
+
Substitutes given generators with given values while not touching
|
|
783
|
+
other generators.
|
|
784
|
+
|
|
785
|
+
This is a generic wrapper around ``__call__``. The syntax is
|
|
786
|
+
meant to be compatible with the corresponding method for
|
|
787
|
+
symbolic expressions.
|
|
788
|
+
|
|
789
|
+
INPUT:
|
|
790
|
+
|
|
791
|
+
- ``in_dict`` -- (optional) dictionary of inputs
|
|
792
|
+
|
|
793
|
+
- ``**kwds`` -- named parameters
|
|
794
|
+
|
|
795
|
+
OUTPUT: new object if substitution is possible, otherwise ``self``
|
|
796
|
+
|
|
797
|
+
EXAMPLES::
|
|
798
|
+
|
|
799
|
+
sage: x, y = PolynomialRing(ZZ,2,'xy').gens()
|
|
800
|
+
sage: f = x^2 + y + x^2*y^2 + 5
|
|
801
|
+
sage: f((5,y))
|
|
802
|
+
25*y^2 + y + 30
|
|
803
|
+
sage: f.subs({x:5})
|
|
804
|
+
25*y^2 + y + 30
|
|
805
|
+
sage: f.subs(x=5)
|
|
806
|
+
25*y^2 + y + 30
|
|
807
|
+
sage: (1/f).subs(x=5) # needs sage.libs.singular
|
|
808
|
+
1/(25*y^2 + y + 30)
|
|
809
|
+
sage: Integer(5).subs(x=4)
|
|
810
|
+
5
|
|
811
|
+
"""
|
|
812
|
+
if not callable(self):
|
|
813
|
+
return self
|
|
814
|
+
parent = self._parent
|
|
815
|
+
try:
|
|
816
|
+
ngens = parent.ngens()
|
|
817
|
+
except (AttributeError, NotImplementedError, TypeError):
|
|
818
|
+
return self
|
|
819
|
+
variables = []
|
|
820
|
+
|
|
821
|
+
# using gen instead of gens
|
|
822
|
+
for i in range(ngens):
|
|
823
|
+
gen = parent.gen(i)
|
|
824
|
+
if str(gen) in kwds:
|
|
825
|
+
variables.append(kwds[str(gen)])
|
|
826
|
+
elif in_dict and gen in in_dict:
|
|
827
|
+
variables.append(in_dict[gen])
|
|
828
|
+
else:
|
|
829
|
+
variables.append(gen)
|
|
830
|
+
return self(*variables)
|
|
831
|
+
|
|
832
|
+
def substitute(self, *args, **kwds):
|
|
833
|
+
"""
|
|
834
|
+
This calls :meth:`self.subs`.
|
|
835
|
+
|
|
836
|
+
EXAMPLES::
|
|
837
|
+
|
|
838
|
+
sage: x, y = PolynomialRing(ZZ, 2, 'xy').gens()
|
|
839
|
+
sage: f = x^2 + y + x^2*y^2 + 5
|
|
840
|
+
sage: f((5,y))
|
|
841
|
+
25*y^2 + y + 30
|
|
842
|
+
sage: f.substitute({x: 5})
|
|
843
|
+
25*y^2 + y + 30
|
|
844
|
+
sage: f.substitute(x=5)
|
|
845
|
+
25*y^2 + y + 30
|
|
846
|
+
sage: (1/f).substitute(x=5) # needs sage.libs.singular
|
|
847
|
+
1/(25*y^2 + y + 30)
|
|
848
|
+
sage: Integer(5).substitute(x=4)
|
|
849
|
+
5
|
|
850
|
+
"""
|
|
851
|
+
return self.subs(*args, **kwds)
|
|
852
|
+
|
|
853
|
+
def numerical_approx(self, prec=None, digits=None, algorithm=None):
|
|
854
|
+
"""
|
|
855
|
+
Return a numerical approximation of ``self`` with ``prec`` bits
|
|
856
|
+
(or decimal ``digits``) of precision.
|
|
857
|
+
|
|
858
|
+
No guarantee is made about the accuracy of the result.
|
|
859
|
+
|
|
860
|
+
INPUT:
|
|
861
|
+
|
|
862
|
+
- ``prec`` -- precision in bits
|
|
863
|
+
|
|
864
|
+
- ``digits`` -- precision in decimal digits (only used if
|
|
865
|
+
``prec`` is not given)
|
|
866
|
+
|
|
867
|
+
- ``algorithm`` -- which algorithm to use to compute this
|
|
868
|
+
approximation (the accepted algorithms depend on the object)
|
|
869
|
+
|
|
870
|
+
If neither ``prec`` nor ``digits`` is given, the default
|
|
871
|
+
precision is 53 bits (roughly 16 digits).
|
|
872
|
+
|
|
873
|
+
EXAMPLES::
|
|
874
|
+
|
|
875
|
+
sage: (2/3).numerical_approx() # needs sage.rings.real_mpfr
|
|
876
|
+
0.666666666666667
|
|
877
|
+
sage: pi.n(digits=10) # needs sage.symbolic
|
|
878
|
+
3.141592654
|
|
879
|
+
sage: pi.n(prec=20) # needs sage.symbolic
|
|
880
|
+
3.1416
|
|
881
|
+
|
|
882
|
+
TESTS:
|
|
883
|
+
|
|
884
|
+
Check that :issue:`14778` is fixed::
|
|
885
|
+
|
|
886
|
+
sage: (0).n(algorithm='foo') # needs sage.rings.real_mpfr
|
|
887
|
+
0.000000000000000
|
|
888
|
+
"""
|
|
889
|
+
from sage.arith.numerical_approx import numerical_approx_generic
|
|
890
|
+
if prec is None:
|
|
891
|
+
prec = digits_to_bits(digits)
|
|
892
|
+
return numerical_approx_generic(self, prec)
|
|
893
|
+
|
|
894
|
+
def n(self, prec=None, digits=None, algorithm=None):
|
|
895
|
+
"""
|
|
896
|
+
Alias for :meth:`numerical_approx`.
|
|
897
|
+
|
|
898
|
+
EXAMPLES::
|
|
899
|
+
|
|
900
|
+
sage: (2/3).n() # needs sage.rings.real_mpfr
|
|
901
|
+
0.666666666666667
|
|
902
|
+
"""
|
|
903
|
+
return self.numerical_approx(prec, digits, algorithm)
|
|
904
|
+
|
|
905
|
+
def _mpmath_(self, prec=53, rounding=None):
|
|
906
|
+
"""
|
|
907
|
+
Evaluates numerically and returns an mpmath number.
|
|
908
|
+
Used as fallback for conversion by mpmath.mpmathify().
|
|
909
|
+
|
|
910
|
+
.. NOTE::
|
|
911
|
+
|
|
912
|
+
Currently, the rounding mode is ignored.
|
|
913
|
+
|
|
914
|
+
EXAMPLES::
|
|
915
|
+
|
|
916
|
+
sage: # needs mpmath
|
|
917
|
+
sage: from sage.libs.mpmath.all import mp, mpmathify
|
|
918
|
+
sage: mp.dps = 30
|
|
919
|
+
sage: 25._mpmath_(53)
|
|
920
|
+
mpf('25.0')
|
|
921
|
+
sage: mpmathify(3 + 4*I) # needs sage.symbolic
|
|
922
|
+
mpc(real='3.0', imag='4.0')
|
|
923
|
+
sage: mpmathify(1 + pi) # needs sage.symbolic
|
|
924
|
+
mpf('4.14159265358979323846264338327933')
|
|
925
|
+
sage: (1 + pi)._mpmath_(10) # needs sage.symbolic
|
|
926
|
+
mpf('4.140625')
|
|
927
|
+
sage: (1 + pi)._mpmath_(mp.prec) # needs sage.symbolic
|
|
928
|
+
mpf('4.14159265358979323846264338327933')
|
|
929
|
+
"""
|
|
930
|
+
t = self.n(prec)
|
|
931
|
+
from sage.rings.real_mpfr import RealNumber
|
|
932
|
+
from sage.rings.complex_mpfr import ComplexNumber
|
|
933
|
+
if not isinstance(t, (RealNumber, ComplexNumber)):
|
|
934
|
+
# avoid infinite recursion
|
|
935
|
+
raise NotImplementedError("mpmath conversion not implemented for %s" % type(self))
|
|
936
|
+
return t._mpmath_(prec=prec)
|
|
937
|
+
|
|
938
|
+
cpdef _act_on_(self, x, bint self_on_left):
|
|
939
|
+
"""
|
|
940
|
+
Use this method to implement ``self`` acting on ``x``.
|
|
941
|
+
|
|
942
|
+
Return ``None`` or raise a ``CoercionException`` if no
|
|
943
|
+
such action is defined here.
|
|
944
|
+
"""
|
|
945
|
+
return None
|
|
946
|
+
|
|
947
|
+
cpdef _acted_upon_(self, x, bint self_on_left):
|
|
948
|
+
"""
|
|
949
|
+
Use this method to implement ``self`` acted on by x.
|
|
950
|
+
|
|
951
|
+
Return ``None`` or raise a ``CoercionException`` if no
|
|
952
|
+
such action is defined here.
|
|
953
|
+
"""
|
|
954
|
+
return None
|
|
955
|
+
|
|
956
|
+
def __xor__(self, right):
|
|
957
|
+
raise RuntimeError("Use ** for exponentiation, not '^', which means xor\n"
|
|
958
|
+
"in Python, and has the wrong precedence.")
|
|
959
|
+
|
|
960
|
+
def __pos__(self):
|
|
961
|
+
return self
|
|
962
|
+
|
|
963
|
+
def _coeff_repr(self, no_space=True):
|
|
964
|
+
if self._is_atomic():
|
|
965
|
+
s = repr(self)
|
|
966
|
+
else:
|
|
967
|
+
s = "(%s)" % repr(self)
|
|
968
|
+
if no_space:
|
|
969
|
+
return s.replace(' ', '')
|
|
970
|
+
return s
|
|
971
|
+
|
|
972
|
+
def _latex_coeff_repr(self):
|
|
973
|
+
try:
|
|
974
|
+
s = self._latex_()
|
|
975
|
+
except AttributeError:
|
|
976
|
+
s = str(self)
|
|
977
|
+
if self._is_atomic():
|
|
978
|
+
return s
|
|
979
|
+
else:
|
|
980
|
+
return "\\left(%s\\right)" % s
|
|
981
|
+
|
|
982
|
+
def _is_atomic(self):
|
|
983
|
+
"""
|
|
984
|
+
Return ``True`` if and only if parenthesis are not required when
|
|
985
|
+
*printing* out any of `x - s`, `x + s`, `x^s` and `x/s`.
|
|
986
|
+
|
|
987
|
+
EXAMPLES::
|
|
988
|
+
|
|
989
|
+
sage: n = 5; n._is_atomic()
|
|
990
|
+
True
|
|
991
|
+
sage: n = x + 1; n._is_atomic() # needs sage.symbolic
|
|
992
|
+
False
|
|
993
|
+
"""
|
|
994
|
+
if self._parent._repr_option('element_is_atomic'):
|
|
995
|
+
return True
|
|
996
|
+
s = str(self)
|
|
997
|
+
return s.find("+") == -1 and s.find("-") == -1 and s.find(" ") == -1
|
|
998
|
+
|
|
999
|
+
def __bool__(self):
|
|
1000
|
+
r"""
|
|
1001
|
+
Return whether this element is equal to ``self.parent()(0)``.
|
|
1002
|
+
|
|
1003
|
+
Note that this is automatically called when converting to
|
|
1004
|
+
boolean, as in the conditional of an if or while statement.
|
|
1005
|
+
|
|
1006
|
+
EXAMPLES::
|
|
1007
|
+
|
|
1008
|
+
sage: bool(1) # indirect doctest
|
|
1009
|
+
True
|
|
1010
|
+
|
|
1011
|
+
If ``self.parent()(0)`` raises an exception (because there is no
|
|
1012
|
+
meaningful zero element,) then this method returns ``True``. Here,
|
|
1013
|
+
there is no zero morphism of rings that goes to a non-trivial ring::
|
|
1014
|
+
|
|
1015
|
+
sage: bool(Hom(ZZ, Zmod(2)).an_element())
|
|
1016
|
+
True
|
|
1017
|
+
|
|
1018
|
+
But there is a zero morphism to the trivial ring::
|
|
1019
|
+
|
|
1020
|
+
sage: bool(Hom(ZZ, Zmod(1)).an_element())
|
|
1021
|
+
False
|
|
1022
|
+
|
|
1023
|
+
TESTS:
|
|
1024
|
+
|
|
1025
|
+
Verify that :issue:`5185` is fixed::
|
|
1026
|
+
|
|
1027
|
+
sage: # needs sage.modules
|
|
1028
|
+
sage: v = vector({1: 1, 3: -1})
|
|
1029
|
+
sage: w = vector({1: -1, 3: 1})
|
|
1030
|
+
sage: v + w
|
|
1031
|
+
(0, 0, 0, 0)
|
|
1032
|
+
sage: (v + w).is_zero()
|
|
1033
|
+
True
|
|
1034
|
+
sage: bool(v + w)
|
|
1035
|
+
False
|
|
1036
|
+
"""
|
|
1037
|
+
try:
|
|
1038
|
+
zero = self._parent.zero()
|
|
1039
|
+
except Exception:
|
|
1040
|
+
return True # by convention
|
|
1041
|
+
|
|
1042
|
+
return self != zero
|
|
1043
|
+
|
|
1044
|
+
def is_zero(self):
|
|
1045
|
+
"""
|
|
1046
|
+
Return ``True`` if ``self`` equals ``self.parent()(0)``.
|
|
1047
|
+
|
|
1048
|
+
The default implementation is to fall back to ``not
|
|
1049
|
+
self.__bool__``.
|
|
1050
|
+
|
|
1051
|
+
.. WARNING::
|
|
1052
|
+
|
|
1053
|
+
Do not re-implement this method in your subclass but
|
|
1054
|
+
implement ``__bool__`` instead.
|
|
1055
|
+
"""
|
|
1056
|
+
return not self
|
|
1057
|
+
|
|
1058
|
+
def _cache_key(self):
|
|
1059
|
+
"""
|
|
1060
|
+
Provide a hashable key for an element if it is not hashable.
|
|
1061
|
+
|
|
1062
|
+
EXAMPLES::
|
|
1063
|
+
|
|
1064
|
+
sage: a = sage.structure.element.Element(ZZ)
|
|
1065
|
+
sage: a._cache_key()
|
|
1066
|
+
(Integer Ring, 'Generic element of a structure')
|
|
1067
|
+
"""
|
|
1068
|
+
return self.parent(), str(self)
|
|
1069
|
+
|
|
1070
|
+
####################################################################
|
|
1071
|
+
# In a Cython or a Python class, you must define _richcmp_
|
|
1072
|
+
#
|
|
1073
|
+
# Rich comparisons (like a < b) will use _richcmp_
|
|
1074
|
+
#
|
|
1075
|
+
# In the _richcmp_ method, you can assume that both arguments have
|
|
1076
|
+
# identical parents.
|
|
1077
|
+
####################################################################
|
|
1078
|
+
def __richcmp__(self, other, int op):
|
|
1079
|
+
"""
|
|
1080
|
+
Compare ``self`` and ``other`` using the coercion framework,
|
|
1081
|
+
comparing according to the comparison operator ``op``.
|
|
1082
|
+
|
|
1083
|
+
Normally, a class will not redefine ``__richcmp__`` but rely on
|
|
1084
|
+
this ``Element.__richcmp__`` method which uses coercion if
|
|
1085
|
+
needed to compare elements. After coercion (or if no coercion
|
|
1086
|
+
is needed), ``_richcmp_`` is called.
|
|
1087
|
+
|
|
1088
|
+
If a class wants to implement rich comparison without coercion,
|
|
1089
|
+
then ``__richcmp__`` should be defined.
|
|
1090
|
+
See :class:`sage.numerical.linear_functions.LinearConstraint`
|
|
1091
|
+
for such an example.
|
|
1092
|
+
|
|
1093
|
+
For efficiency reasons, a class can do certain "manual"
|
|
1094
|
+
coercions directly in ``__richcmp__``, using
|
|
1095
|
+
``coercion_model.richcmp()`` for the remaining cases.
|
|
1096
|
+
This is done for example in :class:`Integer`.
|
|
1097
|
+
"""
|
|
1098
|
+
if have_same_parent(self, other):
|
|
1099
|
+
# Same parents, in particular self and other must both be
|
|
1100
|
+
# an instance of Element. The explicit casts below make
|
|
1101
|
+
# Cython generate optimized code for this call.
|
|
1102
|
+
return (<Element>self)._richcmp_(other, op)
|
|
1103
|
+
else:
|
|
1104
|
+
return coercion_model.richcmp(self, other, op)
|
|
1105
|
+
|
|
1106
|
+
cpdef _richcmp_(left, right, int op):
|
|
1107
|
+
r"""
|
|
1108
|
+
Basic default implementation of rich comparisons for elements with
|
|
1109
|
+
equal parents.
|
|
1110
|
+
|
|
1111
|
+
It does a comparison by id for ``==`` and ``!=``. Calling this
|
|
1112
|
+
default method with ``<``, ``<=``, ``>`` or ``>=`` will return
|
|
1113
|
+
``NotImplemented``.
|
|
1114
|
+
|
|
1115
|
+
EXAMPLES::
|
|
1116
|
+
|
|
1117
|
+
sage: from sage.structure.parent import Parent
|
|
1118
|
+
sage: from sage.structure.element import Element
|
|
1119
|
+
sage: P = Parent()
|
|
1120
|
+
sage: e1 = Element(P); e2 = Element(P)
|
|
1121
|
+
sage: e1 == e1 # indirect doctest
|
|
1122
|
+
True
|
|
1123
|
+
sage: e1 == e2 # indirect doctest
|
|
1124
|
+
False
|
|
1125
|
+
sage: e1 < e2 # indirect doctest
|
|
1126
|
+
Traceback (most recent call last):
|
|
1127
|
+
...
|
|
1128
|
+
TypeError: '<' not supported between instances of 'sage.structure.element.Element' and 'sage.structure.element.Element'
|
|
1129
|
+
|
|
1130
|
+
We now create an ``Element`` class where we define ``_richcmp_``
|
|
1131
|
+
and check that comparison works::
|
|
1132
|
+
|
|
1133
|
+
sage: # needs sage.misc.cython
|
|
1134
|
+
sage: cython(
|
|
1135
|
+
....: '''
|
|
1136
|
+
....: from sage.structure.richcmp cimport rich_to_bool
|
|
1137
|
+
....: from sage.structure.element cimport Element
|
|
1138
|
+
....: cdef class FloatCmp(Element):
|
|
1139
|
+
....: cdef float x
|
|
1140
|
+
....: def __init__(self, float v):
|
|
1141
|
+
....: self.x = v
|
|
1142
|
+
....: cpdef _richcmp_(self, other, int op):
|
|
1143
|
+
....: cdef float x1 = (<FloatCmp>self).x
|
|
1144
|
+
....: cdef float x2 = (<FloatCmp>other).x
|
|
1145
|
+
....: return rich_to_bool(op, (x1 > x2) - (x1 < x2))
|
|
1146
|
+
....: ''')
|
|
1147
|
+
sage: a = FloatCmp(1)
|
|
1148
|
+
sage: b = FloatCmp(2)
|
|
1149
|
+
sage: a <= b, b <= a
|
|
1150
|
+
(True, False)
|
|
1151
|
+
"""
|
|
1152
|
+
# Obvious case
|
|
1153
|
+
if left is right:
|
|
1154
|
+
return rich_to_bool(op, 0)
|
|
1155
|
+
# Check equality by id(), knowing that left is not right
|
|
1156
|
+
if op == Py_EQ:
|
|
1157
|
+
return False
|
|
1158
|
+
if op == Py_NE:
|
|
1159
|
+
return True
|
|
1160
|
+
return NotImplemented
|
|
1161
|
+
|
|
1162
|
+
cpdef int _cmp_(left, right) except -2:
|
|
1163
|
+
"""
|
|
1164
|
+
This was the old comparison framework. Now deprecated. Do not use.
|
|
1165
|
+
"""
|
|
1166
|
+
deprecation(30130, "please use _richcmp_ for comparison methods")
|
|
1167
|
+
raise NotImplementedError("__cmp__ and _cmp_ are deprecated")
|
|
1168
|
+
|
|
1169
|
+
##################################################
|
|
1170
|
+
# Arithmetic using the coercion model
|
|
1171
|
+
##################################################
|
|
1172
|
+
|
|
1173
|
+
def __add__(left, right):
|
|
1174
|
+
"""
|
|
1175
|
+
Top-level addition operator for :class:`Element` invoking
|
|
1176
|
+
the coercion model.
|
|
1177
|
+
|
|
1178
|
+
See :ref:`element_arithmetic`.
|
|
1179
|
+
|
|
1180
|
+
EXAMPLES::
|
|
1181
|
+
|
|
1182
|
+
sage: from sage.structure.element import Element
|
|
1183
|
+
sage: class MyElement(Element):
|
|
1184
|
+
....: def _add_(self, other):
|
|
1185
|
+
....: return 42
|
|
1186
|
+
sage: e = MyElement(Parent())
|
|
1187
|
+
sage: e + e
|
|
1188
|
+
42
|
|
1189
|
+
|
|
1190
|
+
TESTS::
|
|
1191
|
+
|
|
1192
|
+
sage: e = Element(Parent())
|
|
1193
|
+
sage: e + e
|
|
1194
|
+
Traceback (most recent call last):
|
|
1195
|
+
...
|
|
1196
|
+
TypeError: unsupported operand parent(s) for +: '<sage.structure.parent.Parent object at ...>' and '<sage.structure.parent.Parent object at ...>'
|
|
1197
|
+
sage: 1 + e
|
|
1198
|
+
Traceback (most recent call last):
|
|
1199
|
+
...
|
|
1200
|
+
TypeError: unsupported operand parent(s) for +: 'Integer Ring' and '<sage.structure.parent.Parent object at ...>'
|
|
1201
|
+
sage: e + 1
|
|
1202
|
+
Traceback (most recent call last):
|
|
1203
|
+
...
|
|
1204
|
+
TypeError: unsupported operand parent(s) for +: '<sage.structure.parent.Parent object at ...>' and 'Integer Ring'
|
|
1205
|
+
sage: int(1) + e
|
|
1206
|
+
Traceback (most recent call last):
|
|
1207
|
+
...
|
|
1208
|
+
TypeError: unsupported operand type(s) for +: 'int' and 'sage.structure.element.Element'
|
|
1209
|
+
sage: e + int(1)
|
|
1210
|
+
Traceback (most recent call last):
|
|
1211
|
+
...
|
|
1212
|
+
TypeError: unsupported operand type(s) for +: 'sage.structure.element.Element' and 'int'
|
|
1213
|
+
sage: None + e
|
|
1214
|
+
Traceback (most recent call last):
|
|
1215
|
+
...
|
|
1216
|
+
TypeError: unsupported operand type(s) for +: 'NoneType' and 'sage.structure.element.Element'
|
|
1217
|
+
sage: e + None
|
|
1218
|
+
Traceback (most recent call last):
|
|
1219
|
+
...
|
|
1220
|
+
TypeError: unsupported operand type(s) for +: 'sage.structure.element.Element' and 'NoneType'
|
|
1221
|
+
"""
|
|
1222
|
+
cdef int cl = classify_elements(left, right)
|
|
1223
|
+
if HAVE_SAME_PARENT(cl):
|
|
1224
|
+
return (<Element>left)._add_(right)
|
|
1225
|
+
# Left and right are Sage elements => use coercion model
|
|
1226
|
+
if BOTH_ARE_ELEMENT(cl):
|
|
1227
|
+
return coercion_model.bin_op(left, right, add)
|
|
1228
|
+
|
|
1229
|
+
cdef long value
|
|
1230
|
+
cdef int err = -1
|
|
1231
|
+
try:
|
|
1232
|
+
# Special case addition with Python int
|
|
1233
|
+
integer_check_long_py(right, &value, &err)
|
|
1234
|
+
if not err:
|
|
1235
|
+
return (<Element>left)._add_long(value)
|
|
1236
|
+
integer_check_long_py(left, &value, &err)
|
|
1237
|
+
if not err:
|
|
1238
|
+
return (<Element>right)._add_long(value)
|
|
1239
|
+
return coercion_model.bin_op(left, right, add)
|
|
1240
|
+
except TypeError:
|
|
1241
|
+
# Either coercion failed or arithmetic is not defined.
|
|
1242
|
+
#
|
|
1243
|
+
# According to the Python convention, we should return
|
|
1244
|
+
# NotImplemented now. This will cause Python to try the
|
|
1245
|
+
# reversed addition (__radd__).
|
|
1246
|
+
return NotImplemented
|
|
1247
|
+
|
|
1248
|
+
cdef _add_(self, other):
|
|
1249
|
+
"""
|
|
1250
|
+
Virtual addition method for elements with identical parents.
|
|
1251
|
+
|
|
1252
|
+
This default Cython implementation of ``_add_`` calls the
|
|
1253
|
+
Python method ``self._add_`` if it exists. This method may be
|
|
1254
|
+
defined in the ``ElementMethods`` of the category of the parent.
|
|
1255
|
+
If the method is not found, a :exc:`TypeError` is raised
|
|
1256
|
+
indicating that the operation is not supported.
|
|
1257
|
+
|
|
1258
|
+
See :ref:`element_arithmetic`.
|
|
1259
|
+
|
|
1260
|
+
EXAMPLES:
|
|
1261
|
+
|
|
1262
|
+
This method is not visible from Python::
|
|
1263
|
+
|
|
1264
|
+
sage: from sage.structure.element import Element
|
|
1265
|
+
sage: e = Element(Parent())
|
|
1266
|
+
sage: e._add_(e)
|
|
1267
|
+
Traceback (most recent call last):
|
|
1268
|
+
...
|
|
1269
|
+
AttributeError: 'sage.structure.element.Element' object has no attribute '_add_'...
|
|
1270
|
+
"""
|
|
1271
|
+
try:
|
|
1272
|
+
python_op = (<object>self)._add_
|
|
1273
|
+
except AttributeError:
|
|
1274
|
+
raise bin_op_exception('+', self, other)
|
|
1275
|
+
else:
|
|
1276
|
+
return python_op(other)
|
|
1277
|
+
|
|
1278
|
+
cdef _add_long(self, long n):
|
|
1279
|
+
"""
|
|
1280
|
+
Generic path for adding a C long, assumed to commute.
|
|
1281
|
+
|
|
1282
|
+
EXAMPLES::
|
|
1283
|
+
|
|
1284
|
+
sage: # needs sage.misc.cython
|
|
1285
|
+
sage: cython( # long time
|
|
1286
|
+
....: '''
|
|
1287
|
+
....: from sage.structure.element cimport Element
|
|
1288
|
+
....: cdef class MyElement(Element):
|
|
1289
|
+
....: cdef _add_long(self, long n):
|
|
1290
|
+
....: return n
|
|
1291
|
+
....: ''')
|
|
1292
|
+
sage: e = MyElement(Parent()) # long time
|
|
1293
|
+
sage: i = int(42)
|
|
1294
|
+
sage: i + e, e + i # long time
|
|
1295
|
+
(42, 42)
|
|
1296
|
+
"""
|
|
1297
|
+
return coercion_model.bin_op(self, n, add)
|
|
1298
|
+
|
|
1299
|
+
def __sub__(left, right):
|
|
1300
|
+
"""
|
|
1301
|
+
Top-level subtraction operator for :class:`Element` invoking
|
|
1302
|
+
the coercion model.
|
|
1303
|
+
|
|
1304
|
+
See :ref:`element_arithmetic`.
|
|
1305
|
+
|
|
1306
|
+
EXAMPLES::
|
|
1307
|
+
|
|
1308
|
+
sage: from sage.structure.element import Element
|
|
1309
|
+
sage: class MyElement(Element):
|
|
1310
|
+
....: def _sub_(self, other):
|
|
1311
|
+
....: return 42
|
|
1312
|
+
sage: e = MyElement(Parent())
|
|
1313
|
+
sage: e - e
|
|
1314
|
+
42
|
|
1315
|
+
|
|
1316
|
+
TESTS::
|
|
1317
|
+
|
|
1318
|
+
sage: e = Element(Parent())
|
|
1319
|
+
sage: e - e
|
|
1320
|
+
Traceback (most recent call last):
|
|
1321
|
+
...
|
|
1322
|
+
TypeError: unsupported operand parent(s) for -: '<sage.structure.parent.Parent object at ...>' and '<sage.structure.parent.Parent object at ...>'
|
|
1323
|
+
sage: 1 - e
|
|
1324
|
+
Traceback (most recent call last):
|
|
1325
|
+
...
|
|
1326
|
+
TypeError: unsupported operand parent(s) for -: 'Integer Ring' and '<sage.structure.parent.Parent object at ...>'
|
|
1327
|
+
sage: e - 1
|
|
1328
|
+
Traceback (most recent call last):
|
|
1329
|
+
...
|
|
1330
|
+
TypeError: unsupported operand parent(s) for -: '<sage.structure.parent.Parent object at ...>' and 'Integer Ring'
|
|
1331
|
+
sage: int(1) - e
|
|
1332
|
+
Traceback (most recent call last):
|
|
1333
|
+
...
|
|
1334
|
+
TypeError: unsupported operand type(s) for -: 'int' and 'sage.structure.element.Element'
|
|
1335
|
+
sage: e - int(1)
|
|
1336
|
+
Traceback (most recent call last):
|
|
1337
|
+
...
|
|
1338
|
+
TypeError: unsupported operand type(s) for -: 'sage.structure.element.Element' and 'int'
|
|
1339
|
+
sage: None - e
|
|
1340
|
+
Traceback (most recent call last):
|
|
1341
|
+
...
|
|
1342
|
+
TypeError: unsupported operand type(s) for -: 'NoneType' and 'sage.structure.element.Element'
|
|
1343
|
+
sage: e - None
|
|
1344
|
+
Traceback (most recent call last):
|
|
1345
|
+
...
|
|
1346
|
+
TypeError: unsupported operand type(s) for -: 'sage.structure.element.Element' and 'NoneType'
|
|
1347
|
+
"""
|
|
1348
|
+
# See __add__ for comments
|
|
1349
|
+
cdef int cl = classify_elements(left, right)
|
|
1350
|
+
if HAVE_SAME_PARENT(cl):
|
|
1351
|
+
return (<Element>left)._sub_(right)
|
|
1352
|
+
if BOTH_ARE_ELEMENT(cl):
|
|
1353
|
+
return coercion_model.bin_op(left, right, sub)
|
|
1354
|
+
|
|
1355
|
+
try:
|
|
1356
|
+
return coercion_model.bin_op(left, right, sub)
|
|
1357
|
+
except TypeError:
|
|
1358
|
+
return NotImplemented
|
|
1359
|
+
|
|
1360
|
+
cdef _sub_(self, other):
|
|
1361
|
+
"""
|
|
1362
|
+
Virtual subtraction method for elements with identical parents.
|
|
1363
|
+
|
|
1364
|
+
This default Cython implementation of ``_sub_`` calls the
|
|
1365
|
+
Python method ``self._sub_`` if it exists. This method may be
|
|
1366
|
+
defined in the ``ElementMethods`` of the category of the parent.
|
|
1367
|
+
If the method is not found, a :exc:`TypeError` is raised
|
|
1368
|
+
indicating that the operation is not supported.
|
|
1369
|
+
|
|
1370
|
+
See :ref:`element_arithmetic`.
|
|
1371
|
+
|
|
1372
|
+
EXAMPLES:
|
|
1373
|
+
|
|
1374
|
+
This method is not visible from Python::
|
|
1375
|
+
|
|
1376
|
+
sage: from sage.structure.element import Element
|
|
1377
|
+
sage: e = Element(Parent())
|
|
1378
|
+
sage: e._sub_(e)
|
|
1379
|
+
Traceback (most recent call last):
|
|
1380
|
+
...
|
|
1381
|
+
AttributeError: 'sage.structure.element.Element' object has no attribute '_sub_'...
|
|
1382
|
+
"""
|
|
1383
|
+
try:
|
|
1384
|
+
python_op = (<object>self)._sub_
|
|
1385
|
+
except AttributeError:
|
|
1386
|
+
raise bin_op_exception('-', self, other)
|
|
1387
|
+
else:
|
|
1388
|
+
return python_op(other)
|
|
1389
|
+
|
|
1390
|
+
def __neg__(self):
|
|
1391
|
+
"""
|
|
1392
|
+
Top-level negation operator for :class:`Element`.
|
|
1393
|
+
|
|
1394
|
+
EXAMPLES::
|
|
1395
|
+
|
|
1396
|
+
sage: from sage.structure.element import Element
|
|
1397
|
+
sage: class MyElement(Element):
|
|
1398
|
+
....: def _neg_(self):
|
|
1399
|
+
....: return 42
|
|
1400
|
+
sage: e = MyElement(Parent())
|
|
1401
|
+
sage: -e
|
|
1402
|
+
42
|
|
1403
|
+
|
|
1404
|
+
TESTS::
|
|
1405
|
+
|
|
1406
|
+
sage: e = Element(Parent())
|
|
1407
|
+
sage: -e
|
|
1408
|
+
Traceback (most recent call last):
|
|
1409
|
+
...
|
|
1410
|
+
TypeError: unsupported operand parent for unary -: '<sage.structure.parent.Parent object at ...>'
|
|
1411
|
+
"""
|
|
1412
|
+
return self._neg_()
|
|
1413
|
+
|
|
1414
|
+
cdef _neg_(self):
|
|
1415
|
+
"""
|
|
1416
|
+
Virtual unary negation method for elements.
|
|
1417
|
+
|
|
1418
|
+
This default Cython implementation of ``_neg_`` calls the
|
|
1419
|
+
Python method ``self._neg_`` if it exists. This method may be
|
|
1420
|
+
defined in the ``ElementMethods`` of the category of the parent.
|
|
1421
|
+
If the method is not found, a :exc:`TypeError` is raised
|
|
1422
|
+
indicating that the operation is not supported.
|
|
1423
|
+
|
|
1424
|
+
See :ref:`element_arithmetic`.
|
|
1425
|
+
|
|
1426
|
+
EXAMPLES:
|
|
1427
|
+
|
|
1428
|
+
This method is not visible from Python::
|
|
1429
|
+
|
|
1430
|
+
sage: from sage.structure.element import Element
|
|
1431
|
+
sage: e = Element(Parent())
|
|
1432
|
+
sage: e._neg_()
|
|
1433
|
+
Traceback (most recent call last):
|
|
1434
|
+
...
|
|
1435
|
+
AttributeError: 'sage.structure.element.Element' object has no attribute '_neg_'...
|
|
1436
|
+
"""
|
|
1437
|
+
try:
|
|
1438
|
+
python_op = (<object>self)._neg_
|
|
1439
|
+
except AttributeError:
|
|
1440
|
+
raise unary_op_exception('unary -', self)
|
|
1441
|
+
else:
|
|
1442
|
+
return python_op()
|
|
1443
|
+
|
|
1444
|
+
def __mul__(left, right):
|
|
1445
|
+
"""
|
|
1446
|
+
Top-level multiplication operator for :class:`Element` invoking
|
|
1447
|
+
the coercion model.
|
|
1448
|
+
|
|
1449
|
+
See :ref:`element_arithmetic`.
|
|
1450
|
+
|
|
1451
|
+
EXAMPLES::
|
|
1452
|
+
|
|
1453
|
+
sage: from sage.structure.element import Element
|
|
1454
|
+
sage: class MyElement(Element):
|
|
1455
|
+
....: def _mul_(self, other):
|
|
1456
|
+
....: return 42
|
|
1457
|
+
sage: e = MyElement(Parent())
|
|
1458
|
+
sage: e * e
|
|
1459
|
+
42
|
|
1460
|
+
|
|
1461
|
+
TESTS::
|
|
1462
|
+
|
|
1463
|
+
sage: e = Element(Parent())
|
|
1464
|
+
sage: e * e
|
|
1465
|
+
Traceback (most recent call last):
|
|
1466
|
+
...
|
|
1467
|
+
TypeError: unsupported operand parent(s) for *: '<sage.structure.parent.Parent object at ...>' and '<sage.structure.parent.Parent object at ...>'
|
|
1468
|
+
sage: 1 * e
|
|
1469
|
+
Traceback (most recent call last):
|
|
1470
|
+
...
|
|
1471
|
+
TypeError: unsupported operand parent(s) for *: 'Integer Ring' and '<sage.structure.parent.Parent object at ...>'
|
|
1472
|
+
sage: e * 1
|
|
1473
|
+
Traceback (most recent call last):
|
|
1474
|
+
...
|
|
1475
|
+
TypeError: unsupported operand parent(s) for *: '<sage.structure.parent.Parent object at ...>' and 'Integer Ring'
|
|
1476
|
+
sage: int(1) * e
|
|
1477
|
+
Traceback (most recent call last):
|
|
1478
|
+
...
|
|
1479
|
+
TypeError: unsupported operand type(s) for *: 'int' and 'sage.structure.element.Element'
|
|
1480
|
+
sage: e * int(1)
|
|
1481
|
+
Traceback (most recent call last):
|
|
1482
|
+
...
|
|
1483
|
+
TypeError: unsupported operand type(s) for *: 'sage.structure.element.Element' and 'int'
|
|
1484
|
+
sage: None * e
|
|
1485
|
+
Traceback (most recent call last):
|
|
1486
|
+
...
|
|
1487
|
+
TypeError: unsupported operand type(s) for *: 'NoneType' and 'sage.structure.element.Element'
|
|
1488
|
+
sage: e * None
|
|
1489
|
+
Traceback (most recent call last):
|
|
1490
|
+
...
|
|
1491
|
+
TypeError: unsupported operand type(s) for *: 'sage.structure.element.Element' and 'NoneType'
|
|
1492
|
+
|
|
1493
|
+
::
|
|
1494
|
+
|
|
1495
|
+
sage: # needs sage.combinat sage.modules
|
|
1496
|
+
sage: A = AlgebrasWithBasis(QQ).example(); A
|
|
1497
|
+
An example of an algebra with basis: the free algebra
|
|
1498
|
+
on the generators ('a', 'b', 'c') over Rational Field
|
|
1499
|
+
sage: x = A.an_element()
|
|
1500
|
+
sage: x
|
|
1501
|
+
B[word: ] + 2*B[word: a] + 3*B[word: b] + B[word: bab]
|
|
1502
|
+
sage: x.__mul__(x)
|
|
1503
|
+
B[word: ] + 4*B[word: a] + 4*B[word: aa] + 6*B[word: ab]
|
|
1504
|
+
+ 2*B[word: abab] + 6*B[word: b] + 6*B[word: ba]
|
|
1505
|
+
+ 2*B[word: bab] + 2*B[word: baba] + 3*B[word: babb]
|
|
1506
|
+
+ B[word: babbab] + 9*B[word: bb] + 3*B[word: bbab]
|
|
1507
|
+
"""
|
|
1508
|
+
cdef int cl = classify_elements(left, right)
|
|
1509
|
+
if HAVE_SAME_PARENT(cl):
|
|
1510
|
+
return (<Element>left)._mul_(right)
|
|
1511
|
+
if BOTH_ARE_ELEMENT(cl):
|
|
1512
|
+
return coercion_model.bin_op(left, right, mul)
|
|
1513
|
+
|
|
1514
|
+
cdef long value
|
|
1515
|
+
cdef int err = -1
|
|
1516
|
+
try:
|
|
1517
|
+
# Special case multiplication with Python int
|
|
1518
|
+
integer_check_long_py(right, &value, &err)
|
|
1519
|
+
if not err:
|
|
1520
|
+
return (<Element>left)._mul_long(value)
|
|
1521
|
+
integer_check_long_py(left, &value, &err)
|
|
1522
|
+
if not err:
|
|
1523
|
+
return (<Element>right)._mul_long(value)
|
|
1524
|
+
return coercion_model.bin_op(left, right, mul)
|
|
1525
|
+
except TypeError:
|
|
1526
|
+
return NotImplemented
|
|
1527
|
+
|
|
1528
|
+
cdef _mul_(self, other):
|
|
1529
|
+
"""
|
|
1530
|
+
Virtual multiplication method for elements with identical parents.
|
|
1531
|
+
|
|
1532
|
+
This default Cython implementation of ``_mul_`` calls the
|
|
1533
|
+
Python method ``self._mul_`` if it exists. This method may be
|
|
1534
|
+
defined in the ``ElementMethods`` of the category of the parent.
|
|
1535
|
+
If the method is not found, a :exc:`TypeError` is raised
|
|
1536
|
+
indicating that the operation is not supported.
|
|
1537
|
+
|
|
1538
|
+
See :ref:`element_arithmetic`.
|
|
1539
|
+
|
|
1540
|
+
EXAMPLES:
|
|
1541
|
+
|
|
1542
|
+
This method is not visible from Python::
|
|
1543
|
+
|
|
1544
|
+
sage: from sage.structure.element import Element
|
|
1545
|
+
sage: e = Element(Parent())
|
|
1546
|
+
sage: e._mul_(e)
|
|
1547
|
+
Traceback (most recent call last):
|
|
1548
|
+
...
|
|
1549
|
+
AttributeError: 'sage.structure.element.Element' object has no attribute '_mul_'...
|
|
1550
|
+
"""
|
|
1551
|
+
try:
|
|
1552
|
+
python_op = (<object>self)._mul_
|
|
1553
|
+
except AttributeError:
|
|
1554
|
+
raise bin_op_exception('*', self, other)
|
|
1555
|
+
else:
|
|
1556
|
+
return python_op(other)
|
|
1557
|
+
|
|
1558
|
+
cdef _mul_long(self, long n):
|
|
1559
|
+
"""
|
|
1560
|
+
Generic path for multiplying by a C long, assumed to commute.
|
|
1561
|
+
|
|
1562
|
+
EXAMPLES::
|
|
1563
|
+
|
|
1564
|
+
sage: # needs sage.misc.cython
|
|
1565
|
+
sage: cython( # long time
|
|
1566
|
+
....: '''
|
|
1567
|
+
....: from sage.structure.element cimport Element
|
|
1568
|
+
....: cdef class MyElement(Element):
|
|
1569
|
+
....: cdef _mul_long(self, long n):
|
|
1570
|
+
....: return n
|
|
1571
|
+
....: ''')
|
|
1572
|
+
sage: e = MyElement(Parent()) # long time
|
|
1573
|
+
sage: i = int(42)
|
|
1574
|
+
sage: i * e, e * i # long time
|
|
1575
|
+
(42, 42)
|
|
1576
|
+
"""
|
|
1577
|
+
return coercion_model.bin_op(self, n, mul)
|
|
1578
|
+
|
|
1579
|
+
def __matmul__(left, right):
|
|
1580
|
+
"""
|
|
1581
|
+
Top-level matrix multiplication operator for :class:`Element`
|
|
1582
|
+
invoking the coercion model.
|
|
1583
|
+
|
|
1584
|
+
See :ref:`element_arithmetic`.
|
|
1585
|
+
|
|
1586
|
+
EXAMPLES::
|
|
1587
|
+
|
|
1588
|
+
sage: from sage.structure.element import Element
|
|
1589
|
+
sage: class MyElement(Element):
|
|
1590
|
+
....: def _matmul_(self, other):
|
|
1591
|
+
....: return 42
|
|
1592
|
+
sage: e = MyElement(Parent())
|
|
1593
|
+
sage: from operator import matmul
|
|
1594
|
+
sage: matmul(e, e)
|
|
1595
|
+
42
|
|
1596
|
+
|
|
1597
|
+
TESTS::
|
|
1598
|
+
|
|
1599
|
+
sage: e = Element(Parent())
|
|
1600
|
+
sage: matmul(e, e)
|
|
1601
|
+
Traceback (most recent call last):
|
|
1602
|
+
...
|
|
1603
|
+
TypeError: unsupported operand parent(s) for @: '<sage.structure.parent.Parent object at ...>' and '<sage.structure.parent.Parent object at ...>'
|
|
1604
|
+
sage: matmul(1, e)
|
|
1605
|
+
Traceback (most recent call last):
|
|
1606
|
+
...
|
|
1607
|
+
TypeError: unsupported operand parent(s) for @: 'Integer Ring' and '<sage.structure.parent.Parent object at ...>'
|
|
1608
|
+
sage: matmul(e, 1)
|
|
1609
|
+
Traceback (most recent call last):
|
|
1610
|
+
...
|
|
1611
|
+
TypeError: unsupported operand parent(s) for @: '<sage.structure.parent.Parent object at ...>' and 'Integer Ring'
|
|
1612
|
+
sage: matmul(int(1), e)
|
|
1613
|
+
Traceback (most recent call last):
|
|
1614
|
+
...
|
|
1615
|
+
TypeError: unsupported operand type(s) for @: 'int' and 'sage.structure.element.Element'
|
|
1616
|
+
sage: matmul(e, int(1))
|
|
1617
|
+
Traceback (most recent call last):
|
|
1618
|
+
...
|
|
1619
|
+
TypeError: unsupported operand type(s) for @: 'sage.structure.element.Element' and 'int'
|
|
1620
|
+
sage: matmul(None, e)
|
|
1621
|
+
Traceback (most recent call last):
|
|
1622
|
+
...
|
|
1623
|
+
TypeError: unsupported operand type(s) for @: 'NoneType' and 'sage.structure.element.Element'
|
|
1624
|
+
sage: matmul(e, None)
|
|
1625
|
+
Traceback (most recent call last):
|
|
1626
|
+
...
|
|
1627
|
+
TypeError: unsupported operand type(s) for @: 'sage.structure.element.Element' and 'NoneType'
|
|
1628
|
+
"""
|
|
1629
|
+
cdef int cl = classify_elements(left, right)
|
|
1630
|
+
if HAVE_SAME_PARENT(cl):
|
|
1631
|
+
return (<Element>left)._matmul_(right)
|
|
1632
|
+
if BOTH_ARE_ELEMENT(cl):
|
|
1633
|
+
return coercion_model.bin_op(left, right, matmul)
|
|
1634
|
+
|
|
1635
|
+
try:
|
|
1636
|
+
return coercion_model.bin_op(left, right, matmul)
|
|
1637
|
+
except TypeError:
|
|
1638
|
+
return NotImplemented
|
|
1639
|
+
|
|
1640
|
+
cdef _matmul_(self, other):
|
|
1641
|
+
"""
|
|
1642
|
+
Virtual matrix multiplication method for elements with
|
|
1643
|
+
identical parents.
|
|
1644
|
+
|
|
1645
|
+
This default Cython implementation of ``_matmul_`` calls the
|
|
1646
|
+
Python method ``self._matmul_`` if it exists. This method may
|
|
1647
|
+
be defined in the ``ElementMethods`` of the category of the
|
|
1648
|
+
parent. If the method is not found, a :exc:`TypeError` is raised
|
|
1649
|
+
indicating that the operation is not supported.
|
|
1650
|
+
|
|
1651
|
+
See :ref:`element_arithmetic`.
|
|
1652
|
+
|
|
1653
|
+
EXAMPLES:
|
|
1654
|
+
|
|
1655
|
+
This method is not visible from Python::
|
|
1656
|
+
|
|
1657
|
+
sage: from sage.structure.element import Element
|
|
1658
|
+
sage: e = Element(Parent())
|
|
1659
|
+
sage: e._matmul_(e)
|
|
1660
|
+
Traceback (most recent call last):
|
|
1661
|
+
...
|
|
1662
|
+
AttributeError: 'sage.structure.element.Element' object has no attribute '_matmul_'...
|
|
1663
|
+
"""
|
|
1664
|
+
try:
|
|
1665
|
+
python_op = (<object>self)._matmul_
|
|
1666
|
+
except AttributeError:
|
|
1667
|
+
raise bin_op_exception('@', self, other)
|
|
1668
|
+
else:
|
|
1669
|
+
return python_op(other)
|
|
1670
|
+
|
|
1671
|
+
def __truediv__(left, right):
|
|
1672
|
+
"""
|
|
1673
|
+
Top-level true division operator for :class:`Element` invoking
|
|
1674
|
+
the coercion model.
|
|
1675
|
+
|
|
1676
|
+
See :ref:`element_arithmetic`.
|
|
1677
|
+
|
|
1678
|
+
EXAMPLES::
|
|
1679
|
+
|
|
1680
|
+
sage: operator.truediv(2, 3)
|
|
1681
|
+
2/3
|
|
1682
|
+
sage: operator.truediv(pi, 3) # needs sage.symbolic
|
|
1683
|
+
1/3*pi
|
|
1684
|
+
sage: x = polygen(QQ, 'x')
|
|
1685
|
+
sage: K.<i> = NumberField(x^2 + 1) # needs sage.rings.number_field
|
|
1686
|
+
sage: operator.truediv(2, K.ideal(i + 1)) # needs sage.rings.number_field
|
|
1687
|
+
Fractional ideal (-i + 1)
|
|
1688
|
+
|
|
1689
|
+
::
|
|
1690
|
+
|
|
1691
|
+
sage: from sage.structure.element import Element
|
|
1692
|
+
sage: class MyElement(Element):
|
|
1693
|
+
....: def _div_(self, other):
|
|
1694
|
+
....: return 42
|
|
1695
|
+
sage: e = MyElement(Parent())
|
|
1696
|
+
sage: operator.truediv(e, e)
|
|
1697
|
+
42
|
|
1698
|
+
|
|
1699
|
+
TESTS::
|
|
1700
|
+
|
|
1701
|
+
sage: e = Element(Parent())
|
|
1702
|
+
sage: operator.truediv(e, e)
|
|
1703
|
+
Traceback (most recent call last):
|
|
1704
|
+
...
|
|
1705
|
+
TypeError: unsupported operand parent(s) for /: '<sage.structure.parent.Parent object at ...>' and '<sage.structure.parent.Parent object at ...>'
|
|
1706
|
+
sage: operator.truediv(1, e)
|
|
1707
|
+
Traceback (most recent call last):
|
|
1708
|
+
...
|
|
1709
|
+
TypeError: unsupported operand parent(s) for /: 'Integer Ring' and '<sage.structure.parent.Parent object at ...>'
|
|
1710
|
+
sage: operator.truediv(e, 1)
|
|
1711
|
+
Traceback (most recent call last):
|
|
1712
|
+
...
|
|
1713
|
+
TypeError: unsupported operand parent(s) for /: '<sage.structure.parent.Parent object at ...>' and 'Integer Ring'
|
|
1714
|
+
sage: operator.truediv(int(1), e)
|
|
1715
|
+
Traceback (most recent call last):
|
|
1716
|
+
...
|
|
1717
|
+
TypeError: unsupported operand type(s) for /: 'int' and 'sage.structure.element.Element'
|
|
1718
|
+
sage: operator.truediv(e, int(1))
|
|
1719
|
+
Traceback (most recent call last):
|
|
1720
|
+
...
|
|
1721
|
+
TypeError: unsupported operand type(s) for /: 'sage.structure.element.Element' and 'int'
|
|
1722
|
+
sage: operator.truediv(None, e)
|
|
1723
|
+
Traceback (most recent call last):
|
|
1724
|
+
...
|
|
1725
|
+
TypeError: unsupported operand type(s) for /: 'NoneType' and 'sage.structure.element.Element'
|
|
1726
|
+
sage: operator.truediv(e, None)
|
|
1727
|
+
Traceback (most recent call last):
|
|
1728
|
+
...
|
|
1729
|
+
TypeError: unsupported operand type(s) for /: 'sage.structure.element.Element' and 'NoneType'
|
|
1730
|
+
"""
|
|
1731
|
+
# See __add__ for comments
|
|
1732
|
+
cdef int cl = classify_elements(left, right)
|
|
1733
|
+
if HAVE_SAME_PARENT(cl):
|
|
1734
|
+
return (<Element>left)._div_(right)
|
|
1735
|
+
if BOTH_ARE_ELEMENT(cl):
|
|
1736
|
+
return coercion_model.bin_op(left, right, truediv)
|
|
1737
|
+
|
|
1738
|
+
try:
|
|
1739
|
+
return coercion_model.bin_op(left, right, truediv)
|
|
1740
|
+
except TypeError:
|
|
1741
|
+
return NotImplemented
|
|
1742
|
+
|
|
1743
|
+
cdef _div_(self, other):
|
|
1744
|
+
"""
|
|
1745
|
+
Virtual division method for elements with identical parents.
|
|
1746
|
+
This is called for Python 2 division as well as true division.
|
|
1747
|
+
|
|
1748
|
+
This default Cython implementation of ``_div_`` calls the
|
|
1749
|
+
Python method ``self._div_`` if it exists. This method may be
|
|
1750
|
+
defined in the ``ElementMethods`` of the category of the parent.
|
|
1751
|
+
If the method is not found, a :exc:`TypeError` is raised
|
|
1752
|
+
indicating that the operation is not supported.
|
|
1753
|
+
|
|
1754
|
+
See :ref:`element_arithmetic`.
|
|
1755
|
+
|
|
1756
|
+
EXAMPLES:
|
|
1757
|
+
|
|
1758
|
+
This method is not visible from Python::
|
|
1759
|
+
|
|
1760
|
+
sage: from sage.structure.element import Element
|
|
1761
|
+
sage: e = Element(Parent())
|
|
1762
|
+
sage: e._div_(e)
|
|
1763
|
+
Traceback (most recent call last):
|
|
1764
|
+
...
|
|
1765
|
+
AttributeError: 'sage.structure.element.Element' object has no attribute '_div_'...
|
|
1766
|
+
"""
|
|
1767
|
+
try:
|
|
1768
|
+
python_op = (<object>self)._div_
|
|
1769
|
+
except AttributeError:
|
|
1770
|
+
raise bin_op_exception('/', self, other)
|
|
1771
|
+
else:
|
|
1772
|
+
return python_op(other)
|
|
1773
|
+
|
|
1774
|
+
def __floordiv__(left, right):
|
|
1775
|
+
"""
|
|
1776
|
+
Top-level floor division operator for :class:`Element` invoking
|
|
1777
|
+
the coercion model.
|
|
1778
|
+
|
|
1779
|
+
See :ref:`element_arithmetic`.
|
|
1780
|
+
|
|
1781
|
+
EXAMPLES::
|
|
1782
|
+
|
|
1783
|
+
sage: 7 // 3
|
|
1784
|
+
2
|
|
1785
|
+
sage: 7 // int(3)
|
|
1786
|
+
2
|
|
1787
|
+
sage: int(7) // 3
|
|
1788
|
+
2
|
|
1789
|
+
|
|
1790
|
+
::
|
|
1791
|
+
|
|
1792
|
+
sage: from sage.structure.element import Element
|
|
1793
|
+
sage: class MyElement(Element):
|
|
1794
|
+
....: def _floordiv_(self, other):
|
|
1795
|
+
....: return 42
|
|
1796
|
+
sage: e = MyElement(Parent())
|
|
1797
|
+
sage: e // e
|
|
1798
|
+
42
|
|
1799
|
+
|
|
1800
|
+
TESTS::
|
|
1801
|
+
|
|
1802
|
+
sage: e = Element(Parent())
|
|
1803
|
+
sage: e // e
|
|
1804
|
+
Traceback (most recent call last):
|
|
1805
|
+
...
|
|
1806
|
+
TypeError: unsupported operand parent(s) for //: '<sage.structure.parent.Parent object at ...>' and '<sage.structure.parent.Parent object at ...>'
|
|
1807
|
+
sage: 1 // e
|
|
1808
|
+
Traceback (most recent call last):
|
|
1809
|
+
...
|
|
1810
|
+
TypeError: unsupported operand parent(s) for //: 'Integer Ring' and '<sage.structure.parent.Parent object at ...>'
|
|
1811
|
+
sage: e // 1
|
|
1812
|
+
Traceback (most recent call last):
|
|
1813
|
+
...
|
|
1814
|
+
TypeError: unsupported operand parent(s) for //: '<sage.structure.parent.Parent object at ...>' and 'Integer Ring'
|
|
1815
|
+
sage: int(1) // e
|
|
1816
|
+
Traceback (most recent call last):
|
|
1817
|
+
...
|
|
1818
|
+
TypeError: unsupported operand type(s) for //: 'int' and 'sage.structure.element.Element'
|
|
1819
|
+
sage: e // int(1)
|
|
1820
|
+
Traceback (most recent call last):
|
|
1821
|
+
...
|
|
1822
|
+
TypeError: unsupported operand type(s) for //: 'sage.structure.element.Element' and 'int'
|
|
1823
|
+
sage: None // e
|
|
1824
|
+
Traceback (most recent call last):
|
|
1825
|
+
...
|
|
1826
|
+
TypeError: unsupported operand type(s) for //: 'NoneType' and 'sage.structure.element.Element'
|
|
1827
|
+
sage: e // None
|
|
1828
|
+
Traceback (most recent call last):
|
|
1829
|
+
...
|
|
1830
|
+
TypeError: unsupported operand type(s) for //: 'sage.structure.element.Element' and 'NoneType'
|
|
1831
|
+
"""
|
|
1832
|
+
# See __add__ for comments
|
|
1833
|
+
cdef int cl = classify_elements(left, right)
|
|
1834
|
+
if HAVE_SAME_PARENT(cl):
|
|
1835
|
+
return (<Element>left)._floordiv_(right)
|
|
1836
|
+
if BOTH_ARE_ELEMENT(cl):
|
|
1837
|
+
return coercion_model.bin_op(left, right, floordiv)
|
|
1838
|
+
|
|
1839
|
+
try:
|
|
1840
|
+
return coercion_model.bin_op(left, right, floordiv)
|
|
1841
|
+
except TypeError:
|
|
1842
|
+
return NotImplemented
|
|
1843
|
+
|
|
1844
|
+
cdef _floordiv_(self, other):
|
|
1845
|
+
"""
|
|
1846
|
+
Virtual floor division method for elements with identical parents.
|
|
1847
|
+
|
|
1848
|
+
This default Cython implementation of ``_floordiv_`` calls the
|
|
1849
|
+
Python method ``self._floordiv_`` if it exists. This method may be
|
|
1850
|
+
defined in the ``ElementMethods`` of the category of the parent.
|
|
1851
|
+
If the method is not found, a :exc:`TypeError` is raised
|
|
1852
|
+
indicating that the operation is not supported.
|
|
1853
|
+
|
|
1854
|
+
See :ref:`element_arithmetic`.
|
|
1855
|
+
|
|
1856
|
+
EXAMPLES:
|
|
1857
|
+
|
|
1858
|
+
This method is not visible from Python::
|
|
1859
|
+
|
|
1860
|
+
sage: from sage.structure.element import Element
|
|
1861
|
+
sage: e = Element(Parent())
|
|
1862
|
+
sage: e._floordiv_(e)
|
|
1863
|
+
Traceback (most recent call last):
|
|
1864
|
+
...
|
|
1865
|
+
AttributeError: 'sage.structure.element.Element' object has no attribute '_floordiv_'...
|
|
1866
|
+
"""
|
|
1867
|
+
try:
|
|
1868
|
+
python_op = (<object>self)._floordiv_
|
|
1869
|
+
except AttributeError:
|
|
1870
|
+
raise bin_op_exception('//', self, other)
|
|
1871
|
+
else:
|
|
1872
|
+
return python_op(other)
|
|
1873
|
+
|
|
1874
|
+
def __mod__(left, right):
|
|
1875
|
+
"""
|
|
1876
|
+
Top-level modulo operator for :class:`Element` invoking
|
|
1877
|
+
the coercion model.
|
|
1878
|
+
|
|
1879
|
+
See :ref:`element_arithmetic`.
|
|
1880
|
+
|
|
1881
|
+
EXAMPLES::
|
|
1882
|
+
|
|
1883
|
+
sage: 7 % 3
|
|
1884
|
+
1
|
|
1885
|
+
sage: 7 % int(3)
|
|
1886
|
+
1
|
|
1887
|
+
sage: int(7) % 3
|
|
1888
|
+
1
|
|
1889
|
+
|
|
1890
|
+
::
|
|
1891
|
+
|
|
1892
|
+
sage: from sage.structure.element import Element
|
|
1893
|
+
sage: class MyElement(Element):
|
|
1894
|
+
....: def _mod_(self, other):
|
|
1895
|
+
....: return 42
|
|
1896
|
+
sage: e = MyElement(Parent())
|
|
1897
|
+
sage: e % e
|
|
1898
|
+
42
|
|
1899
|
+
|
|
1900
|
+
TESTS::
|
|
1901
|
+
|
|
1902
|
+
sage: e = Element(Parent())
|
|
1903
|
+
sage: e % e
|
|
1904
|
+
Traceback (most recent call last):
|
|
1905
|
+
...
|
|
1906
|
+
TypeError: unsupported operand parent(s) for %: '<sage.structure.parent.Parent object at ...>' and '<sage.structure.parent.Parent object at ...>'
|
|
1907
|
+
sage: 1 % e
|
|
1908
|
+
Traceback (most recent call last):
|
|
1909
|
+
...
|
|
1910
|
+
TypeError: unsupported operand parent(s) for %: 'Integer Ring' and '<sage.structure.parent.Parent object at ...>'
|
|
1911
|
+
sage: e % 1
|
|
1912
|
+
Traceback (most recent call last):
|
|
1913
|
+
...
|
|
1914
|
+
TypeError: unsupported operand parent(s) for %: '<sage.structure.parent.Parent object at ...>' and 'Integer Ring'
|
|
1915
|
+
sage: int(1) % e
|
|
1916
|
+
Traceback (most recent call last):
|
|
1917
|
+
...
|
|
1918
|
+
TypeError: unsupported operand type(s) for %: 'int' and 'sage.structure.element.Element'
|
|
1919
|
+
sage: e % int(1)
|
|
1920
|
+
Traceback (most recent call last):
|
|
1921
|
+
...
|
|
1922
|
+
TypeError: unsupported operand type(s) for %: 'sage.structure.element.Element' and 'int'
|
|
1923
|
+
sage: None % e
|
|
1924
|
+
Traceback (most recent call last):
|
|
1925
|
+
...
|
|
1926
|
+
TypeError: unsupported operand type(s) for %: 'NoneType' and 'sage.structure.element.Element'
|
|
1927
|
+
sage: e % None
|
|
1928
|
+
Traceback (most recent call last):
|
|
1929
|
+
...
|
|
1930
|
+
TypeError: unsupported operand type(s) for %: 'sage.structure.element.Element' and 'NoneType'
|
|
1931
|
+
"""
|
|
1932
|
+
# See __add__ for comments
|
|
1933
|
+
cdef int cl = classify_elements(left, right)
|
|
1934
|
+
if HAVE_SAME_PARENT(cl):
|
|
1935
|
+
return (<Element>left)._mod_(right)
|
|
1936
|
+
if BOTH_ARE_ELEMENT(cl):
|
|
1937
|
+
return coercion_model.bin_op(left, right, mod)
|
|
1938
|
+
|
|
1939
|
+
try:
|
|
1940
|
+
return coercion_model.bin_op(left, right, mod)
|
|
1941
|
+
except TypeError:
|
|
1942
|
+
return NotImplemented
|
|
1943
|
+
|
|
1944
|
+
cdef _mod_(self, other):
|
|
1945
|
+
"""
|
|
1946
|
+
Virtual modulo method for elements with identical parents.
|
|
1947
|
+
|
|
1948
|
+
This default Cython implementation of ``_mod_`` calls the
|
|
1949
|
+
Python method ``self._mod_`` if it exists. This method may be
|
|
1950
|
+
defined in the ``ElementMethods`` of the category of the parent.
|
|
1951
|
+
If the method is not found, a :exc:`TypeError` is raised
|
|
1952
|
+
indicating that the operation is not supported.
|
|
1953
|
+
|
|
1954
|
+
See :ref:`element_arithmetic`.
|
|
1955
|
+
|
|
1956
|
+
EXAMPLES:
|
|
1957
|
+
|
|
1958
|
+
This method is not visible from Python::
|
|
1959
|
+
|
|
1960
|
+
sage: from sage.structure.element import Element
|
|
1961
|
+
sage: e = Element(Parent())
|
|
1962
|
+
sage: e._mod_(e)
|
|
1963
|
+
Traceback (most recent call last):
|
|
1964
|
+
...
|
|
1965
|
+
AttributeError: 'sage.structure.element.Element' object has no attribute '_mod_'...
|
|
1966
|
+
"""
|
|
1967
|
+
try:
|
|
1968
|
+
python_op = (<object>self)._mod_
|
|
1969
|
+
except AttributeError:
|
|
1970
|
+
raise bin_op_exception('%', self, other)
|
|
1971
|
+
else:
|
|
1972
|
+
return python_op(other)
|
|
1973
|
+
|
|
1974
|
+
def __pow__(left, right, modulus):
|
|
1975
|
+
"""
|
|
1976
|
+
Top-level power operator for :class:`Element` invoking
|
|
1977
|
+
the coercion model.
|
|
1978
|
+
|
|
1979
|
+
See :ref:`element_arithmetic`.
|
|
1980
|
+
|
|
1981
|
+
EXAMPLES::
|
|
1982
|
+
|
|
1983
|
+
sage: from sage.structure.element import Element
|
|
1984
|
+
sage: class MyElement(Element):
|
|
1985
|
+
....: def _add_(self, other):
|
|
1986
|
+
....: return 42
|
|
1987
|
+
sage: e = MyElement(Parent())
|
|
1988
|
+
sage: e + e
|
|
1989
|
+
42
|
|
1990
|
+
sage: a = Integers(389)['x']['y'](37)
|
|
1991
|
+
sage: p = sage.structure.element.RingElement.__pow__
|
|
1992
|
+
sage: p(a, 2)
|
|
1993
|
+
202
|
|
1994
|
+
sage: p(a, 2, 1)
|
|
1995
|
+
Traceback (most recent call last):
|
|
1996
|
+
...
|
|
1997
|
+
TypeError: the 3-argument version of pow() is not supported
|
|
1998
|
+
|
|
1999
|
+
::
|
|
2000
|
+
|
|
2001
|
+
sage: # needs sage.symbolic
|
|
2002
|
+
sage: (2/3)^I
|
|
2003
|
+
(2/3)^I
|
|
2004
|
+
sage: (2/3)^sqrt(2)
|
|
2005
|
+
(2/3)^sqrt(2)
|
|
2006
|
+
sage: var('x,y,z,n')
|
|
2007
|
+
(x, y, z, n)
|
|
2008
|
+
sage: (2/3)^(x^n + y^n + z^n)
|
|
2009
|
+
(2/3)^(x^n + y^n + z^n)
|
|
2010
|
+
sage: (-7/11)^(tan(x)+exp(x))
|
|
2011
|
+
(-7/11)^(e^x + tan(x))
|
|
2012
|
+
|
|
2013
|
+
sage: float(1.2)**(1/2)
|
|
2014
|
+
1.0954451150103321
|
|
2015
|
+
sage: complex(1,2)**(1/2) # needs sage.rings.complex_double
|
|
2016
|
+
(1.272019649514069+0.786151377757423...j)
|
|
2017
|
+
|
|
2018
|
+
TESTS::
|
|
2019
|
+
|
|
2020
|
+
sage: e = Element(Parent())
|
|
2021
|
+
sage: e ^ e
|
|
2022
|
+
Traceback (most recent call last):
|
|
2023
|
+
...
|
|
2024
|
+
TypeError: unsupported operand parent(s) for ^: '<sage.structure.parent.Parent object at ...>' and '<sage.structure.parent.Parent object at ...>'
|
|
2025
|
+
sage: 1 ^ e
|
|
2026
|
+
Traceback (most recent call last):
|
|
2027
|
+
...
|
|
2028
|
+
TypeError: unsupported operand parent(s) for ^: 'Integer Ring' and '<sage.structure.parent.Parent object at ...>'
|
|
2029
|
+
sage: e ^ 1
|
|
2030
|
+
Traceback (most recent call last):
|
|
2031
|
+
...
|
|
2032
|
+
TypeError: unsupported operand parent(s) for ^: '<sage.structure.parent.Parent object at ...>' and 'Integer Ring'
|
|
2033
|
+
sage: int(1) ^ e
|
|
2034
|
+
Traceback (most recent call last):
|
|
2035
|
+
...
|
|
2036
|
+
TypeError: unsupported operand type(s) for ** or pow(): 'int' and 'sage.structure.element.Element'
|
|
2037
|
+
sage: e ^ int(1)
|
|
2038
|
+
Traceback (most recent call last):
|
|
2039
|
+
...
|
|
2040
|
+
TypeError: unsupported operand type(s) for ** or pow(): 'sage.structure.element.Element' and 'int'
|
|
2041
|
+
sage: None ^ e
|
|
2042
|
+
Traceback (most recent call last):
|
|
2043
|
+
...
|
|
2044
|
+
TypeError: unsupported operand type(s) for ** or pow(): 'NoneType' and 'sage.structure.element.Element'
|
|
2045
|
+
sage: e ^ None
|
|
2046
|
+
Traceback (most recent call last):
|
|
2047
|
+
...
|
|
2048
|
+
TypeError: unsupported operand type(s) for ** or pow(): 'sage.structure.element.Element' and 'NoneType'
|
|
2049
|
+
"""
|
|
2050
|
+
# The coercion model does not support a modulus
|
|
2051
|
+
if modulus is not None:
|
|
2052
|
+
raise TypeError("the 3-argument version of pow() is not supported")
|
|
2053
|
+
|
|
2054
|
+
cdef int cl = classify_elements(left, right)
|
|
2055
|
+
if HAVE_SAME_PARENT(cl):
|
|
2056
|
+
return (<Element>left)._pow_(right)
|
|
2057
|
+
if BOTH_ARE_ELEMENT(cl):
|
|
2058
|
+
return coercion_model.bin_op(left, right, pow)
|
|
2059
|
+
|
|
2060
|
+
cdef long value
|
|
2061
|
+
cdef int err = -1
|
|
2062
|
+
try:
|
|
2063
|
+
# Special case powering with Python integers
|
|
2064
|
+
integer_check_long_py(right, &value, &err)
|
|
2065
|
+
if not err:
|
|
2066
|
+
return (<Element>left)._pow_long(value)
|
|
2067
|
+
return coercion_model.bin_op(left, right, pow)
|
|
2068
|
+
except TypeError:
|
|
2069
|
+
return NotImplemented
|
|
2070
|
+
|
|
2071
|
+
cdef _pow_(self, other):
|
|
2072
|
+
"""
|
|
2073
|
+
Virtual powering method for elements with identical parents.
|
|
2074
|
+
|
|
2075
|
+
This default Cython implementation of ``_pow_`` calls the
|
|
2076
|
+
Python method ``self._pow_`` if it exists. This method may be
|
|
2077
|
+
defined in the ``ElementMethods`` of the category of the parent.
|
|
2078
|
+
If the method is not found, a :exc:`TypeError` is raised
|
|
2079
|
+
indicating that the operation is not supported.
|
|
2080
|
+
|
|
2081
|
+
See :ref:`element_arithmetic`.
|
|
2082
|
+
|
|
2083
|
+
EXAMPLES:
|
|
2084
|
+
|
|
2085
|
+
This method is not visible from Python::
|
|
2086
|
+
|
|
2087
|
+
sage: from sage.structure.element import Element
|
|
2088
|
+
sage: e = Element(Parent())
|
|
2089
|
+
sage: e._pow_(e)
|
|
2090
|
+
Traceback (most recent call last):
|
|
2091
|
+
...
|
|
2092
|
+
AttributeError: 'sage.structure.element.Element' object has no attribute '_pow_'...
|
|
2093
|
+
"""
|
|
2094
|
+
try:
|
|
2095
|
+
python_op = (<object>self)._pow_
|
|
2096
|
+
except AttributeError:
|
|
2097
|
+
raise bin_op_exception('^', self, other)
|
|
2098
|
+
else:
|
|
2099
|
+
return python_op(other)
|
|
2100
|
+
|
|
2101
|
+
cdef _pow_int(self, other):
|
|
2102
|
+
"""
|
|
2103
|
+
Virtual powering method for powering to an integer exponent.
|
|
2104
|
+
|
|
2105
|
+
This default Cython implementation of ``_pow_int`` calls the
|
|
2106
|
+
Python method ``self._pow_int`` if it exists. This method may be
|
|
2107
|
+
defined in the ``ElementMethods`` of the category of the parent.
|
|
2108
|
+
If the method is not found, a :exc:`TypeError` is raised
|
|
2109
|
+
indicating that the operation is not supported.
|
|
2110
|
+
|
|
2111
|
+
See :ref:`element_arithmetic`.
|
|
2112
|
+
|
|
2113
|
+
EXAMPLES:
|
|
2114
|
+
|
|
2115
|
+
This method is not visible from Python::
|
|
2116
|
+
|
|
2117
|
+
sage: from sage.structure.element import Element
|
|
2118
|
+
sage: e = Element(Parent())
|
|
2119
|
+
sage: e._pow_int(e)
|
|
2120
|
+
Traceback (most recent call last):
|
|
2121
|
+
...
|
|
2122
|
+
AttributeError: 'sage.structure.element.Element' object has no attribute '_pow_int'...
|
|
2123
|
+
"""
|
|
2124
|
+
try:
|
|
2125
|
+
python_op = (<object>self)._pow_int
|
|
2126
|
+
except AttributeError:
|
|
2127
|
+
raise bin_op_exception('^', self, other)
|
|
2128
|
+
else:
|
|
2129
|
+
return python_op(other)
|
|
2130
|
+
|
|
2131
|
+
cdef _pow_long(self, long n):
|
|
2132
|
+
"""
|
|
2133
|
+
Generic path for powering with a C long.
|
|
2134
|
+
"""
|
|
2135
|
+
return self._pow_int(n)
|
|
2136
|
+
|
|
2137
|
+
|
|
2138
|
+
def is_ModuleElement(x):
|
|
2139
|
+
"""
|
|
2140
|
+
Return ``True`` if x is of type ModuleElement.
|
|
2141
|
+
|
|
2142
|
+
This is even faster than using isinstance inline.
|
|
2143
|
+
|
|
2144
|
+
EXAMPLES::
|
|
2145
|
+
|
|
2146
|
+
sage: from sage.structure.element import is_ModuleElement
|
|
2147
|
+
sage: is_ModuleElement(2/3)
|
|
2148
|
+
doctest:warning...
|
|
2149
|
+
DeprecationWarning: The function is_ModuleElement is deprecated; use 'isinstance(..., ModuleElement)' instead.
|
|
2150
|
+
See https://github.com/sagemath/sage/issues/38077 for details.
|
|
2151
|
+
True
|
|
2152
|
+
sage: is_ModuleElement((QQ^3).0) # needs sage.modules
|
|
2153
|
+
True
|
|
2154
|
+
sage: is_ModuleElement('a')
|
|
2155
|
+
False
|
|
2156
|
+
"""
|
|
2157
|
+
from sage.misc.superseded import deprecation_cython
|
|
2158
|
+
deprecation_cython(38077, "The function is_ModuleElement is deprecated; use 'isinstance(..., ModuleElement)' instead.")
|
|
2159
|
+
return isinstance(x, ModuleElement)
|
|
2160
|
+
|
|
2161
|
+
|
|
2162
|
+
cdef class ElementWithCachedMethod(Element):
|
|
2163
|
+
r"""
|
|
2164
|
+
An element class that fully supports cached methods.
|
|
2165
|
+
|
|
2166
|
+
NOTE:
|
|
2167
|
+
|
|
2168
|
+
The :class:`~sage.misc.cachefunc.cached_method` decorator provides
|
|
2169
|
+
a convenient way to automatically cache the result of a computation.
|
|
2170
|
+
Since :issue:`11115`, the cached method decorator applied to a
|
|
2171
|
+
method without optional arguments is faster than a hand-written cache
|
|
2172
|
+
in Python, and a cached method without any arguments (except ``self``)
|
|
2173
|
+
is actually faster than a Python method that does nothing more but
|
|
2174
|
+
to return ``1``. A cached method can also be inherited from the parent
|
|
2175
|
+
or element class of a category.
|
|
2176
|
+
|
|
2177
|
+
However, this holds true only if attribute assignment is supported.
|
|
2178
|
+
If you write an extension class in Cython that does not accept attribute
|
|
2179
|
+
assignment then a cached method inherited from the category will be
|
|
2180
|
+
slower (for :class:`~sage.structure.parent.Parent`) or the cache would
|
|
2181
|
+
even break (for :class:`Element`).
|
|
2182
|
+
|
|
2183
|
+
This class should be used if you write an element class, cannot provide
|
|
2184
|
+
it with attribute assignment, but want that it inherits a cached method
|
|
2185
|
+
from the category. Under these conditions, your class should inherit
|
|
2186
|
+
from this class rather than :class:`Element`. Then, the cache will work,
|
|
2187
|
+
but certainly slower than with attribute assignment. Lazy attributes
|
|
2188
|
+
work as well.
|
|
2189
|
+
|
|
2190
|
+
EXAMPLES:
|
|
2191
|
+
|
|
2192
|
+
We define three element extension classes. The first inherits from
|
|
2193
|
+
:class:`Element`, the second from this class, and the third simply
|
|
2194
|
+
is a Python class. We also define a parent class and, in Python, a
|
|
2195
|
+
category whose element and parent classes define cached methods.
|
|
2196
|
+
::
|
|
2197
|
+
|
|
2198
|
+
sage: # needs sage.misc.cython
|
|
2199
|
+
sage: cython_code = ["from sage.structure.element cimport Element, ElementWithCachedMethod",
|
|
2200
|
+
....: "from sage.structure.richcmp cimport richcmp",
|
|
2201
|
+
....: "cdef class MyBrokenElement(Element):",
|
|
2202
|
+
....: " cdef public object x",
|
|
2203
|
+
....: " def __init__(self, P, x):",
|
|
2204
|
+
....: " self.x = x",
|
|
2205
|
+
....: " Element.__init__(self, P)",
|
|
2206
|
+
....: " def __neg__(self):",
|
|
2207
|
+
....: " return MyBrokenElement(self.parent(), -self.x)",
|
|
2208
|
+
....: " def _repr_(self):",
|
|
2209
|
+
....: " return '<%s>' % self.x",
|
|
2210
|
+
....: " def __hash__(self):",
|
|
2211
|
+
....: " return hash(self.x)",
|
|
2212
|
+
....: " cpdef _richcmp_(left, right, int op):",
|
|
2213
|
+
....: " return richcmp(left.x, right.x, op)",
|
|
2214
|
+
....: " def raw_test(self):",
|
|
2215
|
+
....: " return -self",
|
|
2216
|
+
....: "cdef class MyElement(ElementWithCachedMethod):",
|
|
2217
|
+
....: " cdef public object x",
|
|
2218
|
+
....: " def __init__(self, P, x):",
|
|
2219
|
+
....: " self.x = x",
|
|
2220
|
+
....: " Element.__init__(self, P)",
|
|
2221
|
+
....: " def __neg__(self):",
|
|
2222
|
+
....: " return MyElement(self.parent(), -self.x)",
|
|
2223
|
+
....: " def _repr_(self):",
|
|
2224
|
+
....: " return '<%s>' % self.x",
|
|
2225
|
+
....: " def __hash__(self):",
|
|
2226
|
+
....: " return hash(self.x)",
|
|
2227
|
+
....: " cpdef _richcmp_(left, right, int op):",
|
|
2228
|
+
....: " return richcmp(left.x, right.x, op)",
|
|
2229
|
+
....: " def raw_test(self):",
|
|
2230
|
+
....: " return -self",
|
|
2231
|
+
....: "class MyPythonElement(MyBrokenElement): pass",
|
|
2232
|
+
....: "from sage.structure.parent cimport Parent",
|
|
2233
|
+
....: "cdef class MyParent(Parent):",
|
|
2234
|
+
....: " Element = MyElement"]
|
|
2235
|
+
sage: cython('\n'.join(cython_code))
|
|
2236
|
+
sage: cython_code = ["from sage.misc.cachefunc import cached_method",
|
|
2237
|
+
....: "from sage.misc.cachefunc import cached_in_parent_method",
|
|
2238
|
+
....: "from sage.categories.category import Category",
|
|
2239
|
+
....: "from sage.categories.objects import Objects",
|
|
2240
|
+
....: "class MyCategory(Category):",
|
|
2241
|
+
....: " @cached_method",
|
|
2242
|
+
....: " def super_categories(self):",
|
|
2243
|
+
....: " return [Objects()]",
|
|
2244
|
+
....: " class ElementMethods:",
|
|
2245
|
+
....: " @cached_method",
|
|
2246
|
+
....: " def element_cache_test(self):",
|
|
2247
|
+
....: " return -self",
|
|
2248
|
+
....: " @cached_in_parent_method",
|
|
2249
|
+
....: " def element_via_parent_test(self):",
|
|
2250
|
+
....: " return -self",
|
|
2251
|
+
....: " class ParentMethods:",
|
|
2252
|
+
....: " @cached_method",
|
|
2253
|
+
....: " def one(self):",
|
|
2254
|
+
....: " return self.element_class(self,1)",
|
|
2255
|
+
....: " @cached_method",
|
|
2256
|
+
....: " def invert(self, x):",
|
|
2257
|
+
....: " return -x"]
|
|
2258
|
+
sage: cython('\n'.join(cython_code))
|
|
2259
|
+
sage: C = MyCategory()
|
|
2260
|
+
sage: P = MyParent(category=C)
|
|
2261
|
+
sage: ebroken = MyBrokenElement(P, 5)
|
|
2262
|
+
sage: e = MyElement(P, 5)
|
|
2263
|
+
|
|
2264
|
+
The cached methods inherited by ``MyElement`` works::
|
|
2265
|
+
|
|
2266
|
+
sage: # needs sage.misc.cython
|
|
2267
|
+
sage: e.element_cache_test()
|
|
2268
|
+
<-5>
|
|
2269
|
+
sage: e.element_cache_test() is e.element_cache_test()
|
|
2270
|
+
True
|
|
2271
|
+
sage: e.element_via_parent_test()
|
|
2272
|
+
<-5>
|
|
2273
|
+
sage: e.element_via_parent_test() is e.element_via_parent_test()
|
|
2274
|
+
True
|
|
2275
|
+
|
|
2276
|
+
The other element class can only inherit a
|
|
2277
|
+
``cached_in_parent_method``, since the cache is stored in the
|
|
2278
|
+
parent. In fact, equal elements share the cache, even if they are
|
|
2279
|
+
of different types::
|
|
2280
|
+
|
|
2281
|
+
sage: e == ebroken # needs sage.misc.cython
|
|
2282
|
+
True
|
|
2283
|
+
sage: type(e) == type(ebroken) # needs sage.misc.cython
|
|
2284
|
+
False
|
|
2285
|
+
sage: ebroken.element_via_parent_test() is e.element_via_parent_test() # needs sage.misc.cython
|
|
2286
|
+
True
|
|
2287
|
+
|
|
2288
|
+
However, the cache of the other inherited method breaks, although the method
|
|
2289
|
+
as such works::
|
|
2290
|
+
|
|
2291
|
+
sage: ebroken.element_cache_test() # needs sage.misc.cython
|
|
2292
|
+
<-5>
|
|
2293
|
+
sage: ebroken.element_cache_test() is ebroken.element_cache_test() # needs sage.misc.cython
|
|
2294
|
+
False
|
|
2295
|
+
|
|
2296
|
+
Since ``e`` and ``ebroken`` share the cache, when we empty it for one element
|
|
2297
|
+
it is empty for the other as well::
|
|
2298
|
+
|
|
2299
|
+
sage: b = ebroken.element_via_parent_test() # needs sage.misc.cython
|
|
2300
|
+
sage: e.element_via_parent_test.clear_cache() # needs sage.misc.cython
|
|
2301
|
+
sage: b is ebroken.element_via_parent_test() # needs sage.misc.cython
|
|
2302
|
+
False
|
|
2303
|
+
|
|
2304
|
+
Note that the cache only breaks for elements that do no allow attribute assignment.
|
|
2305
|
+
A Python version of ``MyBrokenElement`` therefore allows for cached methods::
|
|
2306
|
+
|
|
2307
|
+
sage: epython = MyPythonElement(P, 5) # needs sage.misc.cython
|
|
2308
|
+
sage: epython.element_cache_test() # needs sage.misc.cython
|
|
2309
|
+
<-5>
|
|
2310
|
+
sage: epython.element_cache_test() is epython.element_cache_test() # needs sage.misc.cython
|
|
2311
|
+
True
|
|
2312
|
+
"""
|
|
2313
|
+
cdef getattr_from_category(self, name):
|
|
2314
|
+
"""
|
|
2315
|
+
This getattr method ensures that cached methods and lazy attributes
|
|
2316
|
+
can be inherited from the element class of a category.
|
|
2317
|
+
|
|
2318
|
+
.. NOTE::
|
|
2319
|
+
|
|
2320
|
+
The use of cached methods is demonstrated in the main doc
|
|
2321
|
+
string of this class. Here, we demonstrate lazy
|
|
2322
|
+
attributes.
|
|
2323
|
+
|
|
2324
|
+
EXAMPLES::
|
|
2325
|
+
|
|
2326
|
+
sage: # needs sage.misc.cython
|
|
2327
|
+
sage: cython(
|
|
2328
|
+
....: '''
|
|
2329
|
+
....: from sage.structure.element cimport ElementWithCachedMethod
|
|
2330
|
+
....: cdef class MyElement(ElementWithCachedMethod):
|
|
2331
|
+
....: cdef public object x
|
|
2332
|
+
....: def __init__(self, P, x):
|
|
2333
|
+
....: self.x = x
|
|
2334
|
+
....: ElementWithCachedMethod.__init__(self,P)
|
|
2335
|
+
....: def _repr_(self):
|
|
2336
|
+
....: return '<%s>'%self.x
|
|
2337
|
+
....: from sage.structure.parent cimport Parent
|
|
2338
|
+
....: cdef class MyParent(Parent):
|
|
2339
|
+
....: Element = MyElement
|
|
2340
|
+
....: from sage.misc.cachefunc import cached_method
|
|
2341
|
+
....: from sage.misc.lazy_attribute import lazy_attribute
|
|
2342
|
+
....: from sage.categories.category import Category
|
|
2343
|
+
....: from sage.categories.objects import Objects
|
|
2344
|
+
....: class MyCategory(Category):
|
|
2345
|
+
....: @cached_method
|
|
2346
|
+
....: def super_categories(self):
|
|
2347
|
+
....: return [Objects()]
|
|
2348
|
+
....: class ElementMethods:
|
|
2349
|
+
....: @lazy_attribute
|
|
2350
|
+
....: def my_lazy_attr(self):
|
|
2351
|
+
....: return 'lazy attribute of <%s>'%self.x
|
|
2352
|
+
....: ''')
|
|
2353
|
+
sage: C = MyCategory()
|
|
2354
|
+
sage: P = MyParent(category=C)
|
|
2355
|
+
sage: e = MyElement(P, 5)
|
|
2356
|
+
sage: e.my_lazy_attr
|
|
2357
|
+
'lazy attribute of <5>'
|
|
2358
|
+
sage: e.my_lazy_attr is e.my_lazy_attr
|
|
2359
|
+
True
|
|
2360
|
+
"""
|
|
2361
|
+
try:
|
|
2362
|
+
return self._cached_methods[name]
|
|
2363
|
+
except KeyError:
|
|
2364
|
+
attr = getattr_from_other_class(self,
|
|
2365
|
+
self._parent.category().element_class,
|
|
2366
|
+
name)
|
|
2367
|
+
self._cached_methods[name] = attr
|
|
2368
|
+
return attr
|
|
2369
|
+
except TypeError:
|
|
2370
|
+
attr = getattr_from_other_class(self,
|
|
2371
|
+
self._parent.category().element_class,
|
|
2372
|
+
name)
|
|
2373
|
+
self._cached_methods = {name: attr}
|
|
2374
|
+
return attr
|
|
2375
|
+
|
|
2376
|
+
|
|
2377
|
+
cdef class ModuleElement(Element):
|
|
2378
|
+
"""
|
|
2379
|
+
Generic element of a module.
|
|
2380
|
+
"""
|
|
2381
|
+
cpdef _add_(self, other):
|
|
2382
|
+
"""
|
|
2383
|
+
Abstract addition method.
|
|
2384
|
+
|
|
2385
|
+
TESTS::
|
|
2386
|
+
|
|
2387
|
+
sage: from sage.structure.element import ModuleElement
|
|
2388
|
+
sage: e = ModuleElement(Parent())
|
|
2389
|
+
sage: e + e
|
|
2390
|
+
Traceback (most recent call last):
|
|
2391
|
+
...
|
|
2392
|
+
NotImplementedError: addition not implemented for <sage.structure.parent.Parent object at ...>
|
|
2393
|
+
"""
|
|
2394
|
+
raise NotImplementedError(f"addition not implemented for {self._parent}")
|
|
2395
|
+
|
|
2396
|
+
cdef _add_long(self, long n):
|
|
2397
|
+
"""
|
|
2398
|
+
Generic path for adding a C long, assumed to commute.
|
|
2399
|
+
"""
|
|
2400
|
+
if n == 0:
|
|
2401
|
+
return self
|
|
2402
|
+
return coercion_model.bin_op(self, n, add)
|
|
2403
|
+
|
|
2404
|
+
cpdef _sub_(self, other):
|
|
2405
|
+
"""
|
|
2406
|
+
Default implementation of subtraction using addition and
|
|
2407
|
+
negation.
|
|
2408
|
+
"""
|
|
2409
|
+
return self + (-other)
|
|
2410
|
+
|
|
2411
|
+
cpdef _neg_(self):
|
|
2412
|
+
"""
|
|
2413
|
+
Default implementation of negation using multiplication
|
|
2414
|
+
with -1.
|
|
2415
|
+
"""
|
|
2416
|
+
return self._mul_long(-1)
|
|
2417
|
+
|
|
2418
|
+
cdef _mul_long(self, long n):
|
|
2419
|
+
"""
|
|
2420
|
+
Generic path for multiplying by a C long, assumed to commute.
|
|
2421
|
+
"""
|
|
2422
|
+
if n == 1:
|
|
2423
|
+
return self
|
|
2424
|
+
return coercion_model.bin_op(self, n, mul)
|
|
2425
|
+
|
|
2426
|
+
# rmul -- left * self
|
|
2427
|
+
cpdef _rmul_(self, Element left):
|
|
2428
|
+
"""
|
|
2429
|
+
Reversed scalar multiplication for module elements with the
|
|
2430
|
+
module element on the right and the scalar on the left.
|
|
2431
|
+
|
|
2432
|
+
By default, we assume commutativity and reverse the arguments.
|
|
2433
|
+
"""
|
|
2434
|
+
return self._lmul_(left)
|
|
2435
|
+
|
|
2436
|
+
# lmul -- self * right
|
|
2437
|
+
cpdef _lmul_(self, Element right):
|
|
2438
|
+
"""
|
|
2439
|
+
Scalar multiplication for module elements with the module
|
|
2440
|
+
element on the left and the scalar on the right.
|
|
2441
|
+
|
|
2442
|
+
Returning ``None`` indicates that this action is not implemented here.
|
|
2443
|
+
"""
|
|
2444
|
+
return None
|
|
2445
|
+
|
|
2446
|
+
##################################################
|
|
2447
|
+
# Other properties
|
|
2448
|
+
##################################################
|
|
2449
|
+
def order(self):
|
|
2450
|
+
# DO NOT OVERRIDE THIS!!! Instead, override additive_order.
|
|
2451
|
+
"""
|
|
2452
|
+
Return the additive order of ``self``.
|
|
2453
|
+
"""
|
|
2454
|
+
return self.additive_order()
|
|
2455
|
+
|
|
2456
|
+
def additive_order(self):
|
|
2457
|
+
"""
|
|
2458
|
+
Return the additive order of ``self``.
|
|
2459
|
+
"""
|
|
2460
|
+
raise NotImplementedError
|
|
2461
|
+
|
|
2462
|
+
cdef class ModuleElementWithMutability(ModuleElement):
|
|
2463
|
+
"""
|
|
2464
|
+
Generic element of a module with mutability.
|
|
2465
|
+
"""
|
|
2466
|
+
|
|
2467
|
+
def __init__(self, parent, is_immutable=False):
|
|
2468
|
+
"""
|
|
2469
|
+
EXAMPLES::
|
|
2470
|
+
|
|
2471
|
+
sage: v = sage.modules.free_module_element.FreeModuleElement(QQ^3) # needs sage.modules
|
|
2472
|
+
sage: type(v) # needs sage.modules
|
|
2473
|
+
<class 'sage.modules.free_module_element.FreeModuleElement'>
|
|
2474
|
+
"""
|
|
2475
|
+
self._parent = parent
|
|
2476
|
+
self._is_immutable = is_immutable
|
|
2477
|
+
|
|
2478
|
+
def set_immutable(self):
|
|
2479
|
+
"""
|
|
2480
|
+
Make this vector immutable. This operation can't be undone.
|
|
2481
|
+
|
|
2482
|
+
EXAMPLES::
|
|
2483
|
+
|
|
2484
|
+
sage: # needs sage.modules
|
|
2485
|
+
sage: v = vector([1..5]); v
|
|
2486
|
+
(1, 2, 3, 4, 5)
|
|
2487
|
+
sage: v[1] = 10
|
|
2488
|
+
sage: v.set_immutable()
|
|
2489
|
+
sage: v[1] = 10
|
|
2490
|
+
Traceback (most recent call last):
|
|
2491
|
+
...
|
|
2492
|
+
ValueError: vector is immutable; please change a copy instead (use copy())
|
|
2493
|
+
"""
|
|
2494
|
+
self._is_immutable = 1
|
|
2495
|
+
|
|
2496
|
+
cpdef bint is_mutable(self) noexcept:
|
|
2497
|
+
"""
|
|
2498
|
+
Return ``True`` if this vector is mutable, i.e., the entries can be
|
|
2499
|
+
changed.
|
|
2500
|
+
|
|
2501
|
+
EXAMPLES::
|
|
2502
|
+
|
|
2503
|
+
sage: v = vector(QQ['x,y'], [1..5]); v.is_mutable() # needs sage.modules
|
|
2504
|
+
True
|
|
2505
|
+
sage: v.set_immutable() # needs sage.modules
|
|
2506
|
+
sage: v.is_mutable() # needs sage.modules
|
|
2507
|
+
False
|
|
2508
|
+
"""
|
|
2509
|
+
return not self._is_immutable
|
|
2510
|
+
|
|
2511
|
+
cpdef bint is_immutable(self) noexcept:
|
|
2512
|
+
"""
|
|
2513
|
+
Return ``True`` if this vector is immutable, i.e., the entries cannot
|
|
2514
|
+
be changed.
|
|
2515
|
+
|
|
2516
|
+
EXAMPLES::
|
|
2517
|
+
|
|
2518
|
+
sage: v = vector(QQ['x,y'], [1..5]); v.is_immutable() # needs sage.modules
|
|
2519
|
+
False
|
|
2520
|
+
sage: v.set_immutable() # needs sage.modules
|
|
2521
|
+
sage: v.is_immutable() # needs sage.modules
|
|
2522
|
+
True
|
|
2523
|
+
"""
|
|
2524
|
+
return self._is_immutable
|
|
2525
|
+
|
|
2526
|
+
|
|
2527
|
+
########################################################################
|
|
2528
|
+
# Monoid
|
|
2529
|
+
########################################################################
|
|
2530
|
+
|
|
2531
|
+
def is_MonoidElement(x):
|
|
2532
|
+
"""
|
|
2533
|
+
Return ``True`` if x is of type MonoidElement.
|
|
2534
|
+
"""
|
|
2535
|
+
from sage.misc.superseded import deprecation_cython
|
|
2536
|
+
deprecation_cython(38077, "The function is_MonoidElement is deprecated; use 'isinstance(..., MonoidElement)' instead.")
|
|
2537
|
+
return isinstance(x, MonoidElement)
|
|
2538
|
+
|
|
2539
|
+
|
|
2540
|
+
cdef class MonoidElement(Element):
|
|
2541
|
+
"""
|
|
2542
|
+
Generic element of a monoid.
|
|
2543
|
+
"""
|
|
2544
|
+
|
|
2545
|
+
#############################################################
|
|
2546
|
+
# Other generic functions that should be available to
|
|
2547
|
+
# any monoid element.
|
|
2548
|
+
#############################################################
|
|
2549
|
+
def order(self):
|
|
2550
|
+
"""
|
|
2551
|
+
Return the multiplicative order of ``self``.
|
|
2552
|
+
"""
|
|
2553
|
+
return self.multiplicative_order()
|
|
2554
|
+
|
|
2555
|
+
def multiplicative_order(self):
|
|
2556
|
+
"""
|
|
2557
|
+
Return the multiplicative order of ``self``.
|
|
2558
|
+
"""
|
|
2559
|
+
raise NotImplementedError
|
|
2560
|
+
|
|
2561
|
+
cpdef _pow_int(self, n):
|
|
2562
|
+
"""
|
|
2563
|
+
Return the (integral) power of ``self``.
|
|
2564
|
+
"""
|
|
2565
|
+
return arith_generic_power(self, n)
|
|
2566
|
+
|
|
2567
|
+
def powers(self, n):
|
|
2568
|
+
r"""
|
|
2569
|
+
Return the list `[x^0, x^1, \ldots, x^{n-1}]`.
|
|
2570
|
+
|
|
2571
|
+
EXAMPLES::
|
|
2572
|
+
|
|
2573
|
+
sage: G = SymmetricGroup(4) # needs sage.groups
|
|
2574
|
+
sage: g = G([2, 3, 4, 1]) # needs sage.groups
|
|
2575
|
+
sage: g.powers(4) # needs sage.groups
|
|
2576
|
+
[(), (1,2,3,4), (1,3)(2,4), (1,4,3,2)]
|
|
2577
|
+
"""
|
|
2578
|
+
if n < 0:
|
|
2579
|
+
raise ValueError("negative number of powers requested")
|
|
2580
|
+
elif n == 0:
|
|
2581
|
+
return []
|
|
2582
|
+
x = self._parent.one()
|
|
2583
|
+
l = [x]
|
|
2584
|
+
for i in range(n - 1):
|
|
2585
|
+
x = x * self
|
|
2586
|
+
l.append(x)
|
|
2587
|
+
return l
|
|
2588
|
+
|
|
2589
|
+
def __bool__(self):
|
|
2590
|
+
return True
|
|
2591
|
+
|
|
2592
|
+
|
|
2593
|
+
def is_AdditiveGroupElement(x):
|
|
2594
|
+
"""
|
|
2595
|
+
Return ``True`` if x is of type AdditiveGroupElement.
|
|
2596
|
+
"""
|
|
2597
|
+
from sage.misc.superseded import deprecation_cython
|
|
2598
|
+
deprecation_cython(38077, "The function is_AdditiveGroupElement is deprecated; use 'isinstance(..., AdditiveGroupElement)' instead.")
|
|
2599
|
+
return isinstance(x, AdditiveGroupElement)
|
|
2600
|
+
|
|
2601
|
+
|
|
2602
|
+
cdef class AdditiveGroupElement(ModuleElement):
|
|
2603
|
+
"""
|
|
2604
|
+
Generic element of an additive group.
|
|
2605
|
+
"""
|
|
2606
|
+
def order(self):
|
|
2607
|
+
"""
|
|
2608
|
+
Return additive order of element
|
|
2609
|
+
"""
|
|
2610
|
+
return self.additive_order()
|
|
2611
|
+
|
|
2612
|
+
def __invert__(self):
|
|
2613
|
+
raise NotImplementedError("multiplicative inverse not defined for additive group elements")
|
|
2614
|
+
|
|
2615
|
+
|
|
2616
|
+
def is_MultiplicativeGroupElement(x):
|
|
2617
|
+
"""
|
|
2618
|
+
Return ``True`` if x is of type MultiplicativeGroupElement.
|
|
2619
|
+
"""
|
|
2620
|
+
from sage.misc.superseded import deprecation_cython
|
|
2621
|
+
deprecation_cython(38077, "The function is_MultiplicativeGroupElement is deprecated; use 'isinstance(..., MultiplicativeGroupElement)' instead.")
|
|
2622
|
+
return isinstance(x, MultiplicativeGroupElement)
|
|
2623
|
+
|
|
2624
|
+
|
|
2625
|
+
cdef class MultiplicativeGroupElement(MonoidElement):
|
|
2626
|
+
"""
|
|
2627
|
+
Generic element of a multiplicative group.
|
|
2628
|
+
"""
|
|
2629
|
+
def order(self):
|
|
2630
|
+
"""
|
|
2631
|
+
Return the multiplicative order of ``self``.
|
|
2632
|
+
"""
|
|
2633
|
+
return self.multiplicative_order()
|
|
2634
|
+
|
|
2635
|
+
cpdef _div_(self, right):
|
|
2636
|
+
"""
|
|
2637
|
+
Default implementation of division using multiplication by
|
|
2638
|
+
the inverse.
|
|
2639
|
+
"""
|
|
2640
|
+
return self * ~right
|
|
2641
|
+
|
|
2642
|
+
def __invert__(self):
|
|
2643
|
+
r"""
|
|
2644
|
+
Return the multiplicative inverse of ``self``.
|
|
2645
|
+
|
|
2646
|
+
This may cause infinite recursion because of the default definition
|
|
2647
|
+
of division using inversion in ``_div_``.
|
|
2648
|
+
"""
|
|
2649
|
+
return self._parent.one() / self
|
|
2650
|
+
|
|
2651
|
+
|
|
2652
|
+
def is_RingElement(x):
|
|
2653
|
+
"""
|
|
2654
|
+
Return ``True`` if x is of type RingElement.
|
|
2655
|
+
"""
|
|
2656
|
+
from sage.misc.superseded import deprecation_cython
|
|
2657
|
+
deprecation_cython(38077, "The function is_RingElement is deprecated; use 'isinstance(..., RingElement)' instead.")
|
|
2658
|
+
return isinstance(x, RingElement)
|
|
2659
|
+
|
|
2660
|
+
|
|
2661
|
+
cdef class RingElement(ModuleElement):
|
|
2662
|
+
cpdef _mul_(self, other):
|
|
2663
|
+
"""
|
|
2664
|
+
Abstract multiplication method.
|
|
2665
|
+
|
|
2666
|
+
TESTS::
|
|
2667
|
+
|
|
2668
|
+
sage: from sage.structure.element import RingElement
|
|
2669
|
+
sage: e = RingElement(Parent())
|
|
2670
|
+
sage: e * e
|
|
2671
|
+
Traceback (most recent call last):
|
|
2672
|
+
...
|
|
2673
|
+
NotImplementedError: multiplication not implemented for <sage.structure.parent.Parent object at ...>
|
|
2674
|
+
"""
|
|
2675
|
+
raise NotImplementedError(f"multiplication not implemented for {self._parent}")
|
|
2676
|
+
|
|
2677
|
+
def is_one(self):
|
|
2678
|
+
return self == self._parent.one()
|
|
2679
|
+
|
|
2680
|
+
cpdef _pow_int(self, n):
|
|
2681
|
+
"""
|
|
2682
|
+
Return the (integral) power of ``self``.
|
|
2683
|
+
|
|
2684
|
+
EXAMPLES::
|
|
2685
|
+
|
|
2686
|
+
sage: a = GF(389)['x']['y'](37)
|
|
2687
|
+
sage: p = sage.structure.element.RingElement.__pow__
|
|
2688
|
+
sage: p(a,2)
|
|
2689
|
+
202
|
|
2690
|
+
sage: p(a,2,1)
|
|
2691
|
+
Traceback (most recent call last):
|
|
2692
|
+
...
|
|
2693
|
+
TypeError: the 3-argument version of pow() is not supported
|
|
2694
|
+
sage: p(a,388)
|
|
2695
|
+
1
|
|
2696
|
+
sage: p(a,2^120)
|
|
2697
|
+
81
|
|
2698
|
+
sage: p(a,0)
|
|
2699
|
+
1
|
|
2700
|
+
sage: p(a,1) == a
|
|
2701
|
+
True
|
|
2702
|
+
sage: p(a,2) * p(a,3) == p(a,5)
|
|
2703
|
+
True
|
|
2704
|
+
sage: p(a,3)^2 == p(a,6)
|
|
2705
|
+
True
|
|
2706
|
+
sage: p(a,57) * p(a,43) == p(a,100)
|
|
2707
|
+
True
|
|
2708
|
+
sage: p(a,-1) == 1/a
|
|
2709
|
+
True
|
|
2710
|
+
sage: p(a,200) * p(a,-64) == p(a,136)
|
|
2711
|
+
True
|
|
2712
|
+
sage: p(2, 1/2) # needs sage.symbolic
|
|
2713
|
+
sqrt(2)
|
|
2714
|
+
|
|
2715
|
+
TESTS:
|
|
2716
|
+
|
|
2717
|
+
These are not testing this code, but they are probably good to have around::
|
|
2718
|
+
|
|
2719
|
+
sage: 2r**(SR(2)-1-1r) # needs sage.symbolic
|
|
2720
|
+
1
|
|
2721
|
+
sage: 2r^(1/2) # needs sage.symbolic
|
|
2722
|
+
sqrt(2)
|
|
2723
|
+
|
|
2724
|
+
Exponent overflow should throw an :exc:`OverflowError` (:issue:`2956`)::
|
|
2725
|
+
|
|
2726
|
+
sage: K.<x,y> = AA[] # needs sage.rings.number_field
|
|
2727
|
+
sage: x^(2^64 + 12345) # known bug: macos # needs sage.rings.number_field
|
|
2728
|
+
Traceback (most recent call last):
|
|
2729
|
+
...
|
|
2730
|
+
OverflowError: exponent overflow (2147483648)
|
|
2731
|
+
|
|
2732
|
+
Another example from :issue:`2956` which always overflows
|
|
2733
|
+
with Singular 4::
|
|
2734
|
+
|
|
2735
|
+
sage: K.<x,y> = ZZ[]
|
|
2736
|
+
sage: (x^123456)^654321
|
|
2737
|
+
Traceback (most recent call last):
|
|
2738
|
+
...
|
|
2739
|
+
OverflowError: exponent overflow (...)
|
|
2740
|
+
"""
|
|
2741
|
+
return arith_generic_power(self, n)
|
|
2742
|
+
|
|
2743
|
+
def powers(self, n):
|
|
2744
|
+
r"""
|
|
2745
|
+
Return the list `[x^0, x^1, \ldots, x^{n-1}]`.
|
|
2746
|
+
|
|
2747
|
+
EXAMPLES::
|
|
2748
|
+
|
|
2749
|
+
sage: 5.powers(3)
|
|
2750
|
+
[1, 5, 25]
|
|
2751
|
+
"""
|
|
2752
|
+
if n < 0:
|
|
2753
|
+
raise ValueError("negative number of powers requested")
|
|
2754
|
+
elif n == 0:
|
|
2755
|
+
return []
|
|
2756
|
+
x = self._parent.one()
|
|
2757
|
+
l = [x]
|
|
2758
|
+
for i in range(n - 1):
|
|
2759
|
+
x = x * self
|
|
2760
|
+
l.append(x)
|
|
2761
|
+
return l
|
|
2762
|
+
|
|
2763
|
+
cpdef _div_(self, other):
|
|
2764
|
+
"""
|
|
2765
|
+
Default implementation of division using the fraction field.
|
|
2766
|
+
"""
|
|
2767
|
+
try:
|
|
2768
|
+
frac = self._parent.fraction_field()
|
|
2769
|
+
except AttributeError:
|
|
2770
|
+
raise bin_op_exception('/', self, other)
|
|
2771
|
+
return frac(self, other)
|
|
2772
|
+
|
|
2773
|
+
def __divmod__(self, other):
|
|
2774
|
+
"""
|
|
2775
|
+
Return the quotient and remainder of ``self`` divided by ``other``.
|
|
2776
|
+
|
|
2777
|
+
This operation may not be defined in all rings.
|
|
2778
|
+
|
|
2779
|
+
EXAMPLES::
|
|
2780
|
+
|
|
2781
|
+
sage: divmod(5,3)
|
|
2782
|
+
(1, 2)
|
|
2783
|
+
sage: divmod(25r,12)
|
|
2784
|
+
(2, 1)
|
|
2785
|
+
sage: divmod(25,12r)
|
|
2786
|
+
(2, 1)
|
|
2787
|
+
|
|
2788
|
+
::
|
|
2789
|
+
|
|
2790
|
+
sage: R.<x> = QQ[]
|
|
2791
|
+
sage: f = -19/13*x^5 - x^4 - 2/3*x^3 + 6*x^2 - 2
|
|
2792
|
+
sage: g = 3*x^2 + 5
|
|
2793
|
+
sage: q,r = divmod(f,g)
|
|
2794
|
+
sage: q
|
|
2795
|
+
-19/39*x^3 - 1/3*x^2 + 23/39*x + 23/9
|
|
2796
|
+
sage: r
|
|
2797
|
+
-115/39*x - 133/9
|
|
2798
|
+
sage: f == q*g + r
|
|
2799
|
+
True
|
|
2800
|
+
|
|
2801
|
+
::
|
|
2802
|
+
|
|
2803
|
+
sage: R.<x> = ZZ[]
|
|
2804
|
+
sage: f = -2*x^5 + x^4 - 9*x^3 - 5*x^2 + 7*x + 4
|
|
2805
|
+
sage: g = x^2 + 5
|
|
2806
|
+
sage: q,r = divmod(f,g)
|
|
2807
|
+
sage: q
|
|
2808
|
+
-2*x^3 + x^2 + x - 10
|
|
2809
|
+
sage: r
|
|
2810
|
+
2*x + 54
|
|
2811
|
+
sage: f == q*g + r
|
|
2812
|
+
True
|
|
2813
|
+
sage: h = 3*x^2 + 5
|
|
2814
|
+
sage: q,r = divmod(f,h)
|
|
2815
|
+
sage: q
|
|
2816
|
+
-3*x - 2
|
|
2817
|
+
sage: r
|
|
2818
|
+
-2*x^5 + x^4 + x^2 + 22*x + 14
|
|
2819
|
+
sage: f == q*h + r
|
|
2820
|
+
True
|
|
2821
|
+
|
|
2822
|
+
::
|
|
2823
|
+
|
|
2824
|
+
sage: R.<x> = GF(7)[]
|
|
2825
|
+
sage: divmod(x^2, x - 1)
|
|
2826
|
+
(x + 1, 1)
|
|
2827
|
+
|
|
2828
|
+
::
|
|
2829
|
+
|
|
2830
|
+
sage: divmod(22./7, RR(pi)) # needs sage.symbolic
|
|
2831
|
+
(1.00040249943477, 0.000000000000000)
|
|
2832
|
+
"""
|
|
2833
|
+
try:
|
|
2834
|
+
return self.quo_rem(other)
|
|
2835
|
+
except (AttributeError, NotImplementedError):
|
|
2836
|
+
pass
|
|
2837
|
+
return (self // other, self % other)
|
|
2838
|
+
|
|
2839
|
+
def __invert__(self):
|
|
2840
|
+
return self._parent.one() / self
|
|
2841
|
+
|
|
2842
|
+
def additive_order(self):
|
|
2843
|
+
"""
|
|
2844
|
+
Return the additive order of ``self``.
|
|
2845
|
+
"""
|
|
2846
|
+
raise NotImplementedError
|
|
2847
|
+
|
|
2848
|
+
def multiplicative_order(self):
|
|
2849
|
+
r"""
|
|
2850
|
+
Return the multiplicative order of ``self``, if ``self`` is a unit.
|
|
2851
|
+
|
|
2852
|
+
This raises an :class:`ArithmeticError` otherwise.
|
|
2853
|
+
"""
|
|
2854
|
+
if not self.is_unit():
|
|
2855
|
+
raise ArithmeticError("self (=%s) must be a unit to have a multiplicative order.")
|
|
2856
|
+
raise NotImplementedError
|
|
2857
|
+
|
|
2858
|
+
def is_nilpotent(self):
|
|
2859
|
+
"""
|
|
2860
|
+
Return ``True`` if ``self`` is nilpotent, i.e., some power of ``self``
|
|
2861
|
+
is 0.
|
|
2862
|
+
|
|
2863
|
+
TESTS::
|
|
2864
|
+
|
|
2865
|
+
sage: a = QQ(2)
|
|
2866
|
+
sage: a.is_nilpotent()
|
|
2867
|
+
False
|
|
2868
|
+
sage: a = QQ(0)
|
|
2869
|
+
sage: a.is_nilpotent()
|
|
2870
|
+
True
|
|
2871
|
+
sage: m = matrix(QQ, 3, [[3,2,3], [9,0,3], [-9,0,-3]]) # needs sage.modules
|
|
2872
|
+
sage: m.is_nilpotent() # needs sage.libs.pari sage.modules
|
|
2873
|
+
True
|
|
2874
|
+
"""
|
|
2875
|
+
if self.is_unit():
|
|
2876
|
+
return False
|
|
2877
|
+
if self.is_zero():
|
|
2878
|
+
return True
|
|
2879
|
+
raise NotImplementedError
|
|
2880
|
+
|
|
2881
|
+
def abs(self):
|
|
2882
|
+
"""
|
|
2883
|
+
Return the absolute value of ``self``. (This just calls the ``__abs__``
|
|
2884
|
+
method, so it is equivalent to the ``abs()`` built-in function.)
|
|
2885
|
+
|
|
2886
|
+
EXAMPLES::
|
|
2887
|
+
|
|
2888
|
+
sage: RR(-1).abs() # needs sage.rings.real_mpfr
|
|
2889
|
+
1.00000000000000
|
|
2890
|
+
sage: ZZ(-1).abs()
|
|
2891
|
+
1
|
|
2892
|
+
sage: CC(I).abs() # needs sage.rings.real_mpfr sage.symbolic
|
|
2893
|
+
1.00000000000000
|
|
2894
|
+
sage: Mod(-15, 37).abs()
|
|
2895
|
+
Traceback (most recent call last):
|
|
2896
|
+
...
|
|
2897
|
+
ArithmeticError: absolute value not defined on integers modulo n.
|
|
2898
|
+
"""
|
|
2899
|
+
return abs(self)
|
|
2900
|
+
|
|
2901
|
+
def is_prime(self):
|
|
2902
|
+
"""
|
|
2903
|
+
Check whether ``self`` is a prime element.
|
|
2904
|
+
|
|
2905
|
+
A *prime* element is a nonzero, non-unit element `p` such that,
|
|
2906
|
+
whenever `p` divides `ab` for some `a` and `b`, then `p`
|
|
2907
|
+
divides `a` or `p` divides `b`.
|
|
2908
|
+
|
|
2909
|
+
EXAMPLES:
|
|
2910
|
+
|
|
2911
|
+
For polynomial rings, prime is the same as irreducible::
|
|
2912
|
+
|
|
2913
|
+
sage: # needs sage.libs.singular
|
|
2914
|
+
sage: R.<x,y> = QQ[]
|
|
2915
|
+
sage: x.is_prime()
|
|
2916
|
+
True
|
|
2917
|
+
sage: (x^2 + y^3).is_prime()
|
|
2918
|
+
True
|
|
2919
|
+
sage: (x^2 - y^2).is_prime()
|
|
2920
|
+
False
|
|
2921
|
+
sage: R(0).is_prime()
|
|
2922
|
+
False
|
|
2923
|
+
sage: R(2).is_prime()
|
|
2924
|
+
False
|
|
2925
|
+
|
|
2926
|
+
For the Gaussian integers::
|
|
2927
|
+
|
|
2928
|
+
sage: # needs sage.rings.number_field
|
|
2929
|
+
sage: K.<i> = QuadraticField(-1)
|
|
2930
|
+
sage: ZI = K.ring_of_integers()
|
|
2931
|
+
sage: ZI(3).is_prime()
|
|
2932
|
+
True
|
|
2933
|
+
sage: ZI(5).is_prime()
|
|
2934
|
+
False
|
|
2935
|
+
sage: ZI(2 + i).is_prime()
|
|
2936
|
+
True
|
|
2937
|
+
sage: ZI(0).is_prime()
|
|
2938
|
+
False
|
|
2939
|
+
sage: ZI(1).is_prime()
|
|
2940
|
+
False
|
|
2941
|
+
|
|
2942
|
+
In fields, an element is never prime::
|
|
2943
|
+
|
|
2944
|
+
sage: RR(0).is_prime()
|
|
2945
|
+
False
|
|
2946
|
+
sage: RR(2).is_prime()
|
|
2947
|
+
False
|
|
2948
|
+
|
|
2949
|
+
For integers, :meth:`is_prime` redefines prime numbers to be
|
|
2950
|
+
positive::
|
|
2951
|
+
|
|
2952
|
+
sage: (-2).is_prime()
|
|
2953
|
+
False
|
|
2954
|
+
sage: RingElement.is_prime(-2) # needs sage.libs.pari
|
|
2955
|
+
True
|
|
2956
|
+
|
|
2957
|
+
Similarly,
|
|
2958
|
+
:class:`~sage.rings.number_field.number_field_base.NumberField`
|
|
2959
|
+
redefines :meth:`is_prime` to determine primality in the ring
|
|
2960
|
+
of integers::
|
|
2961
|
+
|
|
2962
|
+
sage: # needs sage.rings.number_field
|
|
2963
|
+
sage: (1 + i).is_prime()
|
|
2964
|
+
True
|
|
2965
|
+
sage: K(5).is_prime()
|
|
2966
|
+
False
|
|
2967
|
+
sage: K(7).is_prime()
|
|
2968
|
+
True
|
|
2969
|
+
sage: K(7/13).is_prime()
|
|
2970
|
+
False
|
|
2971
|
+
|
|
2972
|
+
However, for rationals, :meth:`is_prime` *does* follow the
|
|
2973
|
+
general definition of prime elements in a ring (i.e., always
|
|
2974
|
+
returns ``False``) since the rationals are not a
|
|
2975
|
+
:class:`~sage.rings.number_field.number_field_base.NumberField`
|
|
2976
|
+
in Sage::
|
|
2977
|
+
|
|
2978
|
+
sage: QQ(7).is_prime()
|
|
2979
|
+
False
|
|
2980
|
+
"""
|
|
2981
|
+
if not self: # We exclude the 0 element
|
|
2982
|
+
return False
|
|
2983
|
+
return self._parent.ideal(self).is_prime()
|
|
2984
|
+
|
|
2985
|
+
|
|
2986
|
+
def is_CommutativeRingElement(x):
|
|
2987
|
+
"""
|
|
2988
|
+
Return ``True`` if x is of type CommutativeRingElement.
|
|
2989
|
+
|
|
2990
|
+
TESTS::
|
|
2991
|
+
|
|
2992
|
+
sage: from sage.structure.element import is_CommutativeRingElement
|
|
2993
|
+
sage: is_CommutativeRingElement(oo)
|
|
2994
|
+
doctest:warning...
|
|
2995
|
+
DeprecationWarning: The function is_CommutativeRingElement is deprecated; use 'isinstance(..., CommutativeRingElement)' instead.
|
|
2996
|
+
See https://github.com/sagemath/sage/issues/38077 for details.
|
|
2997
|
+
False
|
|
2998
|
+
|
|
2999
|
+
sage: is_CommutativeRingElement(1)
|
|
3000
|
+
True
|
|
3001
|
+
"""
|
|
3002
|
+
from sage.misc.superseded import deprecation_cython
|
|
3003
|
+
deprecation_cython(38077, "The function is_CommutativeRingElement is deprecated; use 'isinstance(..., CommutativeRingElement)' instead.")
|
|
3004
|
+
return isinstance(x, CommutativeRingElement)
|
|
3005
|
+
|
|
3006
|
+
|
|
3007
|
+
cdef class CommutativeRingElement(RingElement):
|
|
3008
|
+
"""
|
|
3009
|
+
Base class for elements of commutative rings.
|
|
3010
|
+
"""
|
|
3011
|
+
|
|
3012
|
+
def inverse_mod(self, I):
|
|
3013
|
+
r"""
|
|
3014
|
+
Return an inverse of ``self`` modulo the ideal `I`, if defined,
|
|
3015
|
+
i.e., if `I` and ``self`` together generate the unit ideal.
|
|
3016
|
+
|
|
3017
|
+
EXAMPLES::
|
|
3018
|
+
|
|
3019
|
+
sage: # needs sage.rings.finite_rings
|
|
3020
|
+
sage: F = GF(25)
|
|
3021
|
+
sage: x = F.gen()
|
|
3022
|
+
sage: z = F.zero()
|
|
3023
|
+
sage: x.inverse_mod(F.ideal(z))
|
|
3024
|
+
2*z2 + 3
|
|
3025
|
+
sage: x.inverse_mod(F.ideal(1))
|
|
3026
|
+
1
|
|
3027
|
+
sage: z.inverse_mod(F.ideal(1))
|
|
3028
|
+
1
|
|
3029
|
+
sage: z.inverse_mod(F.ideal(z))
|
|
3030
|
+
Traceback (most recent call last):
|
|
3031
|
+
...
|
|
3032
|
+
ValueError: an element of a proper ideal does not have an inverse modulo that ideal
|
|
3033
|
+
"""
|
|
3034
|
+
if I.is_one():
|
|
3035
|
+
return self.parent().one()
|
|
3036
|
+
elif self in I:
|
|
3037
|
+
raise ValueError("an element of a proper ideal does not have an inverse modulo that ideal")
|
|
3038
|
+
elif hasattr(self, "is_unit") and self.is_unit():
|
|
3039
|
+
return self.inverse_of_unit()
|
|
3040
|
+
else:
|
|
3041
|
+
raise NotImplementedError
|
|
3042
|
+
|
|
3043
|
+
def divides(self, x):
|
|
3044
|
+
"""
|
|
3045
|
+
Return ``True`` if ``self`` divides x.
|
|
3046
|
+
|
|
3047
|
+
EXAMPLES::
|
|
3048
|
+
|
|
3049
|
+
sage: P.<x> = PolynomialRing(QQ)
|
|
3050
|
+
sage: x.divides(x^2)
|
|
3051
|
+
True
|
|
3052
|
+
sage: x.divides(x^2 + 2)
|
|
3053
|
+
False
|
|
3054
|
+
sage: (x^2 + 2).divides(x)
|
|
3055
|
+
False
|
|
3056
|
+
sage: P.<x> = PolynomialRing(ZZ)
|
|
3057
|
+
sage: x.divides(x^2)
|
|
3058
|
+
True
|
|
3059
|
+
sage: x.divides(x^2 + 2)
|
|
3060
|
+
False
|
|
3061
|
+
sage: (x^2 + 2).divides(x)
|
|
3062
|
+
False
|
|
3063
|
+
|
|
3064
|
+
:issue:`5347` has been fixed::
|
|
3065
|
+
|
|
3066
|
+
sage: K = GF(7)
|
|
3067
|
+
sage: K(3).divides(1)
|
|
3068
|
+
True
|
|
3069
|
+
sage: K(3).divides(K(1))
|
|
3070
|
+
True
|
|
3071
|
+
|
|
3072
|
+
::
|
|
3073
|
+
|
|
3074
|
+
sage: R = Integers(128)
|
|
3075
|
+
sage: R(0).divides(1)
|
|
3076
|
+
False
|
|
3077
|
+
sage: R(0).divides(0)
|
|
3078
|
+
True
|
|
3079
|
+
sage: R(0).divides(R(0))
|
|
3080
|
+
True
|
|
3081
|
+
sage: R(1).divides(0)
|
|
3082
|
+
True
|
|
3083
|
+
sage: R(121).divides(R(120))
|
|
3084
|
+
True
|
|
3085
|
+
sage: R(120).divides(R(121))
|
|
3086
|
+
False
|
|
3087
|
+
|
|
3088
|
+
If ``x`` has different parent than ``self``, they are first coerced to a
|
|
3089
|
+
common parent if possible. If this coercion fails, it returns a
|
|
3090
|
+
:exc:`TypeError`. This fixes :issue:`5759`. ::
|
|
3091
|
+
|
|
3092
|
+
sage: Zmod(2)(0).divides(Zmod(2)(0))
|
|
3093
|
+
True
|
|
3094
|
+
sage: Zmod(2)(0).divides(Zmod(2)(1))
|
|
3095
|
+
False
|
|
3096
|
+
sage: Zmod(5)(1).divides(Zmod(2)(1))
|
|
3097
|
+
Traceback (most recent call last):
|
|
3098
|
+
...
|
|
3099
|
+
TypeError: no common canonical parent for objects with parents:
|
|
3100
|
+
'Ring of integers modulo 5' and 'Ring of integers modulo 2'
|
|
3101
|
+
sage: Zmod(35)(4).divides(Zmod(7)(1))
|
|
3102
|
+
True
|
|
3103
|
+
sage: Zmod(35)(7).divides(Zmod(7)(1))
|
|
3104
|
+
False
|
|
3105
|
+
"""
|
|
3106
|
+
if have_same_parent(self, x):
|
|
3107
|
+
# First we test some generic conditions:
|
|
3108
|
+
try:
|
|
3109
|
+
if x.is_zero():
|
|
3110
|
+
return True # everything divides 0
|
|
3111
|
+
except (AttributeError, NotImplementedError):
|
|
3112
|
+
pass
|
|
3113
|
+
|
|
3114
|
+
try:
|
|
3115
|
+
if self.is_zero():
|
|
3116
|
+
return False # 0 divides nothing else
|
|
3117
|
+
except (AttributeError, NotImplementedError):
|
|
3118
|
+
pass
|
|
3119
|
+
|
|
3120
|
+
try:
|
|
3121
|
+
if self.is_unit():
|
|
3122
|
+
return True # units divide everything
|
|
3123
|
+
except (AttributeError, NotImplementedError):
|
|
3124
|
+
pass
|
|
3125
|
+
|
|
3126
|
+
try:
|
|
3127
|
+
if self.is_one():
|
|
3128
|
+
return True
|
|
3129
|
+
# 1 divides everything
|
|
3130
|
+
# (is_unit() may not be implemented)
|
|
3131
|
+
except (AttributeError, NotImplementedError):
|
|
3132
|
+
pass
|
|
3133
|
+
|
|
3134
|
+
try:
|
|
3135
|
+
return (x % self).is_zero()
|
|
3136
|
+
except (TypeError, NotImplementedError):
|
|
3137
|
+
pass
|
|
3138
|
+
|
|
3139
|
+
raise NotImplementedError
|
|
3140
|
+
|
|
3141
|
+
else:
|
|
3142
|
+
# Different parents, use coercion
|
|
3143
|
+
a, b = coercion_model.canonical_coercion(self, x)
|
|
3144
|
+
return a.divides(b)
|
|
3145
|
+
|
|
3146
|
+
def mod(self, I):
|
|
3147
|
+
r"""
|
|
3148
|
+
Return a representative for ``self`` modulo the ideal I (or the ideal
|
|
3149
|
+
generated by the elements of I if I is not an ideal.)
|
|
3150
|
+
|
|
3151
|
+
EXAMPLES: Integers
|
|
3152
|
+
Reduction of 5 modulo an ideal::
|
|
3153
|
+
|
|
3154
|
+
sage: n = 5
|
|
3155
|
+
sage: n.mod(3*ZZ)
|
|
3156
|
+
2
|
|
3157
|
+
|
|
3158
|
+
Reduction of 5 modulo the ideal generated by 3::
|
|
3159
|
+
|
|
3160
|
+
sage: n.mod(3)
|
|
3161
|
+
2
|
|
3162
|
+
|
|
3163
|
+
Reduction of 5 modulo the ideal generated by 15 and 6, which is `(3)`.
|
|
3164
|
+
|
|
3165
|
+
::
|
|
3166
|
+
|
|
3167
|
+
sage: n.mod([15,6])
|
|
3168
|
+
2
|
|
3169
|
+
|
|
3170
|
+
EXAMPLES: Univariate polynomials
|
|
3171
|
+
|
|
3172
|
+
::
|
|
3173
|
+
|
|
3174
|
+
sage: R.<x> = PolynomialRing(QQ)
|
|
3175
|
+
sage: f = x^3 + x + 1
|
|
3176
|
+
sage: f.mod(x + 1)
|
|
3177
|
+
-1
|
|
3178
|
+
|
|
3179
|
+
Reduction for `\ZZ[x]`::
|
|
3180
|
+
|
|
3181
|
+
sage: R.<x> = PolynomialRing(ZZ)
|
|
3182
|
+
sage: f = x^3 + x + 1
|
|
3183
|
+
sage: f.mod(x + 1)
|
|
3184
|
+
-1
|
|
3185
|
+
|
|
3186
|
+
When little is implemented about a given ring, then ``mod`` may
|
|
3187
|
+
simply return `f`.
|
|
3188
|
+
|
|
3189
|
+
EXAMPLES: Multivariate polynomials
|
|
3190
|
+
We reduce a polynomial in two variables modulo a polynomial
|
|
3191
|
+
and an ideal::
|
|
3192
|
+
|
|
3193
|
+
sage: R.<x,y,z> = PolynomialRing(QQ, 3)
|
|
3194
|
+
sage: (x^2 + y^2 + z^2).mod(x + y + z) # needs sage.libs.singular
|
|
3195
|
+
2*y^2 + 2*y*z + 2*z^2
|
|
3196
|
+
|
|
3197
|
+
Notice above that `x` is eliminated. In the next example,
|
|
3198
|
+
both `y` and `z` are eliminated::
|
|
3199
|
+
|
|
3200
|
+
sage: (x^2 + y^2 + z^2).mod( (x - y, y - z) ) # needs sage.libs.singular
|
|
3201
|
+
3*z^2
|
|
3202
|
+
sage: f = (x^2 + y^2 + z^2)^2; f
|
|
3203
|
+
x^4 + 2*x^2*y^2 + y^4 + 2*x^2*z^2 + 2*y^2*z^2 + z^4
|
|
3204
|
+
sage: f.mod( (x - y, y - z) ) # needs sage.libs.singular
|
|
3205
|
+
9*z^4
|
|
3206
|
+
|
|
3207
|
+
In this example `y` is eliminated::
|
|
3208
|
+
|
|
3209
|
+
sage: (x^2 + y^2 + z^2).mod( (x^3, y - z) ) # needs sage.libs.singular
|
|
3210
|
+
x^2 + 2*z^2
|
|
3211
|
+
"""
|
|
3212
|
+
from sage.rings.ideal import Ideal_generic
|
|
3213
|
+
if not isinstance(I, Ideal_generic) or not I.ring() is self._parent:
|
|
3214
|
+
I = self._parent.ideal(I)
|
|
3215
|
+
return I.reduce(self)
|
|
3216
|
+
|
|
3217
|
+
##################################################
|
|
3218
|
+
# square roots
|
|
3219
|
+
##################################################
|
|
3220
|
+
|
|
3221
|
+
def is_square(self, root=False):
|
|
3222
|
+
"""
|
|
3223
|
+
Return whether or not the ring element ``self`` is a square.
|
|
3224
|
+
|
|
3225
|
+
If the optional argument root is ``True``, then also return
|
|
3226
|
+
the square root (or ``None``, if it is not a square).
|
|
3227
|
+
|
|
3228
|
+
INPUT:
|
|
3229
|
+
|
|
3230
|
+
- ``root`` -- boolean (default: ``False``); whether or not to also
|
|
3231
|
+
return a square root
|
|
3232
|
+
|
|
3233
|
+
OUTPUT:
|
|
3234
|
+
|
|
3235
|
+
- boolean; whether or not a square
|
|
3236
|
+
|
|
3237
|
+
- object; (optional) an actual square root if found, and ``None``
|
|
3238
|
+
otherwise
|
|
3239
|
+
|
|
3240
|
+
EXAMPLES::
|
|
3241
|
+
|
|
3242
|
+
sage: R.<x> = PolynomialRing(QQ)
|
|
3243
|
+
sage: f = 12*(x+1)^2 * (x+3)^2
|
|
3244
|
+
sage: f.is_square()
|
|
3245
|
+
False
|
|
3246
|
+
sage: f.is_square(root=True)
|
|
3247
|
+
(False, None)
|
|
3248
|
+
sage: h = f/3
|
|
3249
|
+
sage: h.is_square()
|
|
3250
|
+
True
|
|
3251
|
+
sage: h.is_square(root=True)
|
|
3252
|
+
(True, 2*x^2 + 8*x + 6)
|
|
3253
|
+
|
|
3254
|
+
.. NOTE::
|
|
3255
|
+
|
|
3256
|
+
This is the is_square implementation for general commutative ring
|
|
3257
|
+
elements. It's implementation is to raise a
|
|
3258
|
+
:exc:`NotImplementedError`. The function definition is here to show
|
|
3259
|
+
what functionality is expected and provide a general framework.
|
|
3260
|
+
"""
|
|
3261
|
+
raise NotImplementedError("is_square() not implemented for elements of %s" % self.parent())
|
|
3262
|
+
|
|
3263
|
+
def sqrt(self, extend=True, all=False, name=None):
|
|
3264
|
+
"""
|
|
3265
|
+
Compute the square root.
|
|
3266
|
+
|
|
3267
|
+
INPUT:
|
|
3268
|
+
|
|
3269
|
+
- ``extend`` -- boolean (default: ``True``); whether to make a ring
|
|
3270
|
+
extension containing a square root if ``self`` is not a square
|
|
3271
|
+
|
|
3272
|
+
- ``all`` -- boolean (default: ``False``); whether to return a list of
|
|
3273
|
+
all square roots or just a square root
|
|
3274
|
+
|
|
3275
|
+
- ``name`` -- required when ``extend=True`` and ``self`` is not a
|
|
3276
|
+
square; this will be the name of the generator of the extension
|
|
3277
|
+
|
|
3278
|
+
OUTPUT:
|
|
3279
|
+
|
|
3280
|
+
- if ``all=False``, a square root; raises an error if ``extend=False``
|
|
3281
|
+
and ``self`` is not a square
|
|
3282
|
+
|
|
3283
|
+
- if ``all=True``, a list of all the square roots (empty if
|
|
3284
|
+
``extend=False`` and ``self`` is not a square)
|
|
3285
|
+
|
|
3286
|
+
ALGORITHM:
|
|
3287
|
+
|
|
3288
|
+
It uses ``is_square(root=true)`` for the hard part of the work, the rest
|
|
3289
|
+
is just wrapper code.
|
|
3290
|
+
|
|
3291
|
+
EXAMPLES::
|
|
3292
|
+
|
|
3293
|
+
sage: # needs sage.libs.pari
|
|
3294
|
+
sage: R.<x> = ZZ[]
|
|
3295
|
+
sage: (x^2).sqrt()
|
|
3296
|
+
x
|
|
3297
|
+
sage: f = x^2 - 4*x + 4; f.sqrt(all=True)
|
|
3298
|
+
[x - 2, -x + 2]
|
|
3299
|
+
sage: sqrtx = x.sqrt(name='y'); sqrtx # needs sage.libs.singular
|
|
3300
|
+
y
|
|
3301
|
+
sage: sqrtx^2 # needs sage.libs.singular
|
|
3302
|
+
x
|
|
3303
|
+
sage: x.sqrt(all=true, name='y') # needs sage.libs.singular
|
|
3304
|
+
[y, -y]
|
|
3305
|
+
sage: x.sqrt(extend=False, all=True)
|
|
3306
|
+
[]
|
|
3307
|
+
sage: x.sqrt()
|
|
3308
|
+
Traceback (most recent call last):
|
|
3309
|
+
...
|
|
3310
|
+
TypeError: Polynomial is not a square. You must specify the name
|
|
3311
|
+
of the square root when using the default extend = True
|
|
3312
|
+
sage: x.sqrt(extend=False)
|
|
3313
|
+
Traceback (most recent call last):
|
|
3314
|
+
...
|
|
3315
|
+
ValueError: trying to take square root of non-square x with extend = False
|
|
3316
|
+
|
|
3317
|
+
TESTS::
|
|
3318
|
+
|
|
3319
|
+
sage: # needs sage.libs.pari
|
|
3320
|
+
sage: f = (x + 3)^2; f.sqrt()
|
|
3321
|
+
x + 3
|
|
3322
|
+
sage: f = (x + 3)^2; f.sqrt(all=True)
|
|
3323
|
+
[x + 3, -x - 3]
|
|
3324
|
+
sage: f = (x^2 - x + 3)^2; f.sqrt()
|
|
3325
|
+
x^2 - x + 3
|
|
3326
|
+
sage: f = (x^2 - x + 3)^6; f.sqrt()
|
|
3327
|
+
x^6 - 3*x^5 + 12*x^4 - 19*x^3 + 36*x^2 - 27*x + 27
|
|
3328
|
+
sage: g = (R.random_element(15))^2
|
|
3329
|
+
sage: g.sqrt()^2 == g
|
|
3330
|
+
True
|
|
3331
|
+
|
|
3332
|
+
sage: # needs sage.libs.pari
|
|
3333
|
+
sage: R.<x> = GF(250037)[]
|
|
3334
|
+
sage: f = x^2/(x+1)^2; f.sqrt()
|
|
3335
|
+
x/(x + 1)
|
|
3336
|
+
sage: f = 9 * x^4 / (x+1)^2; f.sqrt()
|
|
3337
|
+
3*x^2/(x + 1)
|
|
3338
|
+
sage: f = 9 * x^4 / (x+1)^2; f.sqrt(all=True)
|
|
3339
|
+
[3*x^2/(x + 1), 250034*x^2/(x + 1)]
|
|
3340
|
+
|
|
3341
|
+
sage: R.<x> = QQ[]
|
|
3342
|
+
sage: a = 2*(x+1)^2 / (2*(x-1)^2); a.sqrt()
|
|
3343
|
+
(x + 1)/(x - 1)
|
|
3344
|
+
sage: sqrtx = (1/x).sqrt(name='y'); sqrtx # needs sage.libs.singular
|
|
3345
|
+
y
|
|
3346
|
+
sage: sqrtx^2 # needs sage.libs.singular
|
|
3347
|
+
1/x
|
|
3348
|
+
sage: (1/x).sqrt(all=true, name='y') # needs sage.libs.singular
|
|
3349
|
+
[y, -y]
|
|
3350
|
+
sage: (1/x).sqrt(extend=False, all=True)
|
|
3351
|
+
[]
|
|
3352
|
+
sage: (1/(x^2-1)).sqrt()
|
|
3353
|
+
Traceback (most recent call last):
|
|
3354
|
+
...
|
|
3355
|
+
TypeError: Polynomial is not a square. You must specify the name
|
|
3356
|
+
of the square root when using the default extend = True
|
|
3357
|
+
sage: (1/(x^2-3)).sqrt(extend=False)
|
|
3358
|
+
Traceback (most recent call last):
|
|
3359
|
+
...
|
|
3360
|
+
ValueError: trying to take square root of non-square 1/(x^2 - 3) with extend = False
|
|
3361
|
+
"""
|
|
3362
|
+
# This code is very general, it works for all integral domains that have the
|
|
3363
|
+
# is_square(root = True) option
|
|
3364
|
+
|
|
3365
|
+
from sage.categories.integral_domains import IntegralDomains
|
|
3366
|
+
P = self._parent
|
|
3367
|
+
is_sqr, sq_rt = self.is_square(root=True)
|
|
3368
|
+
if is_sqr:
|
|
3369
|
+
if all:
|
|
3370
|
+
if P not in IntegralDomains():
|
|
3371
|
+
raise NotImplementedError('sqrt() with all=True is only implemented for integral domains, not for %s' % P)
|
|
3372
|
+
if P.characteristic()==2 or sq_rt==0:
|
|
3373
|
+
# 0 has only one square root, and in characteristic 2 everything also has only 1 root
|
|
3374
|
+
return [sq_rt]
|
|
3375
|
+
return [sq_rt, -sq_rt]
|
|
3376
|
+
return sq_rt
|
|
3377
|
+
# from now on we know that self is not a square
|
|
3378
|
+
if P not in IntegralDomains():
|
|
3379
|
+
raise NotImplementedError('sqrt() of non squares is only implemented for integral domains, not for %s' % P)
|
|
3380
|
+
if not extend:
|
|
3381
|
+
# all square roots of a non-square should be an empty list
|
|
3382
|
+
if all:
|
|
3383
|
+
return []
|
|
3384
|
+
raise ValueError('trying to take square root of non-square %s with extend = False' % self)
|
|
3385
|
+
|
|
3386
|
+
if name is None:
|
|
3387
|
+
raise TypeError("Polynomial is not a square. You must specify the name of the square root when using the default extend = True")
|
|
3388
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
3389
|
+
PY = PolynomialRing(P, 'y')
|
|
3390
|
+
y = PY.gen()
|
|
3391
|
+
sq_rt = PY.quotient(y**2-self, names = name)(y)
|
|
3392
|
+
if all:
|
|
3393
|
+
if P.characteristic() == 2:
|
|
3394
|
+
return [sq_rt]
|
|
3395
|
+
return [sq_rt, -sq_rt]
|
|
3396
|
+
return sq_rt
|
|
3397
|
+
|
|
3398
|
+
##############################################
|
|
3399
|
+
|
|
3400
|
+
cdef class Expression(CommutativeRingElement):
|
|
3401
|
+
|
|
3402
|
+
r"""
|
|
3403
|
+
Abstract base class for :class:`~sage.symbolic.expression.Expression`.
|
|
3404
|
+
|
|
3405
|
+
This class is defined for the purpose of :func:`isinstance` tests. It should not be
|
|
3406
|
+
instantiated.
|
|
3407
|
+
|
|
3408
|
+
EXAMPLES::
|
|
3409
|
+
|
|
3410
|
+
sage: isinstance(SR.var('y'), sage.structure.element.Expression) # needs sage.symbolic
|
|
3411
|
+
True
|
|
3412
|
+
|
|
3413
|
+
By design, there is a unique direct subclass::
|
|
3414
|
+
|
|
3415
|
+
sage: len(sage.structure.element.Expression.__subclasses__()) <= 1
|
|
3416
|
+
True
|
|
3417
|
+
"""
|
|
3418
|
+
|
|
3419
|
+
pass
|
|
3420
|
+
|
|
3421
|
+
##############################################
|
|
3422
|
+
|
|
3423
|
+
cdef class Vector(ModuleElementWithMutability):
|
|
3424
|
+
cdef bint is_sparse_c(self) noexcept:
|
|
3425
|
+
raise NotImplementedError
|
|
3426
|
+
|
|
3427
|
+
cdef bint is_dense_c(self) noexcept:
|
|
3428
|
+
raise NotImplementedError
|
|
3429
|
+
|
|
3430
|
+
def __mul__(left, right):
|
|
3431
|
+
"""
|
|
3432
|
+
Multiplication of vector by vector, matrix, or scalar.
|
|
3433
|
+
|
|
3434
|
+
AUTHOR:
|
|
3435
|
+
|
|
3436
|
+
- Gonzalo Tornaria (2007-06-21) - write test cases and fix them
|
|
3437
|
+
|
|
3438
|
+
.. NOTE::
|
|
3439
|
+
|
|
3440
|
+
scalar * vector is implemented (and tested) in class RingElement
|
|
3441
|
+
matrix * vector is implemented (and tested) in class Matrix
|
|
3442
|
+
|
|
3443
|
+
TESTS:
|
|
3444
|
+
|
|
3445
|
+
Here we test (vector * vector) multiplication::
|
|
3446
|
+
|
|
3447
|
+
sage: # needs sage.modules
|
|
3448
|
+
sage: parent(vector(ZZ, [1,2]) * vector(ZZ, [1,2]))
|
|
3449
|
+
Integer Ring
|
|
3450
|
+
sage: parent(vector(ZZ, [1,2]) * vector(QQ, [1,2]))
|
|
3451
|
+
Rational Field
|
|
3452
|
+
sage: parent(vector(QQ, [1,2]) * vector(ZZ, [1,2]))
|
|
3453
|
+
Rational Field
|
|
3454
|
+
sage: parent(vector(QQ, [1,2]) * vector(QQ, [1,2]))
|
|
3455
|
+
Rational Field
|
|
3456
|
+
|
|
3457
|
+
sage: parent(vector(QQ, [1,2,3,4]) * vector(ZZ['x'], [1,2,3,4])) # needs sage.modules
|
|
3458
|
+
Univariate Polynomial Ring in x over Rational Field
|
|
3459
|
+
sage: parent(vector(ZZ['x'], [1,2,3,4]) * vector(QQ, [1,2,3,4])) # needs sage.modules
|
|
3460
|
+
Univariate Polynomial Ring in x over Rational Field
|
|
3461
|
+
|
|
3462
|
+
sage: parent(vector(QQ, [1,2,3,4]) * vector(ZZ['x']['y'], [1,2,3,4])) # needs sage.modules
|
|
3463
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3464
|
+
sage: parent(vector(ZZ['x']['y'], [1,2,3,4]) * vector(QQ, [1,2,3,4])) # needs sage.modules
|
|
3465
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3466
|
+
|
|
3467
|
+
sage: parent(vector(QQ['x'], [1,2,3,4]) * vector(ZZ['x']['y'], [1,2,3,4])) # needs sage.modules
|
|
3468
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3469
|
+
sage: parent(vector(ZZ['x']['y'], [1,2,3,4]) * vector(QQ['x'], [1,2,3,4])) # needs sage.modules
|
|
3470
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3471
|
+
|
|
3472
|
+
sage: parent(vector(QQ['y'], [1,2,3,4]) * vector(ZZ['x']['y'], [1,2,3,4])) # needs sage.modules
|
|
3473
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3474
|
+
sage: parent(vector(ZZ['x']['y'], [1,2,3,4]) * vector(QQ['y'], [1,2,3,4])) # needs sage.modules
|
|
3475
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3476
|
+
|
|
3477
|
+
sage: # needs sage.modules
|
|
3478
|
+
sage: parent(vector(ZZ['x'], [1,2,3,4]) * vector(ZZ['y'], [1,2,3,4]))
|
|
3479
|
+
Traceback (most recent call last):
|
|
3480
|
+
...
|
|
3481
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3482
|
+
'Ambient free module of rank 4 over the integral domain Univariate Polynomial Ring in x over Integer Ring' and
|
|
3483
|
+
'Ambient free module of rank 4 over the integral domain Univariate Polynomial Ring in y over Integer Ring'
|
|
3484
|
+
sage: parent(vector(ZZ['x'], [1,2,3,4]) * vector(QQ['y'], [1,2,3,4]))
|
|
3485
|
+
Traceback (most recent call last):
|
|
3486
|
+
...
|
|
3487
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3488
|
+
'Ambient free module of rank 4 over the integral domain Univariate Polynomial Ring in x over Integer Ring' and
|
|
3489
|
+
'Ambient free module of rank 4 over the principal ideal domain Univariate Polynomial Ring in y over Rational Field'
|
|
3490
|
+
sage: parent(vector(QQ['x'], [1,2,3,4]) * vector(ZZ['y'], [1,2,3,4]))
|
|
3491
|
+
Traceback (most recent call last):
|
|
3492
|
+
...
|
|
3493
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3494
|
+
'Ambient free module of rank 4 over the principal ideal domain Univariate Polynomial Ring in x over Rational Field' and
|
|
3495
|
+
'Ambient free module of rank 4 over the integral domain Univariate Polynomial Ring in y over Integer Ring'
|
|
3496
|
+
sage: parent(vector(QQ['x'], [1,2,3,4]) * vector(QQ['y'], [1,2,3,4]))
|
|
3497
|
+
Traceback (most recent call last):
|
|
3498
|
+
...
|
|
3499
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3500
|
+
'Ambient free module of rank 4 over the principal ideal domain Univariate Polynomial Ring in x over Rational Field' and
|
|
3501
|
+
'Ambient free module of rank 4 over the principal ideal domain Univariate Polynomial Ring in y over Rational Field'
|
|
3502
|
+
|
|
3503
|
+
Here we test (vector * matrix) multiplication::
|
|
3504
|
+
|
|
3505
|
+
sage: # needs sage.modules
|
|
3506
|
+
sage: parent(vector(ZZ, [1,2]) * matrix(ZZ, 2, 2, [1,2,3,4]))
|
|
3507
|
+
Ambient free module of rank 2 over the principal ideal domain Integer Ring
|
|
3508
|
+
sage: parent(vector(QQ, [1,2]) * matrix(ZZ, 2, 2, [1,2,3,4]))
|
|
3509
|
+
Vector space of dimension 2 over Rational Field
|
|
3510
|
+
sage: parent(vector(ZZ, [1,2]) * matrix(QQ, 2, 2, [1,2,3,4]))
|
|
3511
|
+
Vector space of dimension 2 over Rational Field
|
|
3512
|
+
sage: parent(vector(QQ, [1,2]) * matrix(QQ, 2, 2, [1,2,3,4]))
|
|
3513
|
+
Vector space of dimension 2 over Rational Field
|
|
3514
|
+
|
|
3515
|
+
sage: parent(vector(QQ, [1,2]) * matrix(ZZ['x'], 2, 2, [1,2,3,4])) # needs sage.modules
|
|
3516
|
+
Ambient free module of rank 2
|
|
3517
|
+
over the principal ideal domain Univariate Polynomial Ring in x over Rational Field
|
|
3518
|
+
sage: parent(vector(ZZ['x'], [1,2]) * matrix(QQ, 2, 2, [1,2,3,4])) # needs sage.modules
|
|
3519
|
+
Ambient free module of rank 2
|
|
3520
|
+
over the principal ideal domain Univariate Polynomial Ring in x over Rational Field
|
|
3521
|
+
|
|
3522
|
+
sage: parent(vector(QQ, [1,2]) * matrix(ZZ['x']['y'], 2, 2, [1,2,3,4])) # needs sage.modules
|
|
3523
|
+
Ambient free module of rank 2 over the integral domain
|
|
3524
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3525
|
+
sage: parent(vector(ZZ['x']['y'], [1,2]) * matrix(QQ, 2, 2, [1,2,3,4])) # needs sage.modules
|
|
3526
|
+
Ambient free module of rank 2 over the integral domain
|
|
3527
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3528
|
+
|
|
3529
|
+
sage: parent(vector(QQ['x'], [1,2]) * matrix(ZZ['x']['y'], 2, 2, [1,2,3,4])) # needs sage.modules
|
|
3530
|
+
Ambient free module of rank 2 over the integral domain
|
|
3531
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3532
|
+
sage: parent(vector(ZZ['x']['y'], [1,2]) * matrix(QQ['x'], 2, 2, [1,2,3,4])) # needs sage.modules
|
|
3533
|
+
Ambient free module of rank 2 over the integral domain
|
|
3534
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3535
|
+
|
|
3536
|
+
sage: parent(vector(QQ['y'], [1,2]) * matrix(ZZ['x']['y'], 2, 2, [1,2,3,4])) # needs sage.modules
|
|
3537
|
+
Ambient free module of rank 2 over the integral domain
|
|
3538
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3539
|
+
sage: parent(vector(ZZ['x']['y'], [1,2]) * matrix(QQ['y'], 2, 2, [1,2,3,4])) # needs sage.modules
|
|
3540
|
+
Ambient free module of rank 2 over the integral domain
|
|
3541
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3542
|
+
|
|
3543
|
+
sage: # needs sage.modules
|
|
3544
|
+
sage: parent(vector(ZZ['x'], [1,2]) * matrix(ZZ['y'], 2, 2, [1,2,3,4]))
|
|
3545
|
+
Traceback (most recent call last):
|
|
3546
|
+
...
|
|
3547
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3548
|
+
'Ambient free module of rank 2 over the integral domain Univariate Polynomial Ring in x over Integer Ring' and
|
|
3549
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in y over Integer Ring'
|
|
3550
|
+
sage: parent(vector(ZZ['x'], [1,2]) * matrix(QQ['y'], 2, 2, [1,2,3,4]))
|
|
3551
|
+
Traceback (most recent call last):
|
|
3552
|
+
...
|
|
3553
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3554
|
+
'Ambient free module of rank 2 over the integral domain Univariate Polynomial Ring in x over Integer Ring' and
|
|
3555
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in y over Rational Field'
|
|
3556
|
+
sage: parent(vector(QQ['x'], [1,2]) * matrix(ZZ['y'], 2, 2, [1,2,3,4]))
|
|
3557
|
+
Traceback (most recent call last):
|
|
3558
|
+
...
|
|
3559
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3560
|
+
'Ambient free module of rank 2 over the principal ideal domain Univariate Polynomial Ring in x over Rational Field' and
|
|
3561
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in y over Integer Ring'
|
|
3562
|
+
sage: parent(vector(QQ['x'], [1,2]) * matrix(QQ['y'], 2, 2, [1,2,3,4]))
|
|
3563
|
+
Traceback (most recent call last):
|
|
3564
|
+
...
|
|
3565
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3566
|
+
'Ambient free module of rank 2 over the principal ideal domain Univariate Polynomial Ring in x over Rational Field' and
|
|
3567
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in y over Rational Field'
|
|
3568
|
+
|
|
3569
|
+
Here we test (vector * scalar) multiplication::
|
|
3570
|
+
|
|
3571
|
+
sage: # needs sage.modules
|
|
3572
|
+
sage: parent(vector(ZZ, [1,2]) * ZZ(1))
|
|
3573
|
+
Ambient free module of rank 2 over the principal ideal domain Integer Ring
|
|
3574
|
+
sage: parent(vector(QQ, [1,2]) * ZZ(1))
|
|
3575
|
+
Vector space of dimension 2 over Rational Field
|
|
3576
|
+
sage: parent(vector(ZZ, [1,2]) * QQ(1))
|
|
3577
|
+
Vector space of dimension 2 over Rational Field
|
|
3578
|
+
sage: parent(vector(QQ, [1,2]) * QQ(1))
|
|
3579
|
+
Vector space of dimension 2 over Rational Field
|
|
3580
|
+
|
|
3581
|
+
sage: parent(vector(QQ, [1,2]) * ZZ['x'](1)) # needs sage.modules
|
|
3582
|
+
Ambient free module of rank 2
|
|
3583
|
+
over the principal ideal domain Univariate Polynomial Ring in x over Rational Field
|
|
3584
|
+
sage: parent(vector(ZZ['x'], [1,2]) * QQ(1)) # needs sage.modules
|
|
3585
|
+
Ambient free module of rank 2
|
|
3586
|
+
over the principal ideal domain Univariate Polynomial Ring in x over Rational Field
|
|
3587
|
+
|
|
3588
|
+
sage: parent(vector(QQ, [1,2]) * ZZ['x']['y'](1)) # needs sage.modules
|
|
3589
|
+
Ambient free module of rank 2 over the integral domain
|
|
3590
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3591
|
+
sage: parent(vector(ZZ['x']['y'], [1,2]) * QQ(1)) # needs sage.modules
|
|
3592
|
+
Ambient free module of rank 2 over the integral domain
|
|
3593
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3594
|
+
|
|
3595
|
+
sage: parent(vector(QQ['x'], [1,2]) * ZZ['x']['y'](1)) # needs sage.modules
|
|
3596
|
+
Ambient free module of rank 2 over the integral domain
|
|
3597
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3598
|
+
sage: parent(vector(ZZ['x']['y'], [1,2]) * QQ['x'](1)) # needs sage.modules
|
|
3599
|
+
Ambient free module of rank 2 over the integral domain
|
|
3600
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3601
|
+
|
|
3602
|
+
sage: parent(vector(QQ['y'], [1,2]) * ZZ['x']['y'](1)) # needs sage.modules
|
|
3603
|
+
Ambient free module of rank 2 over the integral domain
|
|
3604
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3605
|
+
sage: parent(vector(ZZ['x']['y'], [1,2]) * QQ['y'](1)) # needs sage.modules
|
|
3606
|
+
Ambient free module of rank 2 over the integral domain
|
|
3607
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3608
|
+
|
|
3609
|
+
sage: # needs sage.modules
|
|
3610
|
+
sage: parent(vector(ZZ['x'], [1,2]) * ZZ['y'](1))
|
|
3611
|
+
Traceback (most recent call last):
|
|
3612
|
+
...
|
|
3613
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3614
|
+
'Ambient free module of rank 2 over the integral domain Univariate Polynomial Ring in x over Integer Ring' and
|
|
3615
|
+
'Univariate Polynomial Ring in y over Integer Ring'
|
|
3616
|
+
sage: parent(vector(ZZ['x'], [1,2]) * QQ['y'](1))
|
|
3617
|
+
Traceback (most recent call last):
|
|
3618
|
+
...
|
|
3619
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3620
|
+
'Ambient free module of rank 2 over the integral domain Univariate Polynomial Ring in x over Integer Ring' and
|
|
3621
|
+
'Univariate Polynomial Ring in y over Rational Field'
|
|
3622
|
+
sage: parent(vector(QQ['x'], [1,2]) * ZZ['y'](1))
|
|
3623
|
+
Traceback (most recent call last):
|
|
3624
|
+
...
|
|
3625
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3626
|
+
'Ambient free module of rank 2 over the principal ideal domain Univariate Polynomial Ring in x over Rational Field' and
|
|
3627
|
+
'Univariate Polynomial Ring in y over Integer Ring'
|
|
3628
|
+
sage: parent(vector(QQ['x'], [1,2]) * QQ['y'](1))
|
|
3629
|
+
Traceback (most recent call last):
|
|
3630
|
+
...
|
|
3631
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3632
|
+
'Ambient free module of rank 2 over the principal ideal domain Univariate Polynomial Ring in x over Rational Field' and
|
|
3633
|
+
'Univariate Polynomial Ring in y over Rational Field'
|
|
3634
|
+
|
|
3635
|
+
Here we test (scalar * vector) multiplication::
|
|
3636
|
+
|
|
3637
|
+
sage: # needs sage.modules
|
|
3638
|
+
sage: parent(ZZ(1) * vector(ZZ, [1,2]))
|
|
3639
|
+
Ambient free module of rank 2 over the principal ideal domain Integer Ring
|
|
3640
|
+
sage: parent(QQ(1) * vector(ZZ, [1,2]))
|
|
3641
|
+
Vector space of dimension 2 over Rational Field
|
|
3642
|
+
sage: parent(ZZ(1) * vector(QQ, [1,2]))
|
|
3643
|
+
Vector space of dimension 2 over Rational Field
|
|
3644
|
+
sage: parent(QQ(1) * vector(QQ, [1,2]))
|
|
3645
|
+
Vector space of dimension 2 over Rational Field
|
|
3646
|
+
|
|
3647
|
+
sage: parent(QQ(1) * vector(ZZ['x'], [1,2])) # needs sage.modules
|
|
3648
|
+
Ambient free module of rank 2
|
|
3649
|
+
over the principal ideal domain Univariate Polynomial Ring in x over Rational Field
|
|
3650
|
+
sage: parent(ZZ['x'](1) * vector(QQ, [1,2])) # needs sage.modules
|
|
3651
|
+
Ambient free module of rank 2
|
|
3652
|
+
over the principal ideal domain Univariate Polynomial Ring in x over Rational Field
|
|
3653
|
+
|
|
3654
|
+
sage: parent(QQ(1) * vector(ZZ['x']['y'], [1,2])) # needs sage.modules
|
|
3655
|
+
Ambient free module of rank 2 over the integral domain
|
|
3656
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3657
|
+
sage: parent(ZZ['x']['y'](1) * vector(QQ, [1,2])) # needs sage.modules
|
|
3658
|
+
Ambient free module of rank 2 over the integral domain
|
|
3659
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3660
|
+
|
|
3661
|
+
sage: parent(QQ['x'](1) * vector(ZZ['x']['y'], [1,2])) # needs sage.modules
|
|
3662
|
+
Ambient free module of rank 2 over the integral domain
|
|
3663
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3664
|
+
sage: parent(ZZ['x']['y'](1) * vector(QQ['x'], [1,2])) # needs sage.modules
|
|
3665
|
+
Ambient free module of rank 2 over the integral domain
|
|
3666
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3667
|
+
|
|
3668
|
+
sage: parent(QQ['y'](1) * vector(ZZ['x']['y'], [1,2])) # needs sage.modules
|
|
3669
|
+
Ambient free module of rank 2 over the integral domain
|
|
3670
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3671
|
+
sage: parent(ZZ['x']['y'](1) * vector(QQ['y'], [1,2])) # needs sage.modules
|
|
3672
|
+
Ambient free module of rank 2 over the integral domain
|
|
3673
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3674
|
+
|
|
3675
|
+
sage: # needs sage.modules
|
|
3676
|
+
sage: parent(ZZ['x'](1) * vector(ZZ['y'], [1,2]))
|
|
3677
|
+
Traceback (most recent call last):
|
|
3678
|
+
...
|
|
3679
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3680
|
+
'Univariate Polynomial Ring in x over Integer Ring' and
|
|
3681
|
+
'Ambient free module of rank 2 over the integral domain Univariate Polynomial Ring in y over Integer Ring'
|
|
3682
|
+
sage: parent(ZZ['x'](1) * vector(QQ['y'], [1,2]))
|
|
3683
|
+
Traceback (most recent call last):
|
|
3684
|
+
...
|
|
3685
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3686
|
+
'Univariate Polynomial Ring in x over Integer Ring' and
|
|
3687
|
+
'Ambient free module of rank 2 over the principal ideal domain Univariate Polynomial Ring in y over Rational Field'
|
|
3688
|
+
sage: parent(QQ['x'](1) * vector(ZZ['y'], [1,2]))
|
|
3689
|
+
Traceback (most recent call last):
|
|
3690
|
+
...
|
|
3691
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3692
|
+
'Univariate Polynomial Ring in x over Rational Field' and
|
|
3693
|
+
'Ambient free module of rank 2 over the integral domain Univariate Polynomial Ring in y over Integer Ring'
|
|
3694
|
+
sage: parent(QQ['x'](1) * vector(QQ['y'], [1,2]))
|
|
3695
|
+
Traceback (most recent call last):
|
|
3696
|
+
...
|
|
3697
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3698
|
+
'Univariate Polynomial Ring in x over Rational Field' and
|
|
3699
|
+
'Ambient free module of rank 2 over the principal ideal domain Univariate Polynomial Ring in y over Rational Field'
|
|
3700
|
+
"""
|
|
3701
|
+
if have_same_parent(left, right):
|
|
3702
|
+
return (<Vector>left)._dot_product_(<Vector>right)
|
|
3703
|
+
return coercion_model.bin_op(left, right, mul)
|
|
3704
|
+
|
|
3705
|
+
cpdef _dot_product_(Vector left, Vector right):
|
|
3706
|
+
return left._dot_product_coerce_(right)
|
|
3707
|
+
|
|
3708
|
+
cpdef _dot_product_coerce_(Vector left, Vector right):
|
|
3709
|
+
raise bin_op_exception('*', left, right)
|
|
3710
|
+
|
|
3711
|
+
cpdef _pairwise_product_(Vector left, Vector right):
|
|
3712
|
+
raise TypeError("unsupported operation for '%s' and '%s'" % (parent(left), parent(right)))
|
|
3713
|
+
|
|
3714
|
+
def __truediv__(self, right):
|
|
3715
|
+
"""
|
|
3716
|
+
Divide this vector by a scalar, vector or matrix.
|
|
3717
|
+
|
|
3718
|
+
TESTS::
|
|
3719
|
+
|
|
3720
|
+
sage: # needs sage.modules
|
|
3721
|
+
sage: A = matrix([[1, 2], [0, 3]])
|
|
3722
|
+
sage: b = vector([0, 1])
|
|
3723
|
+
sage: x = b / A; x
|
|
3724
|
+
(0, 1/3)
|
|
3725
|
+
sage: x == b * ~A
|
|
3726
|
+
True
|
|
3727
|
+
sage: A = matrix([[1, 2], [0, 3], [1, 5]])
|
|
3728
|
+
sage: (b / A) * A == b
|
|
3729
|
+
True
|
|
3730
|
+
"""
|
|
3731
|
+
right = py_scalar_to_element(right)
|
|
3732
|
+
if isinstance(right, RingElement):
|
|
3733
|
+
# Let __mul__ do the job
|
|
3734
|
+
return self * ~right
|
|
3735
|
+
if isinstance(right, Vector):
|
|
3736
|
+
try:
|
|
3737
|
+
W = (<Vector>right)._parent.submodule([right])
|
|
3738
|
+
return W.coordinates(self)[0] / W.coordinates(right)[0]
|
|
3739
|
+
except ArithmeticError:
|
|
3740
|
+
if right.is_zero():
|
|
3741
|
+
raise ZeroDivisionError("division by zero vector")
|
|
3742
|
+
else:
|
|
3743
|
+
raise ArithmeticError("vector is not in free module")
|
|
3744
|
+
if isinstance(right, Matrix):
|
|
3745
|
+
return right.solve_left(self)
|
|
3746
|
+
raise bin_op_exception('/', self, right)
|
|
3747
|
+
|
|
3748
|
+
def _magma_init_(self, magma):
|
|
3749
|
+
"""
|
|
3750
|
+
Return string that evaluates in Magma to something equivalent
|
|
3751
|
+
to this vector.
|
|
3752
|
+
|
|
3753
|
+
EXAMPLES::
|
|
3754
|
+
|
|
3755
|
+
sage: # optional - magma, needs sage.modules
|
|
3756
|
+
sage: v = vector([1,2,3])
|
|
3757
|
+
sage: v._magma_init_(magma)
|
|
3758
|
+
'_sage_[...]![1,2,3]'
|
|
3759
|
+
sage: mv = magma(v); mv
|
|
3760
|
+
(1 2 3)
|
|
3761
|
+
sage: mv.Type()
|
|
3762
|
+
ModTupRngElt
|
|
3763
|
+
sage: mv.Parent()
|
|
3764
|
+
Full RSpace of degree 3 over Integer Ring
|
|
3765
|
+
|
|
3766
|
+
sage: # optional - magma, needs sage.modules
|
|
3767
|
+
sage: v = vector(QQ, [1/2, 3/4, 5/6])
|
|
3768
|
+
sage: mv = magma(v); mv
|
|
3769
|
+
(1/2 3/4 5/6)
|
|
3770
|
+
sage: mv.Type()
|
|
3771
|
+
ModTupFldElt
|
|
3772
|
+
sage: mv.Parent()
|
|
3773
|
+
Full Vector space of degree 3 over Rational Field
|
|
3774
|
+
|
|
3775
|
+
A more demanding example::
|
|
3776
|
+
|
|
3777
|
+
sage: # optional - magma, needs sage.modules
|
|
3778
|
+
sage: R.<x,y,z> = QQ[]
|
|
3779
|
+
sage: v = vector([x^3, y, 2/3*z + x/y])
|
|
3780
|
+
sage: magma(v)
|
|
3781
|
+
( x^3 y (2/3*y*z + x)/y)
|
|
3782
|
+
sage: magma(v).Parent()
|
|
3783
|
+
Full Vector space of degree 3
|
|
3784
|
+
over Multivariate rational function field of rank 3 over Rational Field
|
|
3785
|
+
"""
|
|
3786
|
+
V = magma(self._parent)
|
|
3787
|
+
v = [x._magma_init_(magma) for x in self.list()]
|
|
3788
|
+
return '%s![%s]' % (V.name(), ','.join(v))
|
|
3789
|
+
|
|
3790
|
+
|
|
3791
|
+
def is_Vector(x):
|
|
3792
|
+
from sage.misc.superseded import deprecation_cython
|
|
3793
|
+
deprecation_cython(38077, "The function is_Vector is deprecated; use 'isinstance(..., Vector)' instead.")
|
|
3794
|
+
return isinstance(x, Vector)
|
|
3795
|
+
|
|
3796
|
+
|
|
3797
|
+
cdef class Matrix(ModuleElement):
|
|
3798
|
+
|
|
3799
|
+
cdef bint is_sparse_c(self) noexcept:
|
|
3800
|
+
raise NotImplementedError
|
|
3801
|
+
|
|
3802
|
+
cdef bint is_dense_c(self) noexcept:
|
|
3803
|
+
raise NotImplementedError
|
|
3804
|
+
|
|
3805
|
+
def __mul__(left, right):
|
|
3806
|
+
"""
|
|
3807
|
+
Multiplication of matrix by matrix, vector, or scalar.
|
|
3808
|
+
|
|
3809
|
+
AUTHOR:
|
|
3810
|
+
|
|
3811
|
+
- Gonzalo Tornaria (2007-06-25) - write test cases and fix them
|
|
3812
|
+
|
|
3813
|
+
.. NOTE::
|
|
3814
|
+
|
|
3815
|
+
scalar * matrix is implemented (and tested) in class RingElement
|
|
3816
|
+
vector * matrix is implemented (and tested) in class Vector
|
|
3817
|
+
|
|
3818
|
+
TESTS:
|
|
3819
|
+
|
|
3820
|
+
Here we test (matrix * matrix) multiplication::
|
|
3821
|
+
|
|
3822
|
+
sage: # needs sage.modules
|
|
3823
|
+
sage: parent(matrix(ZZ, 2, 2, [1,2,3,4]) * matrix(ZZ, 2, 2, [1,2,3,4]))
|
|
3824
|
+
Full MatrixSpace of 2 by 2 dense matrices over Integer Ring
|
|
3825
|
+
sage: parent(matrix(QQ, 2, 2, [1,2,3,4]) * matrix(ZZ, 2, 2, [1,2,3,4]))
|
|
3826
|
+
Full MatrixSpace of 2 by 2 dense matrices over Rational Field
|
|
3827
|
+
sage: parent(matrix(ZZ, 2, 2, [1,2,3,4]) * matrix(QQ, 2, 2, [1,2,3,4]))
|
|
3828
|
+
Full MatrixSpace of 2 by 2 dense matrices over Rational Field
|
|
3829
|
+
sage: parent(matrix(QQ, 2, 2, [1,2,3,4]) * matrix(QQ, 2, 2, [1,2,3,4]))
|
|
3830
|
+
Full MatrixSpace of 2 by 2 dense matrices over Rational Field
|
|
3831
|
+
|
|
3832
|
+
sage: parent(matrix(QQ, 2, 2, [1,2,3,4]) * matrix(ZZ['x'], 2, 2, [1,2,3,4])) # needs sage.modules
|
|
3833
|
+
Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Rational Field
|
|
3834
|
+
sage: parent(matrix(ZZ['x'], 2, 2, [1,2,3,4]) * matrix(QQ, 2, 2, [1,2,3,4])) # needs sage.modules
|
|
3835
|
+
Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Rational Field
|
|
3836
|
+
|
|
3837
|
+
sage: parent(matrix(QQ, 2, 2, [1,2,3,4]) * matrix(ZZ['x']['y'], 2, 2, [1,2,3,4])) # needs sage.modules
|
|
3838
|
+
Full MatrixSpace of 2 by 2 dense matrices over
|
|
3839
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3840
|
+
sage: parent(matrix(ZZ['x']['y'], 2, 2, [1,2,3,4]) * matrix(QQ, 2, 2, [1,2,3,4])) # needs sage.modules
|
|
3841
|
+
Full MatrixSpace of 2 by 2 dense matrices over
|
|
3842
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3843
|
+
|
|
3844
|
+
sage: parent(matrix(QQ['x'], 2, 2, [1,2,3,4]) * matrix(ZZ['x']['y'], 2, 2, [1,2,3,4])) # needs sage.modules
|
|
3845
|
+
Full MatrixSpace of 2 by 2 dense matrices over
|
|
3846
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3847
|
+
sage: parent(matrix(ZZ['x']['y'], 2, 2, [1,2,3,4]) * matrix(QQ['x'], 2, 2, [1,2,3,4])) # needs sage.modules
|
|
3848
|
+
Full MatrixSpace of 2 by 2 dense matrices over
|
|
3849
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3850
|
+
|
|
3851
|
+
sage: parent(matrix(QQ['y'], 2, 2, [1,2,3,4]) * matrix(ZZ['x']['y'], 2, 2, [1,2,3,4])) # needs sage.modules
|
|
3852
|
+
Full MatrixSpace of 2 by 2 dense matrices over
|
|
3853
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3854
|
+
sage: parent(matrix(ZZ['x']['y'], 2, 2, [1,2,3,4]) * matrix(QQ['y'], 2, 2, [1,2,3,4])) # needs sage.modules
|
|
3855
|
+
Full MatrixSpace of 2 by 2 dense matrices over
|
|
3856
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3857
|
+
|
|
3858
|
+
sage: # needs sage.modules
|
|
3859
|
+
sage: parent(matrix(ZZ['x'], 2, 2, [1,2,3,4]) * matrix(ZZ['y'], 2, 2, [1,2,3,4]))
|
|
3860
|
+
Traceback (most recent call last):
|
|
3861
|
+
...
|
|
3862
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3863
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Integer Ring' and
|
|
3864
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in y over Integer Ring'
|
|
3865
|
+
sage: parent(matrix(ZZ['x'], 2, 2, [1,2,3,4]) * matrix(QQ['y'], 2, 2, [1,2,3,4]))
|
|
3866
|
+
Traceback (most recent call last):
|
|
3867
|
+
...
|
|
3868
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3869
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Integer Ring' and
|
|
3870
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in y over Rational Field'
|
|
3871
|
+
sage: parent(matrix(QQ['x'], 2, 2, [1,2,3,4]) * matrix(ZZ['y'], 2, 2, [1,2,3,4]))
|
|
3872
|
+
Traceback (most recent call last):
|
|
3873
|
+
...
|
|
3874
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3875
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Rational Field' and
|
|
3876
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in y over Integer Ring'
|
|
3877
|
+
sage: parent(matrix(QQ['x'], 2, 2, [1,2,3,4]) * matrix(QQ['y'], 2, 2, [1,2,3,4]))
|
|
3878
|
+
Traceback (most recent call last):
|
|
3879
|
+
...
|
|
3880
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3881
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Rational Field' and
|
|
3882
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in y over Rational Field'
|
|
3883
|
+
|
|
3884
|
+
We test that the bug reported in :issue:`27352` has been fixed::
|
|
3885
|
+
|
|
3886
|
+
sage: A = matrix(QQ, [[1, 2], [-1, 0], [1, 1]]) # needs sage.modules
|
|
3887
|
+
sage: B = matrix(QQ, [[0, 4], [1, -1], [1, 2]]) # needs sage.modules
|
|
3888
|
+
sage: A * B # needs sage.modules
|
|
3889
|
+
Traceback (most recent call last):
|
|
3890
|
+
...
|
|
3891
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3892
|
+
'Full MatrixSpace of 3 by 2 dense matrices over Rational Field' and 'Full MatrixSpace of 3 by 2 dense matrices over Rational Field'
|
|
3893
|
+
|
|
3894
|
+
Here we test (matrix * vector) multiplication::
|
|
3895
|
+
|
|
3896
|
+
sage: # needs sage.modules
|
|
3897
|
+
sage: parent(matrix(ZZ, 2, 2, [1,2,3,4]) * vector(ZZ, [1,2]))
|
|
3898
|
+
Ambient free module of rank 2 over the principal ideal domain Integer Ring
|
|
3899
|
+
sage: parent(matrix(QQ, 2, 2, [1,2,3,4]) * vector(ZZ, [1,2]))
|
|
3900
|
+
Vector space of dimension 2 over Rational Field
|
|
3901
|
+
sage: parent(matrix(ZZ, 2, 2, [1,2,3,4]) * vector(QQ, [1,2]))
|
|
3902
|
+
Vector space of dimension 2 over Rational Field
|
|
3903
|
+
sage: parent(matrix(QQ, 2, 2, [1,2,3,4]) * vector(QQ, [1,2]))
|
|
3904
|
+
Vector space of dimension 2 over Rational Field
|
|
3905
|
+
|
|
3906
|
+
sage: parent(matrix(QQ, 2, 2, [1,2,3,4]) * vector(ZZ['x'], [1,2])) # needs sage.modules
|
|
3907
|
+
Ambient free module of rank 2 over the principal ideal domain
|
|
3908
|
+
Univariate Polynomial Ring in x over Rational Field
|
|
3909
|
+
sage: parent(matrix(ZZ['x'], 2, 2, [1,2,3,4]) * vector(QQ, [1,2])) # needs sage.modules
|
|
3910
|
+
Ambient free module of rank 2 over the principal ideal domain
|
|
3911
|
+
Univariate Polynomial Ring in x over Rational Field
|
|
3912
|
+
|
|
3913
|
+
sage: parent(matrix(QQ, 2, 2, [1,2,3,4]) * vector(ZZ['x']['y'], [1,2])) # needs sage.modules
|
|
3914
|
+
Ambient free module of rank 2 over the integral domain
|
|
3915
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3916
|
+
sage: parent(matrix(ZZ['x']['y'], 2, 2, [1,2,3,4]) * vector(QQ, [1,2])) # needs sage.modules
|
|
3917
|
+
Ambient free module of rank 2 over the integral domain
|
|
3918
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3919
|
+
|
|
3920
|
+
sage: parent(matrix(QQ['x'], 2, 2, [1,2,3,4]) * vector(ZZ['x']['y'], [1,2])) # needs sage.modules
|
|
3921
|
+
Ambient free module of rank 2 over the integral domain
|
|
3922
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3923
|
+
sage: parent(matrix(ZZ['x']['y'], 2, 2, [1,2,3,4]) * vector(QQ['x'], [1,2])) # needs sage.modules
|
|
3924
|
+
Ambient free module of rank 2 over the integral domain
|
|
3925
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3926
|
+
|
|
3927
|
+
sage: parent(matrix(QQ['y'], 2, 2, [1,2,3,4]) * vector(ZZ['x']['y'], [1,2])) # needs sage.modules
|
|
3928
|
+
Ambient free module of rank 2 over the integral domain
|
|
3929
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3930
|
+
sage: parent(matrix(ZZ['x']['y'], 2, 2, [1,2,3,4]) * vector(QQ['y'], [1,2])) # needs sage.modules
|
|
3931
|
+
Ambient free module of rank 2 over the integral domain
|
|
3932
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3933
|
+
|
|
3934
|
+
sage: # needs sage.modules
|
|
3935
|
+
sage: parent(matrix(ZZ['x'], 2, 2, [1,2,3,4]) * vector(ZZ['y'], [1,2]))
|
|
3936
|
+
Traceback (most recent call last):
|
|
3937
|
+
...
|
|
3938
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3939
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Integer Ring' and
|
|
3940
|
+
'Ambient free module of rank 2 over the integral domain Univariate Polynomial Ring in y over Integer Ring'
|
|
3941
|
+
sage: parent(matrix(ZZ['x'], 2, 2, [1,2,3,4]) * vector(QQ['y'], [1,2]))
|
|
3942
|
+
Traceback (most recent call last):
|
|
3943
|
+
...
|
|
3944
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3945
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Integer Ring' and
|
|
3946
|
+
'Ambient free module of rank 2 over the principal ideal domain Univariate Polynomial Ring in y over Rational Field'
|
|
3947
|
+
sage: parent(matrix(QQ['x'], 2, 2, [1,2,3,4]) * vector(ZZ['y'], [1,2]))
|
|
3948
|
+
Traceback (most recent call last):
|
|
3949
|
+
...
|
|
3950
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3951
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Rational Field' and
|
|
3952
|
+
'Ambient free module of rank 2 over the integral domain Univariate Polynomial Ring in y over Integer Ring'
|
|
3953
|
+
sage: parent(matrix(QQ['x'], 2, 2, [1,2,3,4]) * vector(QQ['y'], [1,2]))
|
|
3954
|
+
Traceback (most recent call last):
|
|
3955
|
+
...
|
|
3956
|
+
TypeError: unsupported operand parent(s) for *:
|
|
3957
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Rational Field' and
|
|
3958
|
+
'Ambient free module of rank 2 over the principal ideal domain Univariate Polynomial Ring in y over Rational Field'
|
|
3959
|
+
|
|
3960
|
+
Here we test (matrix * scalar) multiplication::
|
|
3961
|
+
|
|
3962
|
+
sage: # needs sage.modules
|
|
3963
|
+
sage: parent(matrix(ZZ, 2, 2, [1,2,3,4]) * ZZ(1))
|
|
3964
|
+
Full MatrixSpace of 2 by 2 dense matrices over Integer Ring
|
|
3965
|
+
sage: parent(matrix(QQ, 2, 2, [1,2,3,4]) * ZZ(1))
|
|
3966
|
+
Full MatrixSpace of 2 by 2 dense matrices over Rational Field
|
|
3967
|
+
sage: parent(matrix(ZZ, 2, 2, [1,2,3,4]) * QQ(1))
|
|
3968
|
+
Full MatrixSpace of 2 by 2 dense matrices over Rational Field
|
|
3969
|
+
sage: parent(matrix(QQ, 2, 2, [1,2,3,4]) * QQ(1))
|
|
3970
|
+
Full MatrixSpace of 2 by 2 dense matrices over Rational Field
|
|
3971
|
+
|
|
3972
|
+
sage: parent(matrix(QQ, 2, 2, [1,2,3,4]) * ZZ['x'](1)) # needs sage.modules
|
|
3973
|
+
Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Rational Field
|
|
3974
|
+
sage: parent(matrix(ZZ['x'], 2, 2, [1,2,3,4]) * QQ(1)) # needs sage.modules
|
|
3975
|
+
Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Rational Field
|
|
3976
|
+
|
|
3977
|
+
sage: parent(matrix(QQ, 2, 2, [1,2,3,4]) * ZZ['x']['y'](1)) # needs sage.modules
|
|
3978
|
+
Full MatrixSpace of 2 by 2 dense matrices over
|
|
3979
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3980
|
+
sage: parent(matrix(ZZ['x']['y'], 2, 2, [1,2,3,4]) * QQ(1)) # needs sage.modules
|
|
3981
|
+
Full MatrixSpace of 2 by 2 dense matrices over
|
|
3982
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3983
|
+
|
|
3984
|
+
sage: parent(matrix(QQ['x'], 2, 2, [1,2,3,4]) * ZZ['x']['y'](1)) # needs sage.modules
|
|
3985
|
+
Full MatrixSpace of 2 by 2 dense matrices over
|
|
3986
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3987
|
+
sage: parent(matrix(ZZ['x']['y'], 2, 2, [1,2,3,4]) * QQ['x'](1)) # needs sage.modules
|
|
3988
|
+
Full MatrixSpace of 2 by 2 dense matrices over
|
|
3989
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3990
|
+
|
|
3991
|
+
sage: parent(matrix(QQ['y'], 2, 2, [1,2,3,4]) * ZZ['x']['y'](1)) # needs sage.modules
|
|
3992
|
+
Full MatrixSpace of 2 by 2 dense matrices over
|
|
3993
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3994
|
+
sage: parent(matrix(ZZ['x']['y'], 2, 2, [1,2,3,4]) * QQ['y'](1)) # needs sage.modules
|
|
3995
|
+
Full MatrixSpace of 2 by 2 dense matrices over
|
|
3996
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
3997
|
+
|
|
3998
|
+
sage: # needs sage.modules
|
|
3999
|
+
sage: parent(matrix(ZZ['x'], 2, 2, [1,2,3,4]) * ZZ['y'](1))
|
|
4000
|
+
Traceback (most recent call last):
|
|
4001
|
+
...
|
|
4002
|
+
TypeError: unsupported operand parent(s) for *:
|
|
4003
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Integer Ring' and
|
|
4004
|
+
'Univariate Polynomial Ring in y over Integer Ring'
|
|
4005
|
+
sage: parent(matrix(ZZ['x'], 2, 2, [1,2,3,4]) * QQ['y'](1))
|
|
4006
|
+
Traceback (most recent call last):
|
|
4007
|
+
...
|
|
4008
|
+
TypeError: unsupported operand parent(s) for *:
|
|
4009
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Integer Ring' and
|
|
4010
|
+
'Univariate Polynomial Ring in y over Rational Field'
|
|
4011
|
+
sage: parent(matrix(QQ['x'], 2, 2, [1,2,3,4]) * ZZ['y'](1))
|
|
4012
|
+
Traceback (most recent call last):
|
|
4013
|
+
...
|
|
4014
|
+
TypeError: unsupported operand parent(s) for *:
|
|
4015
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Rational Field' and
|
|
4016
|
+
'Univariate Polynomial Ring in y over Integer Ring'
|
|
4017
|
+
sage: parent(matrix(QQ['x'], 2, 2, [1,2,3,4]) * QQ['y'](1))
|
|
4018
|
+
Traceback (most recent call last):
|
|
4019
|
+
...
|
|
4020
|
+
TypeError: unsupported operand parent(s) for *:
|
|
4021
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Rational Field' and
|
|
4022
|
+
'Univariate Polynomial Ring in y over Rational Field'
|
|
4023
|
+
|
|
4024
|
+
Here we test (scalar * matrix) multiplication::
|
|
4025
|
+
|
|
4026
|
+
sage: # needs sage.modules
|
|
4027
|
+
sage: parent(ZZ(1) * matrix(ZZ, 2, 2, [1,2,3,4]))
|
|
4028
|
+
Full MatrixSpace of 2 by 2 dense matrices over Integer Ring
|
|
4029
|
+
sage: parent(QQ(1) * matrix(ZZ, 2, 2, [1,2,3,4]))
|
|
4030
|
+
Full MatrixSpace of 2 by 2 dense matrices over Rational Field
|
|
4031
|
+
sage: parent(ZZ(1) * matrix(QQ, 2, 2, [1,2,3,4]))
|
|
4032
|
+
Full MatrixSpace of 2 by 2 dense matrices over Rational Field
|
|
4033
|
+
sage: parent(QQ(1) * matrix(QQ, 2, 2, [1,2,3,4]))
|
|
4034
|
+
Full MatrixSpace of 2 by 2 dense matrices over Rational Field
|
|
4035
|
+
|
|
4036
|
+
sage: parent(QQ(1) * matrix(ZZ['x'], 2, 2, [1,2,3,4])) # needs sage.modules
|
|
4037
|
+
Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Rational Field
|
|
4038
|
+
sage: parent(ZZ['x'](1) * matrix(QQ, 2, 2, [1,2,3,4])) # needs sage.modules
|
|
4039
|
+
Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Rational Field
|
|
4040
|
+
|
|
4041
|
+
sage: parent(QQ(1) * matrix(ZZ['x']['y'], 2, 2, [1,2,3,4])) # needs sage.modules
|
|
4042
|
+
Full MatrixSpace of 2 by 2 dense matrices over
|
|
4043
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
4044
|
+
sage: parent(ZZ['x']['y'](1) * matrix(QQ, 2, 2, [1,2,3,4])) # needs sage.modules
|
|
4045
|
+
Full MatrixSpace of 2 by 2 dense matrices over
|
|
4046
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
4047
|
+
|
|
4048
|
+
sage: parent(QQ['x'](1) * matrix(ZZ['x']['y'], 2, 2, [1,2,3,4])) # needs sage.modules
|
|
4049
|
+
Full MatrixSpace of 2 by 2 dense matrices over
|
|
4050
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
4051
|
+
sage: parent(ZZ['x']['y'](1) * matrix(QQ['x'], 2, 2, [1,2,3,4])) # needs sage.modules
|
|
4052
|
+
Full MatrixSpace of 2 by 2 dense matrices over
|
|
4053
|
+
Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
4054
|
+
|
|
4055
|
+
sage: parent(QQ['y'](1) * matrix(ZZ['x']['y'], 2, 2, [1,2,3,4])) # needs sage.modules
|
|
4056
|
+
Full MatrixSpace of 2 by 2 dense matrices
|
|
4057
|
+
over Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
4058
|
+
sage: parent(ZZ['x']['y'](1) * matrix(QQ['y'], 2, 2, [1,2,3,4])) # needs sage.modules
|
|
4059
|
+
Full MatrixSpace of 2 by 2 dense matrices
|
|
4060
|
+
over Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field
|
|
4061
|
+
|
|
4062
|
+
sage: # needs sage.modules
|
|
4063
|
+
sage: parent(ZZ['x'](1) * matrix(ZZ['y'], 2, 2, [1,2,3,4]))
|
|
4064
|
+
Traceback (most recent call last):
|
|
4065
|
+
...
|
|
4066
|
+
TypeError: unsupported operand parent(s) for *:
|
|
4067
|
+
'Univariate Polynomial Ring in x over Integer Ring' and
|
|
4068
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in y over Integer Ring'
|
|
4069
|
+
sage: parent(ZZ['x'](1) * matrix(QQ['y'], 2, 2, [1,2,3,4]))
|
|
4070
|
+
Traceback (most recent call last):
|
|
4071
|
+
...
|
|
4072
|
+
TypeError: unsupported operand parent(s) for *:
|
|
4073
|
+
'Univariate Polynomial Ring in x over Integer Ring' and
|
|
4074
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in y over Rational Field'
|
|
4075
|
+
sage: parent(QQ['x'](1) * matrix(ZZ['y'], 2, 2, [1,2,3,4]))
|
|
4076
|
+
Traceback (most recent call last):
|
|
4077
|
+
...
|
|
4078
|
+
TypeError: unsupported operand parent(s) for *:
|
|
4079
|
+
'Univariate Polynomial Ring in x over Rational Field' and
|
|
4080
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in y over Integer Ring'
|
|
4081
|
+
sage: parent(QQ['x'](1) * matrix(QQ['y'], 2, 2, [1,2,3,4]))
|
|
4082
|
+
Traceback (most recent call last):
|
|
4083
|
+
...
|
|
4084
|
+
TypeError: unsupported operand parent(s) for *:
|
|
4085
|
+
'Univariate Polynomial Ring in x over Rational Field' and
|
|
4086
|
+
'Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in y over Rational Field'
|
|
4087
|
+
|
|
4088
|
+
Examples with matrices having matrix coefficients::
|
|
4089
|
+
|
|
4090
|
+
sage: m = matrix # needs sage.modules
|
|
4091
|
+
sage: a = m([[m([[1,2],[3,4]]),m([[5,6],[7,8]])],[m([[9,10],[11,12]]),m([[13,14],[15,16]])]]) # needs sage.modules
|
|
4092
|
+
sage: 3 * a # needs sage.modules
|
|
4093
|
+
[[ 3 6]
|
|
4094
|
+
[ 9 12] [15 18]
|
|
4095
|
+
[21 24]]
|
|
4096
|
+
[[27 30]
|
|
4097
|
+
[33 36] [39 42]
|
|
4098
|
+
[45 48]]
|
|
4099
|
+
|
|
4100
|
+
sage: m = matrix # needs sage.modules
|
|
4101
|
+
sage: a = m([[m([[1,2],[3,4]]),m([[5,6],[7,8]])],[m([[9,10],[11,12]]),m([[13,14],[15,16]])]]) # needs sage.modules
|
|
4102
|
+
sage: a * 3 # needs sage.modules
|
|
4103
|
+
[[ 3 6]
|
|
4104
|
+
[ 9 12] [15 18]
|
|
4105
|
+
[21 24]]
|
|
4106
|
+
[[27 30]
|
|
4107
|
+
[33 36] [39 42]
|
|
4108
|
+
[45 48]]
|
|
4109
|
+
"""
|
|
4110
|
+
cdef int cl = classify_elements(left, right)
|
|
4111
|
+
if HAVE_SAME_PARENT(cl):
|
|
4112
|
+
# If they are matrices with the same parent, they had
|
|
4113
|
+
# better be square for the product to be defined.
|
|
4114
|
+
if (<Matrix>left)._nrows == (<Matrix>left)._ncols:
|
|
4115
|
+
return (<Matrix>left)._matrix_times_matrix_(<Matrix>right)
|
|
4116
|
+
else:
|
|
4117
|
+
parent = (<Matrix>left)._parent
|
|
4118
|
+
raise TypeError("unsupported operand parent(s) for *: '{}' and '{}'".format(parent, parent))
|
|
4119
|
+
|
|
4120
|
+
if BOTH_ARE_ELEMENT(cl):
|
|
4121
|
+
return coercion_model.bin_op(left, right, mul)
|
|
4122
|
+
|
|
4123
|
+
cdef long value
|
|
4124
|
+
cdef int err = -1
|
|
4125
|
+
try:
|
|
4126
|
+
# Special case multiplication with C long
|
|
4127
|
+
integer_check_long_py(right, &value, &err)
|
|
4128
|
+
if not err:
|
|
4129
|
+
return (<Element>left)._mul_long(value)
|
|
4130
|
+
integer_check_long_py(left, &value, &err)
|
|
4131
|
+
if not err:
|
|
4132
|
+
return (<Element>right)._mul_long(value)
|
|
4133
|
+
return coercion_model.bin_op(left, right, mul)
|
|
4134
|
+
except TypeError:
|
|
4135
|
+
return NotImplemented
|
|
4136
|
+
|
|
4137
|
+
def __truediv__(left, right):
|
|
4138
|
+
"""
|
|
4139
|
+
Division of the matrix ``left`` by the matrix or scalar
|
|
4140
|
+
``right``.
|
|
4141
|
+
|
|
4142
|
+
EXAMPLES::
|
|
4143
|
+
|
|
4144
|
+
sage: # needs sage.modules
|
|
4145
|
+
sage: a = matrix(ZZ, 2, range(4))
|
|
4146
|
+
sage: operator.truediv(a, 5)
|
|
4147
|
+
[ 0 1/5]
|
|
4148
|
+
[2/5 3/5]
|
|
4149
|
+
sage: a = matrix(ZZ, 2, range(4))
|
|
4150
|
+
sage: b = matrix(ZZ, 2, [1,1,0,5])
|
|
4151
|
+
sage: operator.truediv(a, b)
|
|
4152
|
+
[ 0 1/5]
|
|
4153
|
+
[ 2 1/5]
|
|
4154
|
+
sage: c = matrix(QQ, 2, [3,2,5,7])
|
|
4155
|
+
sage: operator.truediv(c, a)
|
|
4156
|
+
[-5/2 3/2]
|
|
4157
|
+
[-1/2 5/2]
|
|
4158
|
+
|
|
4159
|
+
TESTS::
|
|
4160
|
+
|
|
4161
|
+
sage: # needs sage.modules
|
|
4162
|
+
sage: a = matrix(ZZ, [[1, 2], [0, 3]])
|
|
4163
|
+
sage: b = matrix(ZZ, 3, 2, range(6))
|
|
4164
|
+
sage: x = b / a; x
|
|
4165
|
+
[ 0 1/3]
|
|
4166
|
+
[ 2 -1/3]
|
|
4167
|
+
[ 4 -1]
|
|
4168
|
+
sage: x == b * ~a
|
|
4169
|
+
True
|
|
4170
|
+
sage: a = matrix(ZZ, [[1, 2], [0, 3], [1, 5]])
|
|
4171
|
+
sage: (b / a) * a == b
|
|
4172
|
+
True
|
|
4173
|
+
"""
|
|
4174
|
+
if isinstance(right, Matrix):
|
|
4175
|
+
return right.solve_left(left)
|
|
4176
|
+
return coercion_model.bin_op(left, right, truediv)
|
|
4177
|
+
|
|
4178
|
+
cdef _vector_times_matrix_(matrix_right, Vector vector_left):
|
|
4179
|
+
raise TypeError
|
|
4180
|
+
|
|
4181
|
+
cdef _matrix_times_vector_(matrix_left, Vector vector_right):
|
|
4182
|
+
raise TypeError
|
|
4183
|
+
|
|
4184
|
+
cdef _matrix_times_matrix_(left, Matrix right):
|
|
4185
|
+
raise TypeError
|
|
4186
|
+
|
|
4187
|
+
|
|
4188
|
+
def is_Matrix(x):
|
|
4189
|
+
from sage.misc.superseded import deprecation_cython
|
|
4190
|
+
deprecation_cython(38077, "The function is_Matrix is deprecated; use 'isinstance(..., Matrix)' instead.")
|
|
4191
|
+
return isinstance(x, Matrix)
|
|
4192
|
+
|
|
4193
|
+
|
|
4194
|
+
def is_IntegralDomainElement(x):
|
|
4195
|
+
"""
|
|
4196
|
+
Return ``True`` if x is of type IntegralDomainElement.
|
|
4197
|
+
"""
|
|
4198
|
+
from sage.misc.superseded import deprecation_cython
|
|
4199
|
+
deprecation_cython(38077, "The function is_IntegralDomainElement is deprecated; use 'isinstance(..., IntegralDomainElement)' instead.")
|
|
4200
|
+
return isinstance(x, IntegralDomainElement)
|
|
4201
|
+
|
|
4202
|
+
|
|
4203
|
+
cdef class IntegralDomainElement(CommutativeRingElement):
|
|
4204
|
+
def is_nilpotent(self):
|
|
4205
|
+
return self.is_zero()
|
|
4206
|
+
|
|
4207
|
+
|
|
4208
|
+
def is_DedekindDomainElement(x):
|
|
4209
|
+
"""
|
|
4210
|
+
Return ``True`` if x is of type DedekindDomainElement.
|
|
4211
|
+
"""
|
|
4212
|
+
from sage.misc.superseded import deprecation_cython
|
|
4213
|
+
deprecation_cython(38077, "The function is_DedekindDomainElement is deprecated; use 'isinstance(..., DedekindDomainElement)' instead.")
|
|
4214
|
+
return isinstance(x, DedekindDomainElement)
|
|
4215
|
+
|
|
4216
|
+
|
|
4217
|
+
cdef class DedekindDomainElement(IntegralDomainElement):
|
|
4218
|
+
pass
|
|
4219
|
+
|
|
4220
|
+
|
|
4221
|
+
def is_PrincipalIdealDomainElement(x):
|
|
4222
|
+
"""
|
|
4223
|
+
Return ``True`` if x is of type PrincipalIdealDomainElement.
|
|
4224
|
+
"""
|
|
4225
|
+
from sage.misc.superseded import deprecation_cython
|
|
4226
|
+
deprecation_cython(38077, "The function is_PrincipalIdealDomainElement is deprecated; use 'isinstance(..., PrincipalIdealDomainElement)' instead.")
|
|
4227
|
+
return isinstance(x, PrincipalIdealDomainElement)
|
|
4228
|
+
|
|
4229
|
+
|
|
4230
|
+
cdef class PrincipalIdealDomainElement(DedekindDomainElement):
|
|
4231
|
+
def gcd(self, right):
|
|
4232
|
+
r"""
|
|
4233
|
+
Return the greatest common divisor of ``self`` and ``other``.
|
|
4234
|
+
|
|
4235
|
+
TESTS:
|
|
4236
|
+
|
|
4237
|
+
:issue:`30849`::
|
|
4238
|
+
|
|
4239
|
+
sage: 2.gcd(pari(3)) # needs sage.libs.pari
|
|
4240
|
+
1
|
|
4241
|
+
sage: type(2.gcd(pari(3))) # needs sage.libs.pari
|
|
4242
|
+
<class 'sage.rings.integer.Integer'>
|
|
4243
|
+
|
|
4244
|
+
sage: 2.gcd(pari('1/3')) # needs sage.libs.pari
|
|
4245
|
+
1/3
|
|
4246
|
+
sage: type(2.gcd(pari('1/3'))) # needs sage.libs.pari
|
|
4247
|
+
<class 'sage.rings.rational.Rational'>
|
|
4248
|
+
|
|
4249
|
+
sage: import gmpy2
|
|
4250
|
+
sage: 2.gcd(gmpy2.mpz(3))
|
|
4251
|
+
1
|
|
4252
|
+
sage: type(2.gcd(gmpy2.mpz(3)))
|
|
4253
|
+
<class 'sage.rings.integer.Integer'>
|
|
4254
|
+
|
|
4255
|
+
sage: 2.gcd(gmpy2.mpq(1,3))
|
|
4256
|
+
1/3
|
|
4257
|
+
sage: type(2.gcd(pari('1/3'))) # needs sage.libs.pari
|
|
4258
|
+
<class 'sage.rings.rational.Rational'>
|
|
4259
|
+
"""
|
|
4260
|
+
# NOTE: in order to handle nicely pari or gmpy2 integers we do not rely only on coercion
|
|
4261
|
+
if not isinstance(right, Element):
|
|
4262
|
+
right = py_scalar_to_element(right)
|
|
4263
|
+
if not isinstance(right, Element):
|
|
4264
|
+
right = right.sage()
|
|
4265
|
+
if not ((<Element>right)._parent is self._parent):
|
|
4266
|
+
from sage.arith.misc import GCD as gcd
|
|
4267
|
+
return coercion_model.bin_op(self, right, gcd)
|
|
4268
|
+
return self._gcd(right)
|
|
4269
|
+
|
|
4270
|
+
def lcm(self, right):
|
|
4271
|
+
"""
|
|
4272
|
+
Return the least common multiple of ``self`` and ``right``.
|
|
4273
|
+
|
|
4274
|
+
TESTS:
|
|
4275
|
+
|
|
4276
|
+
:issue:`30849`::
|
|
4277
|
+
|
|
4278
|
+
sage: 2.lcm(pari(3)) # needs sage.libs.pari
|
|
4279
|
+
6
|
|
4280
|
+
sage: type(2.lcm(pari(3))) # needs sage.libs.pari
|
|
4281
|
+
<class 'sage.rings.integer.Integer'>
|
|
4282
|
+
|
|
4283
|
+
sage: 2.lcm(pari('1/3')) # needs sage.libs.pari
|
|
4284
|
+
2
|
|
4285
|
+
sage: type(2.lcm(pari('1/3'))) # needs sage.libs.pari
|
|
4286
|
+
<class 'sage.rings.rational.Rational'>
|
|
4287
|
+
|
|
4288
|
+
sage: import gmpy2
|
|
4289
|
+
sage: 2.lcm(gmpy2.mpz(3))
|
|
4290
|
+
6
|
|
4291
|
+
sage: type(2.lcm(gmpy2.mpz(3)))
|
|
4292
|
+
<class 'sage.rings.integer.Integer'>
|
|
4293
|
+
"""
|
|
4294
|
+
# NOTE: in order to handle nicely pari or gmpy2 integers we do not rely only on coercion
|
|
4295
|
+
if not isinstance(right, Element):
|
|
4296
|
+
right = py_scalar_to_element(right)
|
|
4297
|
+
if not isinstance(right, Element):
|
|
4298
|
+
right = right.sage()
|
|
4299
|
+
if not ((<Element>right)._parent is self._parent):
|
|
4300
|
+
from sage.arith.functions import lcm
|
|
4301
|
+
return coercion_model.bin_op(self, right, lcm)
|
|
4302
|
+
return self._lcm(right)
|
|
4303
|
+
|
|
4304
|
+
# This is pretty nasty low level stuff. The idea is to speed up construction
|
|
4305
|
+
# of EuclideanDomainElements (in particular Integers) by skipping some tp_new
|
|
4306
|
+
# calls up the inheritance tree.
|
|
4307
|
+
PY_SET_TP_NEW(EuclideanDomainElement, Element)
|
|
4308
|
+
|
|
4309
|
+
|
|
4310
|
+
def is_EuclideanDomainElement(x):
|
|
4311
|
+
"""
|
|
4312
|
+
Return ``True`` if x is of type EuclideanDomainElement.
|
|
4313
|
+
"""
|
|
4314
|
+
from sage.misc.superseded import deprecation_cython
|
|
4315
|
+
deprecation_cython(38077, "The function is_EuclideanDomainElement is deprecated; use 'isinstance(..., EuclideanDomainElement)' instead.")
|
|
4316
|
+
return isinstance(x, EuclideanDomainElement)
|
|
4317
|
+
|
|
4318
|
+
|
|
4319
|
+
cdef class EuclideanDomainElement(PrincipalIdealDomainElement):
|
|
4320
|
+
|
|
4321
|
+
def degree(self):
|
|
4322
|
+
raise NotImplementedError
|
|
4323
|
+
|
|
4324
|
+
def leading_coefficient(self):
|
|
4325
|
+
raise NotImplementedError
|
|
4326
|
+
|
|
4327
|
+
def quo_rem(self, other):
|
|
4328
|
+
raise NotImplementedError
|
|
4329
|
+
|
|
4330
|
+
cpdef _floordiv_(self, right):
|
|
4331
|
+
"""
|
|
4332
|
+
Quotient of division of ``self`` by ``other``. This is denoted ``//``.
|
|
4333
|
+
|
|
4334
|
+
This default implementation assumes that ``quo_rem`` has been
|
|
4335
|
+
implemented.
|
|
4336
|
+
|
|
4337
|
+
EXAMPLES::
|
|
4338
|
+
|
|
4339
|
+
sage: cython( # needs sage.misc.cython
|
|
4340
|
+
....: '''
|
|
4341
|
+
....: from sage.structure.element cimport EuclideanDomainElement
|
|
4342
|
+
....: cdef class MyElt(EuclideanDomainElement):
|
|
4343
|
+
....: def quo_rem(self, other):
|
|
4344
|
+
....: return self._parent.var('quo,rem')
|
|
4345
|
+
....: ''')
|
|
4346
|
+
sage: e = MyElt(SR) # needs sage.misc.cython sage.symbolic
|
|
4347
|
+
sage: e // e # needs sage.misc.cython sage.symbolic
|
|
4348
|
+
quo
|
|
4349
|
+
"""
|
|
4350
|
+
Q, _ = self.quo_rem(right)
|
|
4351
|
+
return Q
|
|
4352
|
+
|
|
4353
|
+
cpdef _mod_(self, other):
|
|
4354
|
+
"""
|
|
4355
|
+
Remainder of division of ``self`` by ``other``.
|
|
4356
|
+
|
|
4357
|
+
This default implementation assumes that ``quo_rem`` has been
|
|
4358
|
+
implemented.
|
|
4359
|
+
|
|
4360
|
+
EXAMPLES::
|
|
4361
|
+
|
|
4362
|
+
sage: R.<x> = ZZ[]
|
|
4363
|
+
sage: x % (x+1)
|
|
4364
|
+
-1
|
|
4365
|
+
sage: (x^3 + x - 1) % (x^2 - 1)
|
|
4366
|
+
2*x - 1
|
|
4367
|
+
|
|
4368
|
+
::
|
|
4369
|
+
|
|
4370
|
+
sage: cython( # needs sage.misc.cython
|
|
4371
|
+
....: '''
|
|
4372
|
+
....: from sage.structure.element cimport EuclideanDomainElement
|
|
4373
|
+
....: cdef class MyElt(EuclideanDomainElement):
|
|
4374
|
+
....: def quo_rem(self, other):
|
|
4375
|
+
....: return self._parent.var('quo,rem')
|
|
4376
|
+
....: ''')
|
|
4377
|
+
sage: e = MyElt(SR) # needs sage.misc.cython sage.symbolic
|
|
4378
|
+
sage: e % e # needs sage.misc.cython sage.symbolic
|
|
4379
|
+
rem
|
|
4380
|
+
"""
|
|
4381
|
+
_, R = self.quo_rem(other)
|
|
4382
|
+
return R
|
|
4383
|
+
|
|
4384
|
+
|
|
4385
|
+
def is_FieldElement(x):
|
|
4386
|
+
"""
|
|
4387
|
+
Return ``True`` if x is of type FieldElement.
|
|
4388
|
+
"""
|
|
4389
|
+
from sage.misc.superseded import deprecation_cython
|
|
4390
|
+
deprecation_cython(38077, "The function is_FieldElement is deprecated; use 'isinstance(..., FieldElement)' instead.")
|
|
4391
|
+
return isinstance(x, FieldElement)
|
|
4392
|
+
|
|
4393
|
+
|
|
4394
|
+
cdef class FieldElement(CommutativeRingElement):
|
|
4395
|
+
cpdef _floordiv_(self, right):
|
|
4396
|
+
"""
|
|
4397
|
+
Return the quotient of ``self`` and ``other``. Since these are field
|
|
4398
|
+
elements, the floor division is exactly the same as usual division.
|
|
4399
|
+
|
|
4400
|
+
EXAMPLES::
|
|
4401
|
+
|
|
4402
|
+
sage: # needs sage.rings.number_field
|
|
4403
|
+
sage: x = polygen(ZZ, 'x')
|
|
4404
|
+
sage: K.<b> = NumberField(x^4 + x^2 + 2/3)
|
|
4405
|
+
sage: c = (1+b) // (1-b); c
|
|
4406
|
+
3/4*b^3 + 3/4*b^2 + 3/2*b + 1/2
|
|
4407
|
+
sage: (1+b) / (1-b) == c
|
|
4408
|
+
True
|
|
4409
|
+
sage: c * (1-b)
|
|
4410
|
+
b + 1
|
|
4411
|
+
"""
|
|
4412
|
+
return self._div_(right)
|
|
4413
|
+
|
|
4414
|
+
def is_unit(self):
|
|
4415
|
+
r"""
|
|
4416
|
+
Return ``True`` if ``self`` is a unit in its parent ring.
|
|
4417
|
+
|
|
4418
|
+
EXAMPLES::
|
|
4419
|
+
|
|
4420
|
+
sage: a = 2/3; a.is_unit()
|
|
4421
|
+
True
|
|
4422
|
+
|
|
4423
|
+
On the other hand, 2 is not a unit, since its parent is `\ZZ`.
|
|
4424
|
+
|
|
4425
|
+
::
|
|
4426
|
+
|
|
4427
|
+
sage: a = 2; a.is_unit()
|
|
4428
|
+
False
|
|
4429
|
+
sage: parent(a)
|
|
4430
|
+
Integer Ring
|
|
4431
|
+
|
|
4432
|
+
However, a is a unit when viewed as an element of QQ::
|
|
4433
|
+
|
|
4434
|
+
sage: a = QQ(2); a.is_unit()
|
|
4435
|
+
True
|
|
4436
|
+
"""
|
|
4437
|
+
return not not self
|
|
4438
|
+
|
|
4439
|
+
def _lcm(self, FieldElement other):
|
|
4440
|
+
"""
|
|
4441
|
+
Return the least common multiple of ``self`` and ``other``.
|
|
4442
|
+
"""
|
|
4443
|
+
if self.is_zero() and other.is_zero():
|
|
4444
|
+
return self
|
|
4445
|
+
else:
|
|
4446
|
+
return self._parent(1)
|
|
4447
|
+
|
|
4448
|
+
def quo_rem(self, right):
|
|
4449
|
+
r"""
|
|
4450
|
+
Return the quotient and remainder obtained by dividing ``self`` by
|
|
4451
|
+
``right``. Since this element lives in a field, the remainder is always
|
|
4452
|
+
zero and the quotient is ``self/right``.
|
|
4453
|
+
|
|
4454
|
+
TESTS:
|
|
4455
|
+
|
|
4456
|
+
Test if :issue:`8671` is fixed::
|
|
4457
|
+
|
|
4458
|
+
sage: # needs sage.libs.pari sage.libs.singular
|
|
4459
|
+
sage: R.<x,y> = QQ[]
|
|
4460
|
+
sage: S.<a,b> = R.quo(y^2 + 1)
|
|
4461
|
+
sage: S.is_field = lambda: False
|
|
4462
|
+
sage: F = Frac(S); u = F.one()
|
|
4463
|
+
sage: u.quo_rem(u)
|
|
4464
|
+
(1, 0)
|
|
4465
|
+
"""
|
|
4466
|
+
if not isinstance(right, FieldElement) or not (parent(right) is self._parent):
|
|
4467
|
+
right = self.parent()(right)
|
|
4468
|
+
return self/right, 0
|
|
4469
|
+
|
|
4470
|
+
def divides(self, FieldElement other):
|
|
4471
|
+
r"""
|
|
4472
|
+
Check whether ``self`` divides ``other``, for field elements.
|
|
4473
|
+
|
|
4474
|
+
Since this is a field, all values divide all other values,
|
|
4475
|
+
except that zero does not divide any nonzero values.
|
|
4476
|
+
|
|
4477
|
+
EXAMPLES::
|
|
4478
|
+
|
|
4479
|
+
sage: # needs fpylll sage.rings.number_field sage.symbolic
|
|
4480
|
+
sage: K.<rt3> = QQ[sqrt(3)]
|
|
4481
|
+
sage: K(0).divides(rt3)
|
|
4482
|
+
False
|
|
4483
|
+
sage: rt3.divides(K(17))
|
|
4484
|
+
True
|
|
4485
|
+
sage: K(0).divides(K(0))
|
|
4486
|
+
True
|
|
4487
|
+
sage: rt3.divides(K(0))
|
|
4488
|
+
True
|
|
4489
|
+
"""
|
|
4490
|
+
if not (other._parent is self._parent):
|
|
4491
|
+
other = self.parent()(other)
|
|
4492
|
+
return bool(self) or other.is_zero()
|
|
4493
|
+
|
|
4494
|
+
def canonical_associate(self):
|
|
4495
|
+
"""
|
|
4496
|
+
Return a canonical associate.
|
|
4497
|
+
|
|
4498
|
+
EXAMPLES::
|
|
4499
|
+
|
|
4500
|
+
sage: R.<x,y>=QQ[]; k=R.fraction_field()
|
|
4501
|
+
sage: (x/y).canonical_associate()
|
|
4502
|
+
(1, x/y)
|
|
4503
|
+
sage: (0).canonical_associate()
|
|
4504
|
+
(0, 1)
|
|
4505
|
+
"""
|
|
4506
|
+
P = self.parent()
|
|
4507
|
+
if self.is_zero():
|
|
4508
|
+
return (P.zero(), P.one())
|
|
4509
|
+
return (P.one(), self)
|
|
4510
|
+
|
|
4511
|
+
|
|
4512
|
+
def is_AlgebraElement(x):
|
|
4513
|
+
"""
|
|
4514
|
+
Return ``True`` if x is of type AlgebraElement.
|
|
4515
|
+
|
|
4516
|
+
TESTS::
|
|
4517
|
+
|
|
4518
|
+
sage: from sage.structure.element import is_AlgebraElement
|
|
4519
|
+
sage: is_AlgebraElement(1)
|
|
4520
|
+
doctest:warning...
|
|
4521
|
+
DeprecationWarning: The function is_AlgebraElement is deprecated; use 'isinstance(..., AlgebraElement)' instead.
|
|
4522
|
+
See https://github.com/sagemath/sage/issues/38077 for details.
|
|
4523
|
+
False
|
|
4524
|
+
sage: R.<x,y> = FreeAlgebra(QQ, 2) # needs sage.combinat sage.modules
|
|
4525
|
+
sage: is_AlgebraElement(x * y) # needs sage.combinat sage.modules
|
|
4526
|
+
True
|
|
4527
|
+
|
|
4528
|
+
"""
|
|
4529
|
+
from sage.misc.superseded import deprecation_cython
|
|
4530
|
+
deprecation_cython(38077, "The function is_AlgebraElement is deprecated; use 'isinstance(..., AlgebraElement)' instead.")
|
|
4531
|
+
return isinstance(x, AlgebraElement)
|
|
4532
|
+
|
|
4533
|
+
|
|
4534
|
+
cdef class AlgebraElement(RingElement):
|
|
4535
|
+
pass
|
|
4536
|
+
|
|
4537
|
+
|
|
4538
|
+
def is_CommutativeAlgebraElement(x):
|
|
4539
|
+
"""
|
|
4540
|
+
Return ``True`` if x is of type CommutativeAlgebraElement.
|
|
4541
|
+
"""
|
|
4542
|
+
from sage.misc.superseded import deprecation_cython
|
|
4543
|
+
deprecation_cython(38077, "The function is_CommutativeAlgebraElement is deprecated; use 'isinstance(..., CommutativeAlgebraElement)' instead.")
|
|
4544
|
+
return isinstance(x, CommutativeAlgebraElement)
|
|
4545
|
+
|
|
4546
|
+
|
|
4547
|
+
cdef class CommutativeAlgebraElement(CommutativeRingElement):
|
|
4548
|
+
pass
|
|
4549
|
+
|
|
4550
|
+
|
|
4551
|
+
##############################################
|
|
4552
|
+
|
|
4553
|
+
def is_InfinityElement(x):
|
|
4554
|
+
"""
|
|
4555
|
+
Return ``True`` if x is of type InfinityElement.
|
|
4556
|
+
|
|
4557
|
+
TESTS::
|
|
4558
|
+
|
|
4559
|
+
sage: from sage.structure.element import is_InfinityElement
|
|
4560
|
+
sage: is_InfinityElement(1)
|
|
4561
|
+
doctest:warning...
|
|
4562
|
+
DeprecationWarning: The function is_InfinityElement is deprecated; use 'isinstance(..., InfinityElement)' instead.
|
|
4563
|
+
See https://github.com/sagemath/sage/issues/38077 for details.
|
|
4564
|
+
False
|
|
4565
|
+
|
|
4566
|
+
sage: is_InfinityElement(oo)
|
|
4567
|
+
True
|
|
4568
|
+
"""
|
|
4569
|
+
from sage.misc.superseded import deprecation_cython
|
|
4570
|
+
deprecation_cython(38077, "The function is_InfinityElement is deprecated; use 'isinstance(..., InfinityElement)' instead.")
|
|
4571
|
+
return isinstance(x, InfinityElement)
|
|
4572
|
+
|
|
4573
|
+
|
|
4574
|
+
cdef class InfinityElement(RingElement):
|
|
4575
|
+
def __invert__(self):
|
|
4576
|
+
from sage.rings.integer_ring import ZZ
|
|
4577
|
+
return ZZ(0)
|
|
4578
|
+
|
|
4579
|
+
|
|
4580
|
+
###############################################################################
|
|
4581
|
+
#
|
|
4582
|
+
# Coercion of elements
|
|
4583
|
+
#
|
|
4584
|
+
###############################################################################
|
|
4585
|
+
|
|
4586
|
+
cpdef canonical_coercion(x, y):
|
|
4587
|
+
"""
|
|
4588
|
+
``canonical_coercion(x,y)`` is what is called before doing an
|
|
4589
|
+
arithmetic operation between ``x`` and ``y``. It returns a pair ``(z,w)``
|
|
4590
|
+
such that ``z`` is got from ``x`` and ``w`` from ``y`` via canonical coercion and
|
|
4591
|
+
the parents of ``z`` and ``w`` are identical.
|
|
4592
|
+
|
|
4593
|
+
EXAMPLES::
|
|
4594
|
+
|
|
4595
|
+
sage: A = Matrix([[0, 1], [1, 0]]) # needs sage.modules
|
|
4596
|
+
sage: canonical_coercion(A, 1) # needs sage.modules
|
|
4597
|
+
(
|
|
4598
|
+
[0 1] [1 0]
|
|
4599
|
+
[1 0], [0 1]
|
|
4600
|
+
)
|
|
4601
|
+
"""
|
|
4602
|
+
return coercion_model.canonical_coercion(x, y)
|
|
4603
|
+
|
|
4604
|
+
|
|
4605
|
+
cpdef bin_op(x, y, op):
|
|
4606
|
+
return coercion_model.bin_op(x, y, op)
|
|
4607
|
+
|
|
4608
|
+
|
|
4609
|
+
# Make coercion_model accessible as Python object
|
|
4610
|
+
globals()["coercion_model"] = coercion_model
|
|
4611
|
+
|
|
4612
|
+
|
|
4613
|
+
def get_coercion_model():
|
|
4614
|
+
"""
|
|
4615
|
+
Return the global coercion model.
|
|
4616
|
+
|
|
4617
|
+
EXAMPLES::
|
|
4618
|
+
|
|
4619
|
+
sage: import sage.structure.element as e
|
|
4620
|
+
sage: cm = e.get_coercion_model()
|
|
4621
|
+
sage: cm
|
|
4622
|
+
<sage.structure.coerce.CoercionModel object at ...>
|
|
4623
|
+
sage: cm is coercion_model
|
|
4624
|
+
True
|
|
4625
|
+
"""
|
|
4626
|
+
return coercion_model
|
|
4627
|
+
|
|
4628
|
+
|
|
4629
|
+
def coercion_traceback(dump=True):
|
|
4630
|
+
r"""
|
|
4631
|
+
This function is very helpful in debugging coercion errors. It prints
|
|
4632
|
+
the tracebacks of all the errors caught in the coercion detection. Note
|
|
4633
|
+
that failure is cached, so some errors may be omitted the second time
|
|
4634
|
+
around (as it remembers not to retry failed paths for speed reasons.
|
|
4635
|
+
|
|
4636
|
+
For performance and caching reasons, exception recording must be
|
|
4637
|
+
explicitly enabled before using this function.
|
|
4638
|
+
|
|
4639
|
+
EXAMPLES::
|
|
4640
|
+
|
|
4641
|
+
sage: cm = sage.structure.element.get_coercion_model()
|
|
4642
|
+
sage: cm.record_exceptions()
|
|
4643
|
+
sage: 1 + 1/5
|
|
4644
|
+
6/5
|
|
4645
|
+
sage: coercion_traceback() # Should be empty, as all went well.
|
|
4646
|
+
sage: 1/5 + GF(5).gen()
|
|
4647
|
+
Traceback (most recent call last):
|
|
4648
|
+
...
|
|
4649
|
+
TypeError: unsupported operand parent(s) for +:
|
|
4650
|
+
'Rational Field' and 'Finite Field of size 5'
|
|
4651
|
+
sage: coercion_traceback()
|
|
4652
|
+
Traceback (most recent call last):
|
|
4653
|
+
...
|
|
4654
|
+
TypeError: no common canonical parent for objects with parents:
|
|
4655
|
+
'Rational Field' and 'Finite Field of size 5'
|
|
4656
|
+
"""
|
|
4657
|
+
if dump:
|
|
4658
|
+
for traceback in coercion_model.exception_stack():
|
|
4659
|
+
print(traceback)
|
|
4660
|
+
else:
|
|
4661
|
+
return coercion_model.exception_stack()
|
|
4662
|
+
|
|
4663
|
+
|
|
4664
|
+
def coerce_binop(method):
|
|
4665
|
+
r"""
|
|
4666
|
+
Decorator for a binary operator method for applying coercion to the
|
|
4667
|
+
arguments before calling the method.
|
|
4668
|
+
|
|
4669
|
+
Consider a parent class in the category framework, `S`, whose element class
|
|
4670
|
+
expose a method `binop`. If `a` and `b` are elements of `S`, then
|
|
4671
|
+
`a.binop(b)` behaves as expected. If `a` and `b` are not elements of `S`,
|
|
4672
|
+
but rather have a common parent `T` whose element class also exposes
|
|
4673
|
+
`binop`, we would rather expect `a.binop(b)` to compute `aa.binop(bb)`,
|
|
4674
|
+
where `aa = T(a)` and `bb = T(b)`. This decorator ensures that behaviour
|
|
4675
|
+
without having to otherwise modify the implementation of `binop` on the
|
|
4676
|
+
element class of `A`.
|
|
4677
|
+
|
|
4678
|
+
Since coercion will be attempted on the arguments of the decorated method, a
|
|
4679
|
+
`TypeError` will be thrown if there is no common parent between the
|
|
4680
|
+
elements. An `AttributeError` or `NotImplementedError` or similar will be
|
|
4681
|
+
thrown if there is a common parent of the arguments, but its element class
|
|
4682
|
+
does not implement a method of the same name as the decorated method.
|
|
4683
|
+
|
|
4684
|
+
EXAMPLES:
|
|
4685
|
+
|
|
4686
|
+
Sparse polynomial rings uses ``@coerce_binop`` on ``gcd``::
|
|
4687
|
+
|
|
4688
|
+
sage: S.<x> = PolynomialRing(ZZ, sparse=True)
|
|
4689
|
+
sage: f = x^2
|
|
4690
|
+
sage: g = x
|
|
4691
|
+
sage: f.gcd(g) #indirect doctest
|
|
4692
|
+
x
|
|
4693
|
+
sage: T = PolynomialRing(QQ, name='x', sparse=True)
|
|
4694
|
+
sage: h = 1/2*T(x)
|
|
4695
|
+
sage: u = f.gcd(h); u #indirect doctest
|
|
4696
|
+
x
|
|
4697
|
+
sage: u.parent() == T
|
|
4698
|
+
True
|
|
4699
|
+
|
|
4700
|
+
Another real example::
|
|
4701
|
+
|
|
4702
|
+
sage: R1 = QQ['x,y']
|
|
4703
|
+
sage: R2 = QQ['x,y,z']
|
|
4704
|
+
sage: f = R1(1)
|
|
4705
|
+
sage: g = R1(2)
|
|
4706
|
+
sage: h = R2(1)
|
|
4707
|
+
sage: f.gcd(g)
|
|
4708
|
+
1
|
|
4709
|
+
sage: f.gcd(g, algorithm='modular')
|
|
4710
|
+
1
|
|
4711
|
+
sage: f.gcd(h)
|
|
4712
|
+
1
|
|
4713
|
+
sage: f.gcd(h, algorithm='modular')
|
|
4714
|
+
1
|
|
4715
|
+
sage: h.gcd(f)
|
|
4716
|
+
1
|
|
4717
|
+
sage: h.gcd(f, 'modular')
|
|
4718
|
+
1
|
|
4719
|
+
|
|
4720
|
+
We demonstrate a small class using ``@coerce_binop`` on a method::
|
|
4721
|
+
|
|
4722
|
+
sage: from sage.structure.element import coerce_binop
|
|
4723
|
+
sage: class MyRational(Rational):
|
|
4724
|
+
....: def __init__(self, value):
|
|
4725
|
+
....: self.v = value
|
|
4726
|
+
....: @coerce_binop
|
|
4727
|
+
....: def test_add(self, other, keyword='z'):
|
|
4728
|
+
....: return (self.v, other, keyword)
|
|
4729
|
+
|
|
4730
|
+
Calls func directly if the two arguments have the same parent::
|
|
4731
|
+
|
|
4732
|
+
sage: x = MyRational(1)
|
|
4733
|
+
sage: x.test_add(1/2)
|
|
4734
|
+
(1, 1/2, 'z')
|
|
4735
|
+
sage: x.test_add(1/2, keyword=3)
|
|
4736
|
+
(1, 1/2, 3)
|
|
4737
|
+
|
|
4738
|
+
Passes through coercion and does a method lookup if the left operand is not
|
|
4739
|
+
the same. If the common parent's element class does not have a method of the
|
|
4740
|
+
same name, an exception is raised::
|
|
4741
|
+
|
|
4742
|
+
sage: x.test_add(2)
|
|
4743
|
+
(1, 2, 'z')
|
|
4744
|
+
sage: x.test_add(2, keyword=3)
|
|
4745
|
+
(1, 2, 3)
|
|
4746
|
+
sage: x.test_add(CC(2))
|
|
4747
|
+
Traceback (most recent call last):
|
|
4748
|
+
...
|
|
4749
|
+
AttributeError: 'sage.rings.complex_mpfr.ComplexNumber' object has no attribute 'test_add'...
|
|
4750
|
+
|
|
4751
|
+
TESTS:
|
|
4752
|
+
|
|
4753
|
+
Test that additional arguments given to the method do not override
|
|
4754
|
+
the ``self`` argument, see :issue:`21322`::
|
|
4755
|
+
|
|
4756
|
+
sage: f.gcd(g, 1)
|
|
4757
|
+
Traceback (most recent call last):
|
|
4758
|
+
...
|
|
4759
|
+
TypeError: algorithm 1 not supported
|
|
4760
|
+
"""
|
|
4761
|
+
@sage_wraps(method)
|
|
4762
|
+
@cython.binding(True)
|
|
4763
|
+
def new_method(self, other, *args, **kwargs):
|
|
4764
|
+
if have_same_parent(self, other):
|
|
4765
|
+
return method(self, other, *args, **kwargs)
|
|
4766
|
+
else:
|
|
4767
|
+
a, b = coercion_model.canonical_coercion(self, other)
|
|
4768
|
+
if a is self:
|
|
4769
|
+
return method(a, b, *args, **kwargs)
|
|
4770
|
+
else:
|
|
4771
|
+
return getattr(a, method.__name__)(b, *args, **kwargs)
|
|
4772
|
+
return new_method
|