passagemath-objects 10.6.47__cp311-cp311-macosx_13_0_x86_64.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.
Files changed (280) hide show
  1. passagemath_objects/.dylibs/libgmp.10.dylib +0 -0
  2. passagemath_objects/__init__.py +3 -0
  3. passagemath_objects-10.6.47.dist-info/METADATA +115 -0
  4. passagemath_objects-10.6.47.dist-info/RECORD +280 -0
  5. passagemath_objects-10.6.47.dist-info/WHEEL +6 -0
  6. passagemath_objects-10.6.47.dist-info/top_level.txt +3 -0
  7. sage/all__sagemath_objects.py +37 -0
  8. sage/arith/all__sagemath_objects.py +5 -0
  9. sage/arith/long.pxd +411 -0
  10. sage/arith/numerical_approx.cpython-311-darwin.so +0 -0
  11. sage/arith/numerical_approx.pxd +35 -0
  12. sage/arith/numerical_approx.pyx +75 -0
  13. sage/arith/power.cpython-311-darwin.so +0 -0
  14. sage/arith/power.pxd +31 -0
  15. sage/arith/power.pyx +127 -0
  16. sage/categories/action.cpython-311-darwin.so +0 -0
  17. sage/categories/action.pxd +29 -0
  18. sage/categories/action.pyx +641 -0
  19. sage/categories/algebra_functor.py +745 -0
  20. sage/categories/all__sagemath_objects.py +33 -0
  21. sage/categories/basic.py +62 -0
  22. sage/categories/cartesian_product.py +295 -0
  23. sage/categories/category.py +3401 -0
  24. sage/categories/category_cy_helper.cpython-311-darwin.so +0 -0
  25. sage/categories/category_cy_helper.pxd +8 -0
  26. sage/categories/category_cy_helper.pyx +322 -0
  27. sage/categories/category_singleton.cpython-311-darwin.so +0 -0
  28. sage/categories/category_singleton.pxd +3 -0
  29. sage/categories/category_singleton.pyx +342 -0
  30. sage/categories/category_types.py +637 -0
  31. sage/categories/category_with_axiom.py +2876 -0
  32. sage/categories/covariant_functorial_construction.py +703 -0
  33. sage/categories/facade_sets.py +228 -0
  34. sage/categories/functor.cpython-311-darwin.so +0 -0
  35. sage/categories/functor.pxd +7 -0
  36. sage/categories/functor.pyx +691 -0
  37. sage/categories/homset.py +1338 -0
  38. sage/categories/homsets.py +364 -0
  39. sage/categories/isomorphic_objects.py +73 -0
  40. sage/categories/map.cpython-311-darwin.so +0 -0
  41. sage/categories/map.pxd +34 -0
  42. sage/categories/map.pyx +2106 -0
  43. sage/categories/morphism.cpython-311-darwin.so +0 -0
  44. sage/categories/morphism.pxd +14 -0
  45. sage/categories/morphism.pyx +895 -0
  46. sage/categories/objects.py +167 -0
  47. sage/categories/primer.py +1696 -0
  48. sage/categories/pushout.py +4834 -0
  49. sage/categories/quotients.py +64 -0
  50. sage/categories/realizations.py +200 -0
  51. sage/categories/sets_cat.py +3290 -0
  52. sage/categories/sets_with_partial_maps.py +52 -0
  53. sage/categories/subobjects.py +64 -0
  54. sage/categories/subquotients.py +21 -0
  55. sage/categories/with_realizations.py +311 -0
  56. sage/cpython/__init__.py +19 -0
  57. sage/cpython/_py2_random.py +619 -0
  58. sage/cpython/all.py +3 -0
  59. sage/cpython/atexit.cpython-311-darwin.so +0 -0
  60. sage/cpython/atexit.pyx +269 -0
  61. sage/cpython/builtin_types.cpython-311-darwin.so +0 -0
  62. sage/cpython/builtin_types.pyx +7 -0
  63. sage/cpython/cython_metaclass.cpython-311-darwin.so +0 -0
  64. sage/cpython/cython_metaclass.h +117 -0
  65. sage/cpython/cython_metaclass.pxd +3 -0
  66. sage/cpython/cython_metaclass.pyx +130 -0
  67. sage/cpython/debug.cpython-311-darwin.so +0 -0
  68. sage/cpython/debug.pyx +302 -0
  69. sage/cpython/dict_del_by_value.cpython-311-darwin.so +0 -0
  70. sage/cpython/dict_del_by_value.pxd +9 -0
  71. sage/cpython/dict_del_by_value.pyx +191 -0
  72. sage/cpython/dict_internal.h +245 -0
  73. sage/cpython/getattr.cpython-311-darwin.so +0 -0
  74. sage/cpython/getattr.pxd +9 -0
  75. sage/cpython/getattr.pyx +439 -0
  76. sage/cpython/pycore_long.h +97 -0
  77. sage/cpython/pycore_long.pxd +10 -0
  78. sage/cpython/python_debug.h +44 -0
  79. sage/cpython/python_debug.pxd +47 -0
  80. sage/cpython/pyx_visit.h +13 -0
  81. sage/cpython/string.cpython-311-darwin.so +0 -0
  82. sage/cpython/string.pxd +76 -0
  83. sage/cpython/string.pyx +34 -0
  84. sage/cpython/string_impl.h +60 -0
  85. sage/cpython/type.cpython-311-darwin.so +0 -0
  86. sage/cpython/type.pxd +2 -0
  87. sage/cpython/type.pyx +40 -0
  88. sage/cpython/wrapperdescr.pxd +67 -0
  89. sage/ext/all__sagemath_objects.py +3 -0
  90. sage/ext/ccobject.h +64 -0
  91. sage/ext/cplusplus.pxd +17 -0
  92. sage/ext/mod_int.h +30 -0
  93. sage/ext/mod_int.pxd +24 -0
  94. sage/ext/stdsage.pxd +39 -0
  95. sage/groups/all__sagemath_objects.py +1 -0
  96. sage/groups/group.cpython-311-darwin.so +0 -0
  97. sage/groups/group.pxd +14 -0
  98. sage/groups/group.pyx +322 -0
  99. sage/groups/old.cpython-311-darwin.so +0 -0
  100. sage/groups/old.pxd +14 -0
  101. sage/groups/old.pyx +219 -0
  102. sage/libs/all__sagemath_objects.py +3 -0
  103. sage/libs/gmp/__init__.py +1 -0
  104. sage/libs/gmp/all.pxd +6 -0
  105. sage/libs/gmp/binop.pxd +23 -0
  106. sage/libs/gmp/misc.pxd +8 -0
  107. sage/libs/gmp/mpf.pxd +88 -0
  108. sage/libs/gmp/mpn.pxd +57 -0
  109. sage/libs/gmp/mpq.pxd +57 -0
  110. sage/libs/gmp/mpz.pxd +202 -0
  111. sage/libs/gmp/pylong.cpython-311-darwin.so +0 -0
  112. sage/libs/gmp/pylong.pxd +12 -0
  113. sage/libs/gmp/pylong.pyx +150 -0
  114. sage/libs/gmp/random.pxd +25 -0
  115. sage/libs/gmp/randomize.pxd +59 -0
  116. sage/libs/gmp/types.pxd +53 -0
  117. sage/libs/gmpxx.pxd +19 -0
  118. sage/misc/abstract_method.py +276 -0
  119. sage/misc/all__sagemath_objects.py +43 -0
  120. sage/misc/bindable_class.py +253 -0
  121. sage/misc/c3_controlled.cpython-311-darwin.so +0 -0
  122. sage/misc/c3_controlled.pxd +2 -0
  123. sage/misc/c3_controlled.pyx +1402 -0
  124. sage/misc/cachefunc.cpython-311-darwin.so +0 -0
  125. sage/misc/cachefunc.pxd +43 -0
  126. sage/misc/cachefunc.pyx +3781 -0
  127. sage/misc/call.py +188 -0
  128. sage/misc/classcall_metaclass.cpython-311-darwin.so +0 -0
  129. sage/misc/classcall_metaclass.pxd +14 -0
  130. sage/misc/classcall_metaclass.pyx +599 -0
  131. sage/misc/constant_function.cpython-311-darwin.so +0 -0
  132. sage/misc/constant_function.pyx +130 -0
  133. sage/misc/decorators.py +747 -0
  134. sage/misc/fast_methods.cpython-311-darwin.so +0 -0
  135. sage/misc/fast_methods.pxd +20 -0
  136. sage/misc/fast_methods.pyx +351 -0
  137. sage/misc/flatten.py +90 -0
  138. sage/misc/fpickle.cpython-311-darwin.so +0 -0
  139. sage/misc/fpickle.pyx +177 -0
  140. sage/misc/function_mangling.cpython-311-darwin.so +0 -0
  141. sage/misc/function_mangling.pxd +11 -0
  142. sage/misc/function_mangling.pyx +308 -0
  143. sage/misc/inherit_comparison.cpython-311-darwin.so +0 -0
  144. sage/misc/inherit_comparison.pxd +5 -0
  145. sage/misc/inherit_comparison.pyx +105 -0
  146. sage/misc/instancedoc.cpython-311-darwin.so +0 -0
  147. sage/misc/instancedoc.pyx +331 -0
  148. sage/misc/lazy_attribute.cpython-311-darwin.so +0 -0
  149. sage/misc/lazy_attribute.pyx +607 -0
  150. sage/misc/lazy_format.py +135 -0
  151. sage/misc/lazy_import.cpython-311-darwin.so +0 -0
  152. sage/misc/lazy_import.pyx +1299 -0
  153. sage/misc/lazy_import_cache.py +36 -0
  154. sage/misc/lazy_list.cpython-311-darwin.so +0 -0
  155. sage/misc/lazy_list.pxd +19 -0
  156. sage/misc/lazy_list.pyx +1187 -0
  157. sage/misc/lazy_string.cpython-311-darwin.so +0 -0
  158. sage/misc/lazy_string.pxd +7 -0
  159. sage/misc/lazy_string.pyx +546 -0
  160. sage/misc/misc.py +1066 -0
  161. sage/misc/misc_c.cpython-311-darwin.so +0 -0
  162. sage/misc/misc_c.pxd +3 -0
  163. sage/misc/misc_c.pyx +766 -0
  164. sage/misc/namespace_package.py +37 -0
  165. sage/misc/nested_class.cpython-311-darwin.so +0 -0
  166. sage/misc/nested_class.pxd +3 -0
  167. sage/misc/nested_class.pyx +394 -0
  168. sage/misc/persist.cpython-311-darwin.so +0 -0
  169. sage/misc/persist.pyx +1251 -0
  170. sage/misc/prandom.py +418 -0
  171. sage/misc/randstate.cpython-311-darwin.so +0 -0
  172. sage/misc/randstate.pxd +30 -0
  173. sage/misc/randstate.pyx +1059 -0
  174. sage/misc/repr.py +203 -0
  175. sage/misc/reset.cpython-311-darwin.so +0 -0
  176. sage/misc/reset.pyx +196 -0
  177. sage/misc/sage_ostools.cpython-311-darwin.so +0 -0
  178. sage/misc/sage_ostools.pyx +323 -0
  179. sage/misc/sage_timeit.py +275 -0
  180. sage/misc/sage_timeit_class.cpython-311-darwin.so +0 -0
  181. sage/misc/sage_timeit_class.pyx +120 -0
  182. sage/misc/sage_unittest.py +637 -0
  183. sage/misc/sageinspect.py +2768 -0
  184. sage/misc/session.cpython-311-darwin.so +0 -0
  185. sage/misc/session.pyx +392 -0
  186. sage/misc/superseded.py +557 -0
  187. sage/misc/test_nested_class.py +228 -0
  188. sage/misc/timing.py +264 -0
  189. sage/misc/unknown.py +222 -0
  190. sage/misc/verbose.py +253 -0
  191. sage/misc/weak_dict.cpython-311-darwin.so +0 -0
  192. sage/misc/weak_dict.pxd +15 -0
  193. sage/misc/weak_dict.pyx +1231 -0
  194. sage/modules/all__sagemath_objects.py +1 -0
  195. sage/modules/module.cpython-311-darwin.so +0 -0
  196. sage/modules/module.pxd +5 -0
  197. sage/modules/module.pyx +329 -0
  198. sage/rings/all__sagemath_objects.py +3 -0
  199. sage/rings/integer_fake.h +22 -0
  200. sage/rings/integer_fake.pxd +55 -0
  201. sage/sets/all__sagemath_objects.py +3 -0
  202. sage/sets/pythonclass.cpython-311-darwin.so +0 -0
  203. sage/sets/pythonclass.pxd +9 -0
  204. sage/sets/pythonclass.pyx +247 -0
  205. sage/structure/__init__.py +4 -0
  206. sage/structure/all.py +30 -0
  207. sage/structure/category_object.cpython-311-darwin.so +0 -0
  208. sage/structure/category_object.pxd +28 -0
  209. sage/structure/category_object.pyx +1087 -0
  210. sage/structure/coerce.cpython-311-darwin.so +0 -0
  211. sage/structure/coerce.pxd +44 -0
  212. sage/structure/coerce.pyx +2107 -0
  213. sage/structure/coerce_actions.cpython-311-darwin.so +0 -0
  214. sage/structure/coerce_actions.pxd +27 -0
  215. sage/structure/coerce_actions.pyx +988 -0
  216. sage/structure/coerce_dict.cpython-311-darwin.so +0 -0
  217. sage/structure/coerce_dict.pxd +51 -0
  218. sage/structure/coerce_dict.pyx +1557 -0
  219. sage/structure/coerce_exceptions.py +23 -0
  220. sage/structure/coerce_maps.cpython-311-darwin.so +0 -0
  221. sage/structure/coerce_maps.pxd +28 -0
  222. sage/structure/coerce_maps.pyx +718 -0
  223. sage/structure/debug_options.cpython-311-darwin.so +0 -0
  224. sage/structure/debug_options.pxd +6 -0
  225. sage/structure/debug_options.pyx +54 -0
  226. sage/structure/dynamic_class.py +541 -0
  227. sage/structure/element.cpython-311-darwin.so +0 -0
  228. sage/structure/element.pxd +272 -0
  229. sage/structure/element.pyx +4772 -0
  230. sage/structure/element_wrapper.cpython-311-darwin.so +0 -0
  231. sage/structure/element_wrapper.pxd +12 -0
  232. sage/structure/element_wrapper.pyx +582 -0
  233. sage/structure/factorization.py +1422 -0
  234. sage/structure/factorization_integer.py +105 -0
  235. sage/structure/factory.cpython-311-darwin.so +0 -0
  236. sage/structure/factory.pyx +786 -0
  237. sage/structure/formal_sum.py +489 -0
  238. sage/structure/gens_py.py +73 -0
  239. sage/structure/global_options.py +1743 -0
  240. sage/structure/indexed_generators.py +863 -0
  241. sage/structure/list_clone.cpython-311-darwin.so +0 -0
  242. sage/structure/list_clone.pxd +65 -0
  243. sage/structure/list_clone.pyx +1867 -0
  244. sage/structure/list_clone_demo.cpython-311-darwin.so +0 -0
  245. sage/structure/list_clone_demo.pyx +248 -0
  246. sage/structure/list_clone_timings.py +179 -0
  247. sage/structure/list_clone_timings_cy.cpython-311-darwin.so +0 -0
  248. sage/structure/list_clone_timings_cy.pyx +86 -0
  249. sage/structure/mutability.cpython-311-darwin.so +0 -0
  250. sage/structure/mutability.pxd +21 -0
  251. sage/structure/mutability.pyx +348 -0
  252. sage/structure/nonexact.py +69 -0
  253. sage/structure/parent.cpython-311-darwin.so +0 -0
  254. sage/structure/parent.pxd +112 -0
  255. sage/structure/parent.pyx +3093 -0
  256. sage/structure/parent_base.cpython-311-darwin.so +0 -0
  257. sage/structure/parent_base.pxd +13 -0
  258. sage/structure/parent_base.pyx +44 -0
  259. sage/structure/parent_gens.cpython-311-darwin.so +0 -0
  260. sage/structure/parent_gens.pxd +22 -0
  261. sage/structure/parent_gens.pyx +377 -0
  262. sage/structure/parent_old.cpython-311-darwin.so +0 -0
  263. sage/structure/parent_old.pxd +25 -0
  264. sage/structure/parent_old.pyx +294 -0
  265. sage/structure/proof/__init__.py +1 -0
  266. sage/structure/proof/all.py +243 -0
  267. sage/structure/proof/proof.py +300 -0
  268. sage/structure/richcmp.cpython-311-darwin.so +0 -0
  269. sage/structure/richcmp.pxd +213 -0
  270. sage/structure/richcmp.pyx +495 -0
  271. sage/structure/sage_object.cpython-311-darwin.so +0 -0
  272. sage/structure/sage_object.pxd +3 -0
  273. sage/structure/sage_object.pyx +988 -0
  274. sage/structure/sage_object_test.py +19 -0
  275. sage/structure/sequence.py +937 -0
  276. sage/structure/set_factories.py +1178 -0
  277. sage/structure/set_factories_example.py +527 -0
  278. sage/structure/support_view.py +179 -0
  279. sage/structure/test_factory.py +56 -0
  280. 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