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,988 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-objects
|
|
2
|
+
"""
|
|
3
|
+
Coerce actions
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
#*****************************************************************************
|
|
7
|
+
# Copyright (C) 2007 Robert Bradshaw <robertwb@math.washington.edu>
|
|
8
|
+
#
|
|
9
|
+
# This program is free software: you can redistribute it and/or modify
|
|
10
|
+
# it under the terms of the GNU General Public License as published by
|
|
11
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
12
|
+
# (at your option) any later version.
|
|
13
|
+
# http://www.gnu.org/licenses/
|
|
14
|
+
#*****************************************************************************
|
|
15
|
+
|
|
16
|
+
import operator
|
|
17
|
+
|
|
18
|
+
from cpython.long cimport *
|
|
19
|
+
from cpython.number cimport *
|
|
20
|
+
from cysignals.signals cimport sig_check
|
|
21
|
+
|
|
22
|
+
from sage.structure.coerce cimport coercion_model
|
|
23
|
+
from sage.structure.element cimport parent, Element, ModuleElement
|
|
24
|
+
from sage.structure.parent cimport Parent
|
|
25
|
+
from sage.structure.coerce_exceptions import CoercionException
|
|
26
|
+
from sage.categories.action cimport InverseAction, PrecomposedAction
|
|
27
|
+
from sage.arith.long cimport integer_check_long
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
cdef _record_exception():
|
|
31
|
+
coercion_model._record_exception()
|
|
32
|
+
|
|
33
|
+
cdef inline an_element(R):
|
|
34
|
+
if isinstance(R, Parent):
|
|
35
|
+
return R.an_element()
|
|
36
|
+
else:
|
|
37
|
+
for x in ([(1, 2)], "abc", 10.5, 10):
|
|
38
|
+
try:
|
|
39
|
+
return R(x)
|
|
40
|
+
except Exception:
|
|
41
|
+
pass
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# In the code below, I take the convention that g is acting on a.
|
|
45
|
+
|
|
46
|
+
cdef class GenericAction(Action):
|
|
47
|
+
|
|
48
|
+
cdef _codomain
|
|
49
|
+
|
|
50
|
+
def __init__(self, Parent G, S, is_left, bint check=True):
|
|
51
|
+
"""
|
|
52
|
+
TESTS:
|
|
53
|
+
|
|
54
|
+
Note that coerce actions should only be used inside of the coercion
|
|
55
|
+
model. For this test, we need to strongly reference the domains,
|
|
56
|
+
for otherwise they could be garbage collected, giving rise to
|
|
57
|
+
random errors (see :issue:`18157`). ::
|
|
58
|
+
|
|
59
|
+
sage: from sage.structure.coerce_actions import ActedUponAction, GenericAction
|
|
60
|
+
sage: M = MatrixSpace(ZZ, 2) # needs sage.modules
|
|
61
|
+
sage: ActedUponAction(M, Cusps, True) # needs sage.modular sage.modules
|
|
62
|
+
Left action
|
|
63
|
+
by Full MatrixSpace of 2 by 2 dense matrices over Integer Ring
|
|
64
|
+
on Set P^1(QQ) of all cusps
|
|
65
|
+
|
|
66
|
+
sage: Z6 = Zmod(6)
|
|
67
|
+
sage: GenericAction(QQ, Z6, True)
|
|
68
|
+
Traceback (most recent call last):
|
|
69
|
+
...
|
|
70
|
+
NotImplementedError: action for <class 'sage.structure.coerce_actions.GenericAction'> not implemented
|
|
71
|
+
|
|
72
|
+
This will break if we tried to use it::
|
|
73
|
+
|
|
74
|
+
sage: GenericAction(QQ, Z6, True, check=False)
|
|
75
|
+
Left action by Rational Field on Ring of integers modulo 6
|
|
76
|
+
"""
|
|
77
|
+
Action.__init__(self, G, S, is_left, operator.mul)
|
|
78
|
+
if check:
|
|
79
|
+
res = self.act(G.an_element(), S.an_element())
|
|
80
|
+
if res is None:
|
|
81
|
+
raise CoercionException
|
|
82
|
+
_codomain = parent(res)
|
|
83
|
+
|
|
84
|
+
def codomain(self):
|
|
85
|
+
"""
|
|
86
|
+
Return the "codomain" of this action, i.e. the Parent in which the
|
|
87
|
+
result elements live. Typically, this should be the same as the
|
|
88
|
+
acted upon set.
|
|
89
|
+
|
|
90
|
+
EXAMPLES:
|
|
91
|
+
|
|
92
|
+
Note that coerce actions should only be used inside of the coercion
|
|
93
|
+
model. For this test, we need to strongly reference the domains, for
|
|
94
|
+
otherwise they could be garbage collected, giving rise to random
|
|
95
|
+
errors (see :issue:`18157`). ::
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
sage: M = MatrixSpace(ZZ, 2) # needs sage.modules
|
|
99
|
+
sage: A = sage.structure.coerce_actions.ActedUponAction(M, Cusps, True) # needs sage.modular sage.modules
|
|
100
|
+
sage: A.codomain() # needs sage.modular sage.modules
|
|
101
|
+
Set P^1(QQ) of all cusps
|
|
102
|
+
|
|
103
|
+
sage: # needs sage.groups
|
|
104
|
+
sage: S3 = SymmetricGroup(3)
|
|
105
|
+
sage: QQxyz = QQ['x,y,z']
|
|
106
|
+
sage: A = sage.structure.coerce_actions.ActOnAction(S3, QQxyz, False)
|
|
107
|
+
sage: A.codomain()
|
|
108
|
+
Multivariate Polynomial Ring in x, y, z over Rational Field
|
|
109
|
+
"""
|
|
110
|
+
if self._codomain is None:
|
|
111
|
+
self._codomain = parent(self.act(an_element(self.G),
|
|
112
|
+
an_element(self.underlying_set())))
|
|
113
|
+
return self._codomain
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
cdef class ActOnAction(GenericAction):
|
|
117
|
+
"""
|
|
118
|
+
Class for actions defined via the _act_on_ method.
|
|
119
|
+
"""
|
|
120
|
+
cpdef _act_(self, g, x):
|
|
121
|
+
"""
|
|
122
|
+
TESTS::
|
|
123
|
+
|
|
124
|
+
sage: # needs sage.groups
|
|
125
|
+
sage: G = SymmetricGroup(3)
|
|
126
|
+
sage: R.<x,y,z> = QQ[]
|
|
127
|
+
sage: A = sage.structure.coerce_actions.ActOnAction(G, R, False)
|
|
128
|
+
sage: A(x^2 + y - z, G((1,2)))
|
|
129
|
+
y^2 + x - z
|
|
130
|
+
sage: A(x + 2*y + 3*z, G((1,3,2)))
|
|
131
|
+
2*x + 3*y + z
|
|
132
|
+
sage: type(A)
|
|
133
|
+
<... 'sage.structure.coerce_actions.ActOnAction'>
|
|
134
|
+
"""
|
|
135
|
+
return (<Element>g)._act_on_(x, self._is_left)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
cdef class ActedUponAction(GenericAction):
|
|
139
|
+
"""
|
|
140
|
+
Class for actions defined via the _acted_upon_ method.
|
|
141
|
+
"""
|
|
142
|
+
cpdef _act_(self, g, x):
|
|
143
|
+
"""
|
|
144
|
+
TESTS::
|
|
145
|
+
|
|
146
|
+
sage: # needs sage.modular sage.modules
|
|
147
|
+
sage: M = MatrixSpace(ZZ, 2)
|
|
148
|
+
sage: A = sage.structure.coerce_actions.ActedUponAction(M, Cusps, True)
|
|
149
|
+
sage: A.act(matrix(ZZ, 2, [1,0,2,-1]), Cusp(1,2))
|
|
150
|
+
Infinity
|
|
151
|
+
sage: A(matrix(ZZ, 2, [1,0,2,-1]), Cusp(1,2))
|
|
152
|
+
Infinity
|
|
153
|
+
sage: type(A)
|
|
154
|
+
<... 'sage.structure.coerce_actions.ActedUponAction'>
|
|
155
|
+
"""
|
|
156
|
+
return (<Element>x)._acted_upon_(g, not self._is_left)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def detect_element_action(Parent X, Y, bint X_on_left, X_el=None, Y_el=None):
|
|
160
|
+
r"""
|
|
161
|
+
Return an action of X on Y as defined by elements of X, if any.
|
|
162
|
+
|
|
163
|
+
EXAMPLES:
|
|
164
|
+
|
|
165
|
+
Note that coerce actions should only be used inside of the coercion
|
|
166
|
+
model. For this test, we need to strongly reference the domains,
|
|
167
|
+
for otherwise they could be garbage collected, giving rise to
|
|
168
|
+
random errors (see :issue:`18157`). ::
|
|
169
|
+
|
|
170
|
+
sage: from sage.structure.coerce_actions import detect_element_action
|
|
171
|
+
sage: ZZx = ZZ['x']
|
|
172
|
+
sage: M = MatrixSpace(ZZ, 2) # needs sage.modules
|
|
173
|
+
sage: detect_element_action(ZZx, ZZ, False)
|
|
174
|
+
Left scalar multiplication by Integer Ring
|
|
175
|
+
on Univariate Polynomial Ring in x over Integer Ring
|
|
176
|
+
sage: detect_element_action(ZZx, QQ, True)
|
|
177
|
+
Right scalar multiplication by Rational Field
|
|
178
|
+
on Univariate Polynomial Ring in x over Integer Ring
|
|
179
|
+
sage: detect_element_action(Cusps, M, False) # needs sage.modular sage.modules
|
|
180
|
+
Left action by Full MatrixSpace of 2 by 2 dense matrices over Integer Ring
|
|
181
|
+
on Set P^1(QQ) of all cusps
|
|
182
|
+
sage: detect_element_action(Cusps, M, True), # needs sage.modular sage.modules
|
|
183
|
+
(None,)
|
|
184
|
+
sage: detect_element_action(ZZ, QQ, True),
|
|
185
|
+
(None,)
|
|
186
|
+
|
|
187
|
+
TESTS:
|
|
188
|
+
|
|
189
|
+
This test checks that the issue in :issue:`7718` has been fixed::
|
|
190
|
+
|
|
191
|
+
sage: class MyParent(Parent):
|
|
192
|
+
....: def an_element(self):
|
|
193
|
+
....: pass
|
|
194
|
+
....:
|
|
195
|
+
sage: A = MyParent()
|
|
196
|
+
sage: detect_element_action(A, ZZ, True)
|
|
197
|
+
Traceback (most recent call last):
|
|
198
|
+
...
|
|
199
|
+
RuntimeError: an_element() for <__main__.MyParent object at ...> returned None
|
|
200
|
+
"""
|
|
201
|
+
cdef Element x
|
|
202
|
+
|
|
203
|
+
# sample elements x and y
|
|
204
|
+
if X_el is None or (parent(X_el) is not X):
|
|
205
|
+
x = an_element(X)
|
|
206
|
+
else:
|
|
207
|
+
x = X_el
|
|
208
|
+
if x is None:
|
|
209
|
+
raise RuntimeError("an_element() for %s returned None" % X)
|
|
210
|
+
if Y_el is None or (parent(Y_el) is not Y):
|
|
211
|
+
y = an_element(Y)
|
|
212
|
+
else:
|
|
213
|
+
y = Y_el
|
|
214
|
+
if y is None:
|
|
215
|
+
if isinstance(Y, Parent):
|
|
216
|
+
raise RuntimeError("an_element() for %s returned None" % Y)
|
|
217
|
+
else:
|
|
218
|
+
return # don't know how to make elements of this type...
|
|
219
|
+
|
|
220
|
+
# element x defining _lmul_ or _rmul_
|
|
221
|
+
if isinstance(x, ModuleElement) and isinstance(y, Element):
|
|
222
|
+
try:
|
|
223
|
+
return (RightModuleAction if X_on_left else LeftModuleAction)(Y, X, y, x)
|
|
224
|
+
except CoercionException as msg:
|
|
225
|
+
_record_exception()
|
|
226
|
+
|
|
227
|
+
# element x defining _act_on_
|
|
228
|
+
try:
|
|
229
|
+
if x._act_on_(y, X_on_left) is not None:
|
|
230
|
+
return ActOnAction(X, Y, X_on_left, False)
|
|
231
|
+
except CoercionException:
|
|
232
|
+
_record_exception()
|
|
233
|
+
|
|
234
|
+
# element x defining _acted_upon_
|
|
235
|
+
if isinstance(Y, Parent):
|
|
236
|
+
try:
|
|
237
|
+
if x._acted_upon_(y, X_on_left) is not None:
|
|
238
|
+
return ActedUponAction(Y, X, not X_on_left, False)
|
|
239
|
+
except CoercionException:
|
|
240
|
+
_record_exception()
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
cdef class ModuleAction(Action):
|
|
244
|
+
"""
|
|
245
|
+
Module action.
|
|
246
|
+
|
|
247
|
+
.. SEEALSO::
|
|
248
|
+
|
|
249
|
+
This is an abstract class, one must actually instantiate a
|
|
250
|
+
:class:`LeftModuleAction` or a :class:`RightModuleAction`.
|
|
251
|
+
|
|
252
|
+
INPUT:
|
|
253
|
+
|
|
254
|
+
- ``G`` -- the actor, an instance of :class:`~sage.structure.parent.Parent`
|
|
255
|
+
- ``S`` -- the object that is acted upon
|
|
256
|
+
- ``g`` -- (optional) an element of ``G``
|
|
257
|
+
- ``a`` -- (optional) an element of ``S``
|
|
258
|
+
- ``check`` -- if ``True`` (default), then there will be no consistency tests
|
|
259
|
+
performed on sample elements
|
|
260
|
+
|
|
261
|
+
NOTE:
|
|
262
|
+
|
|
263
|
+
By default, the sample elements of ``S`` and ``G`` are obtained from
|
|
264
|
+
:meth:`~sage.structure.parent.Parent.an_element`, which relies on the
|
|
265
|
+
implementation of an ``_an_element_()`` method. This is not always
|
|
266
|
+
available. But usually, the action is only needed when one already
|
|
267
|
+
*has* two elements. Hence, by :issue:`14249`, the coercion model will
|
|
268
|
+
pass these two elements to the :class:`ModuleAction` constructor.
|
|
269
|
+
|
|
270
|
+
The actual action is implemented by the ``_rmul_`` or ``_lmul_``
|
|
271
|
+
function on its elements. We must, however, be very particular about
|
|
272
|
+
what we feed into these functions, because they operate under the
|
|
273
|
+
assumption that the inputs lie exactly in the base ring and may
|
|
274
|
+
segfault otherwise. Thus we handle all possible base extensions
|
|
275
|
+
manually here.
|
|
276
|
+
"""
|
|
277
|
+
def __init__(self, G, S, g=None, a=None, check=True):
|
|
278
|
+
"""
|
|
279
|
+
This creates an action of an element of a module by an element of its
|
|
280
|
+
base ring. The simplest example to keep in mind is R acting on the
|
|
281
|
+
polynomial ring R[x].
|
|
282
|
+
|
|
283
|
+
EXAMPLES:
|
|
284
|
+
|
|
285
|
+
Note that coerce actions should only be used inside of the coercion
|
|
286
|
+
model. For this test, we need to strongly reference the domains,
|
|
287
|
+
for otherwise they could be garbage collected, giving rise to
|
|
288
|
+
random errors (see :issue:`18157`). ::
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
sage: from sage.structure.coerce_actions import LeftModuleAction
|
|
292
|
+
sage: ZZx = ZZ['x']
|
|
293
|
+
sage: QQx = QQ['x']
|
|
294
|
+
sage: QQy = QQ['y']
|
|
295
|
+
sage: ZZxy = ZZ['x']['y']
|
|
296
|
+
sage: LeftModuleAction(ZZ, ZZx)
|
|
297
|
+
Left scalar multiplication by Integer Ring on Univariate Polynomial Ring in x over Integer Ring
|
|
298
|
+
sage: LeftModuleAction(ZZ, QQx)
|
|
299
|
+
Left scalar multiplication by Integer Ring on Univariate Polynomial Ring in x over Rational Field
|
|
300
|
+
sage: LeftModuleAction(QQ, ZZx)
|
|
301
|
+
Left scalar multiplication by Rational Field on Univariate Polynomial Ring in x over Integer Ring
|
|
302
|
+
sage: LeftModuleAction(QQ, ZZxy)
|
|
303
|
+
Left scalar multiplication by Rational Field
|
|
304
|
+
on Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Integer Ring
|
|
305
|
+
|
|
306
|
+
The following tests against a problem that was relevant during work on
|
|
307
|
+
:issue:`9944`::
|
|
308
|
+
|
|
309
|
+
sage: R.<x> = PolynomialRing(ZZ)
|
|
310
|
+
sage: S.<x> = PolynomialRing(ZZ, sparse=True)
|
|
311
|
+
sage: 1/R.0
|
|
312
|
+
1/x
|
|
313
|
+
sage: 1/S.0
|
|
314
|
+
1/x
|
|
315
|
+
|
|
316
|
+
If there is a coercion from ``G`` to ``S``, we do not create
|
|
317
|
+
the module action of ``G`` on the pushout of ``G`` and ``S``::
|
|
318
|
+
|
|
319
|
+
sage: # needs sage.modules
|
|
320
|
+
sage: G = PolynomialRing(QQ, "x")
|
|
321
|
+
sage: S = PolynomialRing(MatrixSpace(QQ, 2), "x")
|
|
322
|
+
sage: G.gen() * S.gen()
|
|
323
|
+
[1 0]
|
|
324
|
+
[0 1]*x^2
|
|
325
|
+
|
|
326
|
+
Contrast the previous example with the following, where we
|
|
327
|
+
have no coercion from ``G`` to ``S``::
|
|
328
|
+
|
|
329
|
+
sage: # needs sage.modules
|
|
330
|
+
sage: S = PolynomialRing(MatrixSpace(QQ, 2), "y")
|
|
331
|
+
sage: G.gen() * S.gen()
|
|
332
|
+
[x 0]
|
|
333
|
+
[0 x]*y
|
|
334
|
+
"""
|
|
335
|
+
Action.__init__(self, G, S, not isinstance(self, RightModuleAction), operator.mul)
|
|
336
|
+
if not isinstance(G, Parent):
|
|
337
|
+
# only let Parents act
|
|
338
|
+
raise TypeError("Actor must be a parent.")
|
|
339
|
+
base = S.base()
|
|
340
|
+
if base is S or base is None:
|
|
341
|
+
# The right thing to do is a normal multiplication
|
|
342
|
+
raise CoercionException("Best viewed as standard multiplication")
|
|
343
|
+
# Objects are implemented with the assumption that
|
|
344
|
+
# _lmul_/_rmul_ are given an element of the base ring
|
|
345
|
+
if G is not base:
|
|
346
|
+
# first we try the easy case of coercing G to the base ring of S
|
|
347
|
+
self.connecting = base._internal_coerce_map_from(G)
|
|
348
|
+
if self.connecting is None:
|
|
349
|
+
if S._internal_coerce_map_from(G) is not None:
|
|
350
|
+
raise CoercionException("Best viewed as standard coercion multiplication.")
|
|
351
|
+
# otherwise, we try and find a base extension
|
|
352
|
+
from sage.categories.pushout import pushout
|
|
353
|
+
# this may raise a type error, which we propagate
|
|
354
|
+
self.extended_base = pushout(G, S)
|
|
355
|
+
# make sure the pushout actually gave a correct base extension of S
|
|
356
|
+
if self.extended_base.base() != pushout(G, base):
|
|
357
|
+
raise CoercionException("Actor must be coercible into base.")
|
|
358
|
+
else:
|
|
359
|
+
self.connecting = self.extended_base.base()._internal_coerce_map_from(G)
|
|
360
|
+
if self.connecting is None:
|
|
361
|
+
# this may happen if G is, say, int rather than a parent
|
|
362
|
+
# TODO: let python types be valid actions
|
|
363
|
+
raise CoercionException("Missing connecting morphism")
|
|
364
|
+
|
|
365
|
+
# Don't waste time if our connecting morphisms happen to be the identity.
|
|
366
|
+
if self.connecting is not None and self.connecting.codomain() is G:
|
|
367
|
+
self.connecting = None
|
|
368
|
+
|
|
369
|
+
if self.extended_base is not None and self.extended_base is S:
|
|
370
|
+
self.extended_base = None
|
|
371
|
+
|
|
372
|
+
# At this point, we can assert it is safe to call _Xmul_
|
|
373
|
+
the_ring = G if self.connecting is None else self.connecting.codomain()
|
|
374
|
+
the_set = S if self.extended_base is None else self.extended_base
|
|
375
|
+
assert the_ring is the_set.base(), "BUG in coercion model\n Apparently there are two versions of\n %s\n in the cache." % the_ring
|
|
376
|
+
|
|
377
|
+
if not check:
|
|
378
|
+
return
|
|
379
|
+
if g is None:
|
|
380
|
+
g = G.an_element()
|
|
381
|
+
if parent(g) is not G:
|
|
382
|
+
raise CoercionException("The parent of %s is not %s but %s" % (g, G, parent(g)))
|
|
383
|
+
if a is None:
|
|
384
|
+
a = S.an_element()
|
|
385
|
+
if parent(a) is not S:
|
|
386
|
+
raise CoercionException("The parent of %s is not %s but %s" % (a, S, parent(a)))
|
|
387
|
+
if not isinstance(g, Element) or not isinstance(a, ModuleElement):
|
|
388
|
+
raise CoercionException("not an Element acting on a ModuleElement")
|
|
389
|
+
res = self.act(g, a)
|
|
390
|
+
if parent(res) is not the_set:
|
|
391
|
+
# In particular we will raise an error if res is None
|
|
392
|
+
raise CoercionException("Result is None or has wrong parent.")
|
|
393
|
+
|
|
394
|
+
def __reduce__(self):
|
|
395
|
+
"""
|
|
396
|
+
Used in pickling.
|
|
397
|
+
|
|
398
|
+
TESTS:
|
|
399
|
+
|
|
400
|
+
Check that this action can be pickled (:issue:`29031`)::
|
|
401
|
+
|
|
402
|
+
sage: A = ZZ['x'].get_action(QQ, self_on_left=False, op=operator.mul)
|
|
403
|
+
sage: loads(dumps(A)) is not None
|
|
404
|
+
True
|
|
405
|
+
"""
|
|
406
|
+
return (type(self), (self.G, self.underlying_set()))
|
|
407
|
+
|
|
408
|
+
def _repr_name_(self):
|
|
409
|
+
"""
|
|
410
|
+
The default name of this action type, which is has a sane default.
|
|
411
|
+
|
|
412
|
+
EXAMPLES:
|
|
413
|
+
|
|
414
|
+
Note that coerce actions should only be used inside of the
|
|
415
|
+
coercion model. For this test, we need to strongly reference the
|
|
416
|
+
domains, for otherwise they could be garbage collected, giving rise to
|
|
417
|
+
random errors (see :issue:`18157`). ::
|
|
418
|
+
|
|
419
|
+
sage: from sage.structure.coerce_actions import LeftModuleAction, RightModuleAction
|
|
420
|
+
sage: ZZx = ZZ['x']
|
|
421
|
+
sage: A = LeftModuleAction(ZZ, ZZx); A
|
|
422
|
+
Left scalar multiplication by Integer Ring
|
|
423
|
+
on Univariate Polynomial Ring in x over Integer Ring
|
|
424
|
+
sage: A._repr_name_()
|
|
425
|
+
'scalar multiplication'
|
|
426
|
+
|
|
427
|
+
sage: GF5 = GF(5)
|
|
428
|
+
sage: GF5t = GF5[['t']]
|
|
429
|
+
sage: RightModuleAction(GF5, GF5t)
|
|
430
|
+
Right scalar multiplication by Finite Field of size 5
|
|
431
|
+
on Power Series Ring in t over Finite Field of size 5
|
|
432
|
+
"""
|
|
433
|
+
return "scalar multiplication"
|
|
434
|
+
|
|
435
|
+
def codomain(self):
|
|
436
|
+
"""
|
|
437
|
+
The codomain of self, which may or may not be equal to the domain.
|
|
438
|
+
|
|
439
|
+
EXAMPLES:
|
|
440
|
+
|
|
441
|
+
Note that coerce actions should only be used inside of the coercion
|
|
442
|
+
model. For this test, we need to strongly reference the domains,
|
|
443
|
+
for otherwise they could be garbage collected, giving rise to
|
|
444
|
+
random errors (see :issue:`18157`). ::
|
|
445
|
+
|
|
446
|
+
sage: from sage.structure.coerce_actions import LeftModuleAction
|
|
447
|
+
sage: ZZxyz = ZZ['x,y,z']
|
|
448
|
+
sage: A = LeftModuleAction(QQ, ZZxyz)
|
|
449
|
+
sage: A.codomain()
|
|
450
|
+
Multivariate Polynomial Ring in x, y, z over Rational Field
|
|
451
|
+
"""
|
|
452
|
+
if self.extended_base is not None:
|
|
453
|
+
return self.extended_base
|
|
454
|
+
return self.underlying_set()
|
|
455
|
+
|
|
456
|
+
def domain(self):
|
|
457
|
+
"""
|
|
458
|
+
The domain of self, which is the module that is being acted on.
|
|
459
|
+
|
|
460
|
+
EXAMPLES:
|
|
461
|
+
|
|
462
|
+
Note that coerce actions should only be used inside of the coercion
|
|
463
|
+
model. For this test, we need to strongly reference the domains,
|
|
464
|
+
for otherwise they could be garbage collected, giving rise to
|
|
465
|
+
random errors (see :issue:`18157`). ::
|
|
466
|
+
|
|
467
|
+
sage: from sage.structure.coerce_actions import LeftModuleAction
|
|
468
|
+
sage: ZZxyz = ZZ['x,y,z']
|
|
469
|
+
sage: A = LeftModuleAction(QQ, ZZxyz)
|
|
470
|
+
sage: A.domain()
|
|
471
|
+
Multivariate Polynomial Ring in x, y, z over Integer Ring
|
|
472
|
+
"""
|
|
473
|
+
return self.underlying_set()
|
|
474
|
+
|
|
475
|
+
def __invert__(self):
|
|
476
|
+
"""
|
|
477
|
+
EXAMPLES:
|
|
478
|
+
|
|
479
|
+
Note that coerce actions should only be used inside of the coercion
|
|
480
|
+
model. For this test, we need to strongly reference the domains, for
|
|
481
|
+
otherwise they could be garbage collected, giving rise to random
|
|
482
|
+
errors (see :issue:`18157`). ::
|
|
483
|
+
|
|
484
|
+
sage: from sage.structure.coerce_actions import RightModuleAction
|
|
485
|
+
|
|
486
|
+
sage: ZZx = ZZ['x']
|
|
487
|
+
sage: x = ZZx.gen()
|
|
488
|
+
sage: QQx = QQ['x']
|
|
489
|
+
sage: A = ~RightModuleAction(QQ, QQx); A
|
|
490
|
+
Right inverse action by Rational Field on Univariate Polynomial Ring in x over Rational Field
|
|
491
|
+
sage: A(x, 2)
|
|
492
|
+
1/2*x
|
|
493
|
+
|
|
494
|
+
sage: A = ~RightModuleAction(QQ, ZZx); A
|
|
495
|
+
Right inverse action by Rational Field on Univariate Polynomial Ring in x over Integer Ring
|
|
496
|
+
sage: A.codomain()
|
|
497
|
+
Univariate Polynomial Ring in x over Rational Field
|
|
498
|
+
sage: A(x, 2)
|
|
499
|
+
1/2*x
|
|
500
|
+
|
|
501
|
+
sage: A = ~RightModuleAction(ZZ, ZZx); A
|
|
502
|
+
Right inverse action by Rational Field on Univariate Polynomial Ring in x over Integer Ring
|
|
503
|
+
with precomposition on right by Natural morphism:
|
|
504
|
+
From: Integer Ring
|
|
505
|
+
To: Rational Field
|
|
506
|
+
sage: A.codomain()
|
|
507
|
+
Univariate Polynomial Ring in x over Rational Field
|
|
508
|
+
sage: A(x, 2)
|
|
509
|
+
1/2*x
|
|
510
|
+
|
|
511
|
+
sage: GF5x = GF(5)['x']
|
|
512
|
+
sage: A = ~RightModuleAction(ZZ, GF5x); A
|
|
513
|
+
Right inverse action by Finite Field of size 5
|
|
514
|
+
on Univariate Polynomial Ring in x over Finite Field of size 5
|
|
515
|
+
with precomposition on right by Natural morphism:
|
|
516
|
+
From: Integer Ring
|
|
517
|
+
To: Finite Field of size 5
|
|
518
|
+
sage: A(x, 2)
|
|
519
|
+
3*x
|
|
520
|
+
|
|
521
|
+
sage: GF5xy = GF5x['y']
|
|
522
|
+
sage: A = ~RightModuleAction(ZZ, GF5xy); A
|
|
523
|
+
Right inverse action by Finite Field of size 5
|
|
524
|
+
on Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Finite Field of size 5
|
|
525
|
+
with precomposition on right by Natural morphism:
|
|
526
|
+
From: Integer Ring
|
|
527
|
+
To: Finite Field of size 5
|
|
528
|
+
|
|
529
|
+
sage: ZZy = ZZ['y']
|
|
530
|
+
sage: ZZxyzw = ZZx['y']['z']['w']
|
|
531
|
+
sage: A = ~RightModuleAction(ZZy, ZZxyzw); A
|
|
532
|
+
Right inverse action by Fraction Field of Univariate Polynomial Ring in y
|
|
533
|
+
over Univariate Polynomial Ring in x
|
|
534
|
+
over Integer Ring
|
|
535
|
+
on Univariate Polynomial Ring in w
|
|
536
|
+
over Univariate Polynomial Ring in z
|
|
537
|
+
over Univariate Polynomial Ring in y
|
|
538
|
+
over Univariate Polynomial Ring in x
|
|
539
|
+
over Integer Ring
|
|
540
|
+
with precomposition on right by Conversion via FractionFieldElement map:
|
|
541
|
+
From: Univariate Polynomial Ring in y over Integer Ring
|
|
542
|
+
To: Fraction Field of Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Integer Ring
|
|
543
|
+
|
|
544
|
+
TESTS:
|
|
545
|
+
|
|
546
|
+
See :issue:`19521`::
|
|
547
|
+
|
|
548
|
+
sage: # needs sage.symbolic
|
|
549
|
+
sage: Q.<y> = SR.subring(no_variables=True)[[]]
|
|
550
|
+
sage: (y / 1).parent()
|
|
551
|
+
Power Series Ring in y over Symbolic Constants Subring
|
|
552
|
+
sage: R.<x> = SR.subring(no_variables=True)[]
|
|
553
|
+
sage: cm = sage.structure.element.get_coercion_model()
|
|
554
|
+
sage: cm.explain(x, 1, operator.truediv)
|
|
555
|
+
Action discovered.
|
|
556
|
+
Right inverse action by Symbolic Constants Subring
|
|
557
|
+
on Univariate Polynomial Ring in x over Symbolic Constants Subring
|
|
558
|
+
with precomposition on right by Conversion via _symbolic_ method map:
|
|
559
|
+
From: Integer Ring
|
|
560
|
+
To: Symbolic Constants Subring
|
|
561
|
+
Result lives in Univariate Polynomial Ring in x over Symbolic Constants Subring
|
|
562
|
+
Univariate Polynomial Ring in x over Symbolic Constants Subring
|
|
563
|
+
"""
|
|
564
|
+
K = self.G._pseudo_fraction_field()
|
|
565
|
+
if K is self.G:
|
|
566
|
+
return InverseAction(self)
|
|
567
|
+
else:
|
|
568
|
+
# Try to find a suitable ring between G and R in which to compute
|
|
569
|
+
# the inverse.
|
|
570
|
+
from sage.categories.pushout import construction_tower, pushout
|
|
571
|
+
R = self.G if self.connecting is None else self.connecting.codomain()
|
|
572
|
+
K = pushout(self.G._pseudo_fraction_field(), R)
|
|
573
|
+
if K is None:
|
|
574
|
+
K = R._pseudo_fraction_field()
|
|
575
|
+
|
|
576
|
+
# Suppose we have parents of a construction tower
|
|
577
|
+
# A -> B -> C <- D <- E -> F <- G -> H,
|
|
578
|
+
# where the arrows specify the direction of coercion (i.e.
|
|
579
|
+
# A -> B means A coerces to B). Note that B = FA(A), C = FB(B), ...
|
|
580
|
+
# As we want to find a "smallest" parent with some properties,
|
|
581
|
+
# we need the order
|
|
582
|
+
# A, B, E, D, C, G, F, H
|
|
583
|
+
# for our search. Thus the elements connected with a <- have to
|
|
584
|
+
# be reversed. See code below.
|
|
585
|
+
tower = []
|
|
586
|
+
reversed_part = []
|
|
587
|
+
for Fi, Ri in reversed(construction_tower(K)):
|
|
588
|
+
if Fi is not None and Fi.coercion_reversed:
|
|
589
|
+
reversed_part.append((Fi, Ri))
|
|
590
|
+
else:
|
|
591
|
+
tower.append((Fi, Ri))
|
|
592
|
+
if reversed_part:
|
|
593
|
+
tower += reversed(reversed_part)
|
|
594
|
+
reversed_part = []
|
|
595
|
+
assert(not reversed_part)
|
|
596
|
+
for _, Ri in tower:
|
|
597
|
+
if not Ri.has_coerce_map_from(self.G):
|
|
598
|
+
continue
|
|
599
|
+
Ki = Ri._pseudo_fraction_field()
|
|
600
|
+
if Ki is Ri:
|
|
601
|
+
K = Ki
|
|
602
|
+
break
|
|
603
|
+
module_action = type(self)(K, self.codomain())
|
|
604
|
+
connecting = K.coerce_map_from(self.G)
|
|
605
|
+
left, right = (connecting, None) if self._is_left else (None, connecting)
|
|
606
|
+
return PrecomposedAction(InverseAction(module_action), left, right)
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
cdef class LeftModuleAction(ModuleAction):
|
|
610
|
+
cpdef _act_(self, g, a):
|
|
611
|
+
"""
|
|
612
|
+
A left module action is an action that takes the ring element as the
|
|
613
|
+
first argument (the left side) and the module element as the second
|
|
614
|
+
argument (the right side).
|
|
615
|
+
|
|
616
|
+
EXAMPLES:
|
|
617
|
+
|
|
618
|
+
Note that coerce actions should only be used inside of the coercion
|
|
619
|
+
model. For this test, we need to strongly reference the domains,
|
|
620
|
+
for otherwise they could be garbage collected, giving rise to
|
|
621
|
+
random errors (see :issue:`18157`). ::
|
|
622
|
+
|
|
623
|
+
sage: from sage.structure.coerce_actions import LeftModuleAction
|
|
624
|
+
sage: R.<x> = QQ['x']
|
|
625
|
+
sage: A = LeftModuleAction(ZZ, R)
|
|
626
|
+
sage: A(5, x+1)
|
|
627
|
+
5*x + 5
|
|
628
|
+
sage: R.<x> = ZZ['x']
|
|
629
|
+
sage: A = LeftModuleAction(QQ, R)
|
|
630
|
+
sage: A(1/2, x+1)
|
|
631
|
+
1/2*x + 1/2
|
|
632
|
+
sage: A(1/2, x+1)
|
|
633
|
+
1/2*x + 1/2
|
|
634
|
+
"""
|
|
635
|
+
# The way we are called, we know for sure that a is a
|
|
636
|
+
# ModuleElement and that g is an Element.
|
|
637
|
+
# If we change a or g, we need to explicitly check this,
|
|
638
|
+
# which explains the <?> casts below.
|
|
639
|
+
if self.connecting is not None:
|
|
640
|
+
g = <Element?>self.connecting._call_(g)
|
|
641
|
+
if self.extended_base is not None:
|
|
642
|
+
a = <ModuleElement?>self.extended_base(a)
|
|
643
|
+
return (<ModuleElement>a)._rmul_(<Element>g) # g * a
|
|
644
|
+
|
|
645
|
+
|
|
646
|
+
cdef class RightModuleAction(ModuleAction):
|
|
647
|
+
cpdef _act_(self, g, a):
|
|
648
|
+
"""
|
|
649
|
+
A right module action is an action that takes the module element as the
|
|
650
|
+
first argument (the left side) and the ring element as the second
|
|
651
|
+
argument (the right side).
|
|
652
|
+
|
|
653
|
+
EXAMPLES:
|
|
654
|
+
|
|
655
|
+
Note that coerce actions should only be used inside of the coercion
|
|
656
|
+
model. For this test, we need to strongly reference the domains,
|
|
657
|
+
for otherwise they could be garbage collected, giving rise to
|
|
658
|
+
random errors (see :issue:`18157`). ::
|
|
659
|
+
|
|
660
|
+
sage: from sage.structure.coerce_actions import RightModuleAction
|
|
661
|
+
sage: R.<x> = QQ['x']
|
|
662
|
+
sage: A = RightModuleAction(ZZ, R)
|
|
663
|
+
sage: A(x+5, 2)
|
|
664
|
+
2*x + 10
|
|
665
|
+
sage: A(x+5, 2)
|
|
666
|
+
2*x + 10
|
|
667
|
+
"""
|
|
668
|
+
# The way we are called, we know for sure that a is a
|
|
669
|
+
# ModuleElement and that g is an Element.
|
|
670
|
+
# If we change a or g, we need to explicitly check this,
|
|
671
|
+
# which explains the <?> casts below.
|
|
672
|
+
if self.connecting is not None:
|
|
673
|
+
g = <Element?>self.connecting._call_(g)
|
|
674
|
+
if self.extended_base is not None:
|
|
675
|
+
a = <ModuleElement?>self.extended_base(a)
|
|
676
|
+
return (<ModuleElement>a)._lmul_(<Element>g) # a * g
|
|
677
|
+
|
|
678
|
+
|
|
679
|
+
cdef class IntegerAction(Action):
|
|
680
|
+
"""
|
|
681
|
+
Abstract base class representing some action by integers on
|
|
682
|
+
something. Here, "integer" is defined loosely in the "duck typing"
|
|
683
|
+
sense.
|
|
684
|
+
|
|
685
|
+
INPUT:
|
|
686
|
+
|
|
687
|
+
- ``Z`` -- a type or parent representing integers
|
|
688
|
+
|
|
689
|
+
For the other arguments, see :class:`Action`.
|
|
690
|
+
|
|
691
|
+
.. NOTE::
|
|
692
|
+
|
|
693
|
+
This class is used internally in Sage's coercion model. Outside
|
|
694
|
+
of the coercion model, special precautions are needed to prevent
|
|
695
|
+
domains of the action from being garbage collected.
|
|
696
|
+
"""
|
|
697
|
+
def __init__(self, Z, S, is_left, op):
|
|
698
|
+
if isinstance(Z, type):
|
|
699
|
+
from sage.sets.pythonclass import Set_PythonType
|
|
700
|
+
Z = Set_PythonType(Z)
|
|
701
|
+
super().__init__(Z, S, is_left, op)
|
|
702
|
+
|
|
703
|
+
def __reduce__(self):
|
|
704
|
+
"""
|
|
705
|
+
Used in pickling.
|
|
706
|
+
|
|
707
|
+
TESTS:
|
|
708
|
+
|
|
709
|
+
Check that this action can be pickled (:issue:`29031`)::
|
|
710
|
+
|
|
711
|
+
sage: from sage.structure.coerce_actions import IntegerMulAction
|
|
712
|
+
sage: act = IntegerMulAction(ZZ, CDF) # needs sage.rings.complex_double
|
|
713
|
+
sage: loads(dumps(act)) is not None # needs sage.rings.complex_double
|
|
714
|
+
True
|
|
715
|
+
"""
|
|
716
|
+
# All base classes must take the signature
|
|
717
|
+
# (Z, S, is_left)
|
|
718
|
+
return (type(self), (self.G, self.underlying_set(), self._is_left))
|
|
719
|
+
|
|
720
|
+
def __invert__(self):
|
|
721
|
+
"""
|
|
722
|
+
EXAMPLES::
|
|
723
|
+
|
|
724
|
+
sage: from sage.structure.coerce_actions import IntegerMulAction
|
|
725
|
+
sage: act = IntegerMulAction(ZZ, CDF) # needs sage.rings.complex_double
|
|
726
|
+
sage: ~act # needs sage.rings.complex_double
|
|
727
|
+
Traceback (most recent call last):
|
|
728
|
+
...
|
|
729
|
+
TypeError: actions by ZZ cannot be inverted
|
|
730
|
+
"""
|
|
731
|
+
raise TypeError("actions by ZZ cannot be inverted")
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
cdef class IntegerMulAction(IntegerAction):
|
|
735
|
+
r"""
|
|
736
|
+
Implement the action `n \cdot a = a + a + ... + a` via repeated
|
|
737
|
+
doubling.
|
|
738
|
+
|
|
739
|
+
Both addition and negation must be defined on the set `M`.
|
|
740
|
+
|
|
741
|
+
INPUT:
|
|
742
|
+
|
|
743
|
+
- ``Z`` -- a type or parent representing integers
|
|
744
|
+
|
|
745
|
+
- ``M`` -- a ``ZZ``-module
|
|
746
|
+
|
|
747
|
+
- ``m`` -- (optional) an element of ``M``
|
|
748
|
+
|
|
749
|
+
EXAMPLES::
|
|
750
|
+
|
|
751
|
+
sage: from sage.structure.coerce_actions import IntegerMulAction
|
|
752
|
+
sage: R.<x> = QQ['x']
|
|
753
|
+
sage: act = IntegerMulAction(ZZ, R)
|
|
754
|
+
sage: act(5, x)
|
|
755
|
+
5*x
|
|
756
|
+
sage: act(0, x)
|
|
757
|
+
0
|
|
758
|
+
sage: act(-3, x-1)
|
|
759
|
+
-3*x + 3
|
|
760
|
+
"""
|
|
761
|
+
def __init__(self, Z, M, is_left=True, m=None):
|
|
762
|
+
if m is None:
|
|
763
|
+
m = M.an_element()
|
|
764
|
+
_ = m + (-m) # make sure addition and negation is allowed
|
|
765
|
+
super().__init__(Z, M, is_left, operator.mul)
|
|
766
|
+
|
|
767
|
+
cpdef _act_(self, nn, a):
|
|
768
|
+
"""
|
|
769
|
+
EXAMPLES:
|
|
770
|
+
|
|
771
|
+
Note that coerce actions should only be used inside of the coercion
|
|
772
|
+
model. For this test, we need to strongly reference the field
|
|
773
|
+
``GF(101)``, for otherwise it could be garbage collected, giving rise
|
|
774
|
+
random errors (see :issue:`18157`). ::
|
|
775
|
+
|
|
776
|
+
sage: from sage.structure.coerce_actions import IntegerMulAction
|
|
777
|
+
sage: GF101 = GF(101)
|
|
778
|
+
sage: act = IntegerMulAction(ZZ, GF101)
|
|
779
|
+
sage: act(3, 9)
|
|
780
|
+
27
|
|
781
|
+
sage: act(3^689, 9)
|
|
782
|
+
42
|
|
783
|
+
sage: 3^689 * mod(9, 101)
|
|
784
|
+
42
|
|
785
|
+
|
|
786
|
+
TESTS:
|
|
787
|
+
|
|
788
|
+
Use round off error to verify this is doing actual repeated addition
|
|
789
|
+
instead of just multiplying::
|
|
790
|
+
|
|
791
|
+
sage: act = IntegerMulAction(ZZ, RR)
|
|
792
|
+
sage: act(49, 1/49) == 49*RR(1/49)
|
|
793
|
+
False
|
|
794
|
+
|
|
795
|
+
This used to hang before :issue:`17844`::
|
|
796
|
+
|
|
797
|
+
sage: E = EllipticCurve(GF(5), [4,0]) # needs sage.schemes
|
|
798
|
+
sage: P = E.random_element() # needs sage.schemes
|
|
799
|
+
sage: (-2^63)*P # needs sage.schemes
|
|
800
|
+
(0 : 1 : 0)
|
|
801
|
+
|
|
802
|
+
Check that large multiplications can be interrupted::
|
|
803
|
+
|
|
804
|
+
sage: # needs sage.schemes
|
|
805
|
+
sage: P = E([2,1,1])
|
|
806
|
+
sage: from sage.doctest.util import ensure_interruptible_after
|
|
807
|
+
sage: with ensure_interruptible_after(0.001): 2^(10^8) * P
|
|
808
|
+
|
|
809
|
+
Verify that cysignals correctly detects that the above
|
|
810
|
+
exception has been handled::
|
|
811
|
+
|
|
812
|
+
sage: # needs sage.schemes
|
|
813
|
+
sage: from cysignals.tests import print_sig_occurred
|
|
814
|
+
sage: print_sig_occurred()
|
|
815
|
+
No current exception
|
|
816
|
+
"""
|
|
817
|
+
cdef int err = 0
|
|
818
|
+
cdef long n_long
|
|
819
|
+
|
|
820
|
+
if integer_check_long(nn, &n_long, &err) and not err:
|
|
821
|
+
return fast_mul_long(a, n_long)
|
|
822
|
+
|
|
823
|
+
return fast_mul(a, nn)
|
|
824
|
+
|
|
825
|
+
def _repr_name_(self):
|
|
826
|
+
"""
|
|
827
|
+
EXAMPLES:
|
|
828
|
+
|
|
829
|
+
Note that coerce actions should only be used inside of the coercion
|
|
830
|
+
model. For this test, we need to strongly reference the field
|
|
831
|
+
``GF(5)``, for otherwise it could be garbage collected, giving rise
|
|
832
|
+
random errors (see :issue:`18157`). ::
|
|
833
|
+
|
|
834
|
+
sage: from sage.structure.coerce_actions import IntegerMulAction
|
|
835
|
+
sage: GF5 = GF(5)
|
|
836
|
+
sage: IntegerMulAction(ZZ, GF5)
|
|
837
|
+
Left Integer Multiplication by Integer Ring
|
|
838
|
+
on Finite Field of size 5
|
|
839
|
+
"""
|
|
840
|
+
return "Integer Multiplication"
|
|
841
|
+
|
|
842
|
+
|
|
843
|
+
cdef class IntegerPowAction(IntegerAction):
|
|
844
|
+
r"""
|
|
845
|
+
The right action ``a ^ n = a * a * ... * a`` where `n` is an
|
|
846
|
+
integer.
|
|
847
|
+
|
|
848
|
+
The action is implemented using the ``_pow_int`` method on elements.
|
|
849
|
+
|
|
850
|
+
INPUT:
|
|
851
|
+
|
|
852
|
+
- ``Z`` -- a type or parent representing integers
|
|
853
|
+
|
|
854
|
+
- ``M`` -- a parent whose elements implement ``_pow_int``
|
|
855
|
+
|
|
856
|
+
- ``m`` -- (optional) an element of ``M``
|
|
857
|
+
|
|
858
|
+
EXAMPLES::
|
|
859
|
+
|
|
860
|
+
sage: from sage.structure.coerce_actions import IntegerPowAction
|
|
861
|
+
sage: R.<x> = LaurentSeriesRing(QQ)
|
|
862
|
+
sage: act = IntegerPowAction(ZZ, R)
|
|
863
|
+
sage: act(x, 5)
|
|
864
|
+
x^5
|
|
865
|
+
sage: act(x, -2)
|
|
866
|
+
x^-2
|
|
867
|
+
sage: act(x, int(5))
|
|
868
|
+
x^5
|
|
869
|
+
|
|
870
|
+
TESTS::
|
|
871
|
+
|
|
872
|
+
sage: IntegerPowAction(ZZ, R, True)
|
|
873
|
+
Traceback (most recent call last):
|
|
874
|
+
...
|
|
875
|
+
ValueError: powering must be a right action
|
|
876
|
+
sage: IntegerPowAction(ZZ, QQ^3) # needs sage.modules
|
|
877
|
+
Traceback (most recent call last):
|
|
878
|
+
...
|
|
879
|
+
TypeError: no integer powering action defined on Vector space of dimension 3 over Rational Field
|
|
880
|
+
|
|
881
|
+
::
|
|
882
|
+
|
|
883
|
+
sage: var('x,y') # needs sage.symbolic
|
|
884
|
+
(x, y)
|
|
885
|
+
sage: RDF('-2.3')^(x+y^3+sin(x)) # needs sage.symbolic
|
|
886
|
+
(-2.3)^(y^3 + x + sin(x))
|
|
887
|
+
sage: RDF('-2.3')^x # needs sage.symbolic
|
|
888
|
+
(-2.3)^x
|
|
889
|
+
"""
|
|
890
|
+
def __init__(self, Z, M, is_left=False, m=None):
|
|
891
|
+
if is_left:
|
|
892
|
+
raise ValueError("powering must be a right action")
|
|
893
|
+
if m is None:
|
|
894
|
+
m = M.an_element()
|
|
895
|
+
try:
|
|
896
|
+
# Check that there is a _pow_int() method
|
|
897
|
+
m._pow_int
|
|
898
|
+
except AttributeError:
|
|
899
|
+
raise TypeError(f"no integer powering action defined on {M}")
|
|
900
|
+
super().__init__(Z, M, False, operator.pow)
|
|
901
|
+
|
|
902
|
+
cpdef _act_(self, n, a):
|
|
903
|
+
"""
|
|
904
|
+
EXAMPLES:
|
|
905
|
+
|
|
906
|
+
Note that coerce actions should only be used inside of the coercion
|
|
907
|
+
model. For this test, we need to strongly reference the field
|
|
908
|
+
``GF(101)``::
|
|
909
|
+
|
|
910
|
+
sage: from sage.structure.coerce_actions import IntegerPowAction
|
|
911
|
+
sage: GF101 = GF(101)
|
|
912
|
+
sage: act = IntegerPowAction(ZZ, GF101)
|
|
913
|
+
sage: act(3, 100)
|
|
914
|
+
1
|
|
915
|
+
sage: act(3, -1)
|
|
916
|
+
34
|
|
917
|
+
sage: act(3, 1000000000000000000000000000000000000000000001)
|
|
918
|
+
3
|
|
919
|
+
"""
|
|
920
|
+
cdef Element e = <Element>a
|
|
921
|
+
cdef long value = 0
|
|
922
|
+
cdef int err
|
|
923
|
+
integer_check_long(n, &value, &err)
|
|
924
|
+
if not err:
|
|
925
|
+
return e._pow_long(value)
|
|
926
|
+
return e._pow_int(n)
|
|
927
|
+
|
|
928
|
+
def _repr_name_(self):
|
|
929
|
+
"""
|
|
930
|
+
EXAMPLES::
|
|
931
|
+
|
|
932
|
+
sage: from sage.structure.coerce_actions import IntegerPowAction
|
|
933
|
+
sage: IntegerPowAction(ZZ, QQ)
|
|
934
|
+
Right Integer Powering by Integer Ring on Rational Field
|
|
935
|
+
"""
|
|
936
|
+
return "Integer Powering"
|
|
937
|
+
|
|
938
|
+
|
|
939
|
+
cdef inline fast_mul(a, n):
|
|
940
|
+
if n < 0:
|
|
941
|
+
n = -n
|
|
942
|
+
a = -a
|
|
943
|
+
pow2a = a
|
|
944
|
+
while n & 1 == 0:
|
|
945
|
+
sig_check()
|
|
946
|
+
pow2a += pow2a
|
|
947
|
+
n = n >> 1
|
|
948
|
+
sum = pow2a
|
|
949
|
+
n = n >> 1
|
|
950
|
+
while n != 0:
|
|
951
|
+
sig_check()
|
|
952
|
+
pow2a += pow2a
|
|
953
|
+
if n & 1:
|
|
954
|
+
sum += pow2a
|
|
955
|
+
n = n >> 1
|
|
956
|
+
return sum
|
|
957
|
+
|
|
958
|
+
cdef inline fast_mul_long(a, long s):
|
|
959
|
+
# It's important to change the signed s to an unsigned n,
|
|
960
|
+
# since -LONG_MIN = LONG_MIN. See Issue #17844.
|
|
961
|
+
cdef unsigned long n
|
|
962
|
+
if s < 0:
|
|
963
|
+
n = -s
|
|
964
|
+
a = -a
|
|
965
|
+
else:
|
|
966
|
+
n = s
|
|
967
|
+
if n < 4:
|
|
968
|
+
if n == 0:
|
|
969
|
+
p = parent(a)
|
|
970
|
+
try:
|
|
971
|
+
return p.zero()
|
|
972
|
+
except AttributeError:
|
|
973
|
+
return p(0)
|
|
974
|
+
elif n == 1: return a
|
|
975
|
+
elif n == 2: return a+a
|
|
976
|
+
elif n == 3: return a+a+a
|
|
977
|
+
pow2a = a
|
|
978
|
+
while n & 1 == 0:
|
|
979
|
+
pow2a += pow2a
|
|
980
|
+
n = n >> 1
|
|
981
|
+
sum = pow2a
|
|
982
|
+
n = n >> 1
|
|
983
|
+
while n != 0:
|
|
984
|
+
pow2a += pow2a
|
|
985
|
+
if n & 1:
|
|
986
|
+
sum += pow2a
|
|
987
|
+
n = n >> 1
|
|
988
|
+
return sum
|