passagemath-objects 10.6.46__cp314-cp314t-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.

Potentially problematic release.


This version of passagemath-objects might be problematic. Click here for more details.

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.46.dist-info/METADATA +115 -0
  4. passagemath_objects-10.6.46.dist-info/RECORD +280 -0
  5. passagemath_objects-10.6.46.dist-info/WHEEL +6 -0
  6. passagemath_objects-10.6.46.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-314t-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-314t-darwin.so +0 -0
  14. sage/arith/power.pxd +31 -0
  15. sage/arith/power.pyx +127 -0
  16. sage/categories/action.cpython-314t-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-314t-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-314t-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-314t-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-314t-darwin.so +0 -0
  41. sage/categories/map.pxd +34 -0
  42. sage/categories/map.pyx +2106 -0
  43. sage/categories/morphism.cpython-314t-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-314t-darwin.so +0 -0
  60. sage/cpython/atexit.pyx +269 -0
  61. sage/cpython/builtin_types.cpython-314t-darwin.so +0 -0
  62. sage/cpython/builtin_types.pyx +7 -0
  63. sage/cpython/cython_metaclass.cpython-314t-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-314t-darwin.so +0 -0
  68. sage/cpython/debug.pyx +302 -0
  69. sage/cpython/dict_del_by_value.cpython-314t-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-314t-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-314t-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-314t-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-314t-darwin.so +0 -0
  97. sage/groups/group.pxd +14 -0
  98. sage/groups/group.pyx +322 -0
  99. sage/groups/old.cpython-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-darwin.so +0 -0
  139. sage/misc/fpickle.pyx +177 -0
  140. sage/misc/function_mangling.cpython-314t-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-314t-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-314t-darwin.so +0 -0
  147. sage/misc/instancedoc.pyx +331 -0
  148. sage/misc/lazy_attribute.cpython-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-darwin.so +0 -0
  169. sage/misc/persist.pyx +1251 -0
  170. sage/misc/prandom.py +418 -0
  171. sage/misc/randstate.cpython-314t-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-314t-darwin.so +0 -0
  176. sage/misc/reset.pyx +196 -0
  177. sage/misc/sage_ostools.cpython-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-darwin.so +0 -0
  211. sage/structure/coerce.pxd +44 -0
  212. sage/structure/coerce.pyx +2107 -0
  213. sage/structure/coerce_actions.cpython-314t-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-314t-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-314t-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-314t-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-314t-darwin.so +0 -0
  228. sage/structure/element.pxd +272 -0
  229. sage/structure/element.pyx +4772 -0
  230. sage/structure/element_wrapper.cpython-314t-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-314t-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-314t-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-314t-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-314t-darwin.so +0 -0
  248. sage/structure/list_clone_timings_cy.pyx +86 -0
  249. sage/structure/mutability.cpython-314t-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-314t-darwin.so +0 -0
  254. sage/structure/parent.pxd +112 -0
  255. sage/structure/parent.pyx +3093 -0
  256. sage/structure/parent_base.cpython-314t-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-314t-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-314t-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-314t-darwin.so +0 -0
  269. sage/structure/richcmp.pxd +213 -0
  270. sage/structure/richcmp.pyx +495 -0
  271. sage/structure/sage_object.cpython-314t-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,3093 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ r"""
3
+ Base class for parent objects
4
+
5
+ CLASS HIERARCHY::
6
+
7
+ SageObject
8
+ CategoryObject
9
+ Parent
10
+
11
+ A simple example of registering coercions::
12
+
13
+ sage: class A_class(Parent):
14
+ ....: def __init__(self, name):
15
+ ....: Parent.__init__(self)
16
+ ....: self._populate_coercion_lists_()
17
+ ....: self.rename(name)
18
+ ....:
19
+ ....: def category(self):
20
+ ....: return Sets()
21
+ ....:
22
+ ....: def _element_constructor_(self, i):
23
+ ....: assert(isinstance(i, (int, Integer)))
24
+ ....: return ElementWrapper(self, i)
25
+ sage: A = A_class("A")
26
+ sage: B = A_class("B")
27
+ sage: C = A_class("C")
28
+
29
+ sage: def f(a):
30
+ ....: return B(a.value+1)
31
+ sage: class MyMorphism(Morphism):
32
+ ....: def __init__(self, domain, codomain):
33
+ ....: Morphism.__init__(self, Hom(domain, codomain))
34
+ ....:
35
+ ....: def _call_(self, x):
36
+ ....: return self.codomain()(x.value)
37
+ sage: f = MyMorphism(A,B)
38
+ sage: f
39
+ Generic morphism:
40
+ From: A
41
+ To: B
42
+ sage: B.register_coercion(f)
43
+ sage: C.register_coercion(MyMorphism(B,C))
44
+ sage: A(A(1)) == A(1)
45
+ True
46
+ sage: B(A(1)) == B(1)
47
+ True
48
+ sage: C(A(1)) == C(1)
49
+ True
50
+
51
+ sage: A(B(1))
52
+ Traceback (most recent call last):
53
+ ...
54
+ AssertionError
55
+
56
+ When implementing an element of a ring, one would typically provide the
57
+ element class with ``_rmul_`` and/or ``_lmul_`` methods for the action of a
58
+ base ring, and with ``_mul_`` for the ring multiplication. However, prior to
59
+ :issue:`14249`, it would have been necessary to additionally define a method
60
+ ``_an_element_()`` for the parent. But now, the following example works::
61
+
62
+ sage: from sage.structure.element import RingElement
63
+ sage: class MyElement(RingElement):
64
+ ....: def __init__(self, parent, x, y):
65
+ ....: RingElement.__init__(self, parent)
66
+ ....: def _mul_(self, other):
67
+ ....: return self
68
+ ....: def _rmul_(self, other):
69
+ ....: return self
70
+ ....: def _lmul_(self, other):
71
+ ....: return self
72
+ sage: class MyParent(Parent):
73
+ ....: Element = MyElement
74
+
75
+ Now, we define ::
76
+
77
+ sage: P = MyParent(base=ZZ, category=Rings())
78
+ sage: a = P(1,2)
79
+ sage: a*a is a
80
+ True
81
+ sage: a*2 is a
82
+ True
83
+ sage: 2*a is a
84
+ True
85
+
86
+ TESTS:
87
+
88
+ This came up in some subtle bug once::
89
+
90
+ sage: gp(2) + gap(3) # needs sage.libs.gap sage.libs.pari
91
+ 5
92
+ """
93
+ # ****************************************************************************
94
+ # Copyright (C) 2009 Robert Bradshaw <robertwb@math.washington.edu>
95
+ # Copyright (C) 2008 Burcin Erocal <burcin@erocal.org>
96
+ # Copyright (C) 2008 Mike Hansen <mhansen@gmail.com>
97
+ # Copyright (C) 2008 David Roe <roed@math.harvard.edu>
98
+ # Copyright (C) 2007 William Stein <wstein@gmail.com>
99
+ #
100
+ # This program is free software: you can redistribute it and/or modify
101
+ # it under the terms of the GNU General Public License as published by
102
+ # the Free Software Foundation, either version 2 of the License, or
103
+ # (at your option) any later version.
104
+ # https://www.gnu.org/licenses/
105
+ # ****************************************************************************
106
+
107
+ from cpython.object cimport Py_EQ, Py_LE, Py_GE
108
+ from cpython.bool cimport *
109
+
110
+ from types import MethodType, BuiltinMethodType
111
+ import operator
112
+ from copy import copy
113
+
114
+ from sage.cpython.type cimport can_assign_class
115
+ cimport sage.categories.map as map
116
+ from sage.structure.debug_options cimport debug
117
+ from sage.structure.sage_object cimport SageObject
118
+ from sage.misc.cachefunc import cached_method
119
+ from sage.misc.lazy_attribute import lazy_attribute
120
+ from sage.categories.sets_cat import Sets, EmptySetError
121
+ from sage.misc.lazy_string cimport _LazyString
122
+ from sage.sets.pythonclass cimport Set_PythonType_class
123
+ from sage.structure.category_object import CategoryObject
124
+ from sage.structure.coerce cimport coercion_model
125
+ from sage.structure.coerce cimport parent_is_integers
126
+ from sage.structure.coerce_exceptions import CoercionException
127
+ from sage.structure.coerce_maps cimport (NamedConvertMap, DefaultConvertMap,
128
+ DefaultConvertMap_unique, CallableConvertMap)
129
+ from sage.structure.element cimport parent
130
+
131
+
132
+ cdef _record_exception():
133
+ coercion_model._record_exception()
134
+
135
+ cdef object _Integer
136
+ cdef bint is_Integer(x) noexcept:
137
+ global _Integer
138
+ if _Integer is None:
139
+ from sage.rings.integer import Integer as _Integer
140
+ return type(x) is _Integer or type(x) is int
141
+
142
+
143
+ def is_Parent(x):
144
+ """
145
+ Return ``True`` if x is a parent object, i.e., derives from
146
+ sage.structure.parent.Parent and ``False`` otherwise.
147
+
148
+ EXAMPLES::
149
+
150
+ sage: from sage.structure.parent import is_Parent
151
+ sage: is_Parent(2/3)
152
+ doctest:warning...
153
+ DeprecationWarning: the function is_Parent is deprecated;
154
+ use 'isinstance(..., Parent)' instead
155
+ See https://github.com/sagemath/sage/issues/37922 for details.
156
+ False
157
+ sage: is_Parent(ZZ)
158
+ True
159
+ sage: is_Parent(Primes())
160
+ True
161
+ """
162
+ from sage.misc.superseded import deprecation_cython
163
+ deprecation_cython(37922, "the function is_Parent is deprecated; use 'isinstance(..., Parent)' instead")
164
+ return isinstance(x, Parent)
165
+
166
+
167
+ cdef bint guess_pass_parent(parent, element_constructor) noexcept:
168
+ # Returning True here is deprecated, see #26879
169
+ if isinstance(element_constructor, MethodType):
170
+ return False
171
+ elif isinstance(element_constructor, BuiltinMethodType):
172
+ return element_constructor.__self__ is not parent
173
+ else:
174
+ return True
175
+
176
+ from sage.categories.category import Category
177
+ from sage.structure.dynamic_class import dynamic_class
178
+ Sets_parent_class = Sets().parent_class
179
+
180
+
181
+ cdef inline bint good_as_coerce_domain(S) noexcept:
182
+ """
183
+ Determine whether the input can be the domain of a map.
184
+
185
+ .. NOTE::
186
+
187
+ This is the same as being an object in a category, or
188
+ being a type. Namely, in Sage, we do consider coercion maps
189
+ from the type ``<int>`` to, say, `ZZ`.
190
+
191
+ TESTS:
192
+
193
+ If an instance `S` is not suitable as domain of a map, then
194
+ the non-existence of a coercion or conversion map from `S`
195
+ to some other parent is not cached, by :issue:`13378`::
196
+
197
+ sage: P.<x,y> = QQ[]
198
+ sage: P._is_coercion_cached(x)
199
+ False
200
+ sage: P.coerce_map_from(x)
201
+ sage: P._is_coercion_cached(x)
202
+ False
203
+ """
204
+ return isinstance(S, (CategoryObject, type))
205
+
206
+
207
+ cdef inline bint good_as_convert_domain(S) noexcept:
208
+ return isinstance(S, (SageObject, type))
209
+
210
+
211
+ cdef class Parent(sage.structure.category_object.CategoryObject):
212
+ def __cinit__(self):
213
+ self._action_hash = TripleDict()
214
+
215
+ def __init__(self, base=None, *, category=None,
216
+ names=None, normalize=True, facade=None):
217
+ """
218
+ Base class for all parents.
219
+
220
+ Parents are the Sage/mathematical analogues of container
221
+ objects in computer science.
222
+
223
+ INPUT:
224
+
225
+ - ``base`` -- an algebraic structure considered to be the "base" of
226
+ this parent (e.g. the base field for a vector space)
227
+
228
+ - ``category`` -- a category or list/tuple of categories. The category
229
+ in which this parent lies (or list or tuple thereof). Since
230
+ categories support more general super-categories, this should be the
231
+ most specific category possible. If category is a list or tuple, a
232
+ ``JoinCategory`` is created out of them. If category is not
233
+ specified, the category will be guessed (see
234
+ :class:`~sage.structure.category_object.CategoryObject`), but will
235
+ not be used to inherit parent's or element's code from this category.
236
+
237
+ - ``names`` -- names of generators
238
+
239
+ - ``normalize`` -- whether to standardize the names (remove
240
+ punctuation, etc.)
241
+
242
+ - ``facade`` -- a parent, or tuple thereof, or ``True``
243
+
244
+ If ``facade`` is specified, then ``Sets().Facade()`` is added
245
+ to the categories of the parent. Furthermore, if ``facade`` is
246
+ not ``True``, the internal attribute ``_facade_for`` is set
247
+ accordingly for use by
248
+ :meth:`Sets.Facade.ParentMethods.facade_for`.
249
+
250
+ Internal invariants:
251
+
252
+ - ``self._element_init_pass_parent == guess_pass_parent(self,
253
+ self._element_constructor)`` Ensures that :meth:`__call__`
254
+ passes down the parent properly to
255
+ :meth:`_element_constructor`. See :issue:`5979`.
256
+
257
+ .. TODO::
258
+
259
+ Eventually, category should be
260
+ :class:`~sage.categories.sets_cat.Sets` by default.
261
+
262
+ TESTS:
263
+
264
+ We check that the facade option is compatible with specifying
265
+ categories as a tuple::
266
+
267
+ sage: class MyClass(Parent): pass
268
+ sage: P = MyClass(facade = ZZ, category = (Monoids(), CommutativeAdditiveMonoids()))
269
+ sage: P.category()
270
+ Join of Category of monoids and Category of commutative additive monoids and Category of facade sets
271
+
272
+ .. automethod:: __call__
273
+ .. automethod:: _populate_coercion_lists_
274
+ .. automethod:: __mul__
275
+ .. automethod:: __contains__
276
+ .. automethod:: _coerce_map_from_
277
+ .. automethod:: _convert_map_from_
278
+ .. automethod:: _get_action_
279
+ .. automethod:: _an_element_
280
+ .. automethod:: _repr_option
281
+ .. automethod:: _init_category_
282
+ .. automethod:: _is_coercion_cached
283
+ .. automethod:: _is_conversion_cached
284
+ """
285
+ if isinstance(category, (tuple, list)):
286
+ category = Category.join(category)
287
+ if facade is not None and facade is not False:
288
+ if facade is not True:
289
+ if isinstance(facade, Parent):
290
+ self._facade_for = (facade,)
291
+ else:
292
+ self._facade_for = tuple(facade)
293
+ if category is None:
294
+ category = Sets().Facade()
295
+ else:
296
+ category = Category.join((category, Sets().Facade()))
297
+
298
+ CategoryObject.__init__(self, category, base)
299
+
300
+ if names is not None:
301
+ self._assign_names(names, normalize)
302
+ self._set_element_constructor()
303
+ self.init_coerce(False)
304
+
305
+ for cls in self.__class__.mro():
306
+ # this calls __init_extra__ if it is *defined* in cls (not in a super class)
307
+ if "__init_extra__" in cls.__dict__:
308
+ cls.__init_extra__(self)
309
+
310
+ def _init_category_(self, category):
311
+ """
312
+ Initialize the category framework.
313
+
314
+ Most parents initialize their category upon construction, and
315
+ this is the recommended behavior. For example, this happens
316
+ when the constructor calls :meth:`Parent.__init__` directly or
317
+ indirectly. However, some parents defer this for performance
318
+ reasons. For example,
319
+ :mod:`sage.matrix.matrix_space.MatrixSpace` does not.
320
+
321
+ EXAMPLES::
322
+
323
+ sage: P = Parent()
324
+ sage: P.category()
325
+ Category of sets
326
+ sage: class MyParent(Parent):
327
+ ....: def __init__(self):
328
+ ....: self._init_category_(Groups())
329
+ sage: MyParent().category()
330
+ Category of groups
331
+ """
332
+ CategoryObject._init_category_(self, category)
333
+
334
+ # This substitutes the class of this parent to a subclass
335
+ # which also subclasses the parent_class of the category.
336
+
337
+ # Some parent class may readily have their category classes attached
338
+ # TODO: assert that the category is consistent
339
+ if can_assign_class(self) and not isinstance(self, Sets_parent_class):
340
+ # Documentation transfer is handled by dynamic_class
341
+ self.__class__ = dynamic_class(
342
+ f"{type(self).__name__}_with_category",
343
+ (type(self), self._category.parent_class),
344
+ doccls=type(self))
345
+
346
+ def _refine_category_(self, category):
347
+ """
348
+ Change the category of ``self`` into a subcategory.
349
+
350
+ INPUT:
351
+
352
+ - ``category`` -- a category or list or tuple thereof
353
+
354
+ The new category is obtained by adjoining ``category`` to the
355
+ current one.
356
+
357
+ .. NOTE::
358
+
359
+ The class of ``self`` might be replaced by a sub-class.
360
+
361
+ .. SEEALSO::
362
+
363
+ :meth:`CategoryObject._refine_category`
364
+
365
+ EXAMPLES::
366
+
367
+ sage: P.<x,y> = QQ[]
368
+ sage: Q = P.quotient(x^2 + 2)
369
+ sage: Q.category()
370
+ Join of
371
+ Category of commutative rings and
372
+ Category of subquotients of monoids and
373
+ Category of quotients of semigroups
374
+ sage: first_class = Q.__class__
375
+ sage: Q._refine_category_(Fields())
376
+ sage: Q.category()
377
+ Join of
378
+ Category of fields and
379
+ Category of subquotients of monoids and
380
+ Category of quotients of semigroups
381
+ sage: first_class == Q.__class__
382
+ False
383
+ sage: TestSuite(Q).run() # needs sage.libs.singular
384
+
385
+ TESTS:
386
+
387
+ Here is a test against :issue:`14471`. Refining the category will issue
388
+ a warning, if this change affects the hash value (note that this will
389
+ only be seen in doctest mode)::
390
+
391
+ sage: class MyParent(Parent):
392
+ ....: def __hash__(self):
393
+ ....: return hash(type(self)) # subtle mistake
394
+ sage: a = MyParent()
395
+ sage: h_a = hash(a)
396
+ sage: a._refine_category_(Algebras(QQ))
397
+ hash of <class '__main__.MyParent_with_category'> changed in
398
+ Parent._refine_category_ during initialisation
399
+
400
+ sage: b = MyParent(category=Rings())
401
+ sage: h_b = hash(b)
402
+ sage: h_a == h_b
403
+ False
404
+ sage: b._refine_category_(Algebras(QQ))
405
+ hash of <class '__main__.MyParent_with_category'> changed in
406
+ Parent._refine_category_ during refinement
407
+ sage: hash(a) == hash(b)
408
+ True
409
+ sage: hash(a) != h_a
410
+ True
411
+ """
412
+ cdef Py_hash_t hash_old = -1
413
+ if debug.refine_category_hash_check:
414
+ # check that the hash stays the same after refinement
415
+ hash_old = hash(self)
416
+
417
+ if self._category is None:
418
+ self._init_category_(category)
419
+ if hash_old != -1 and hash_old != hash(self):
420
+ print(f'hash of {type(self)} changed in Parent._refine_category_ during initialisation')
421
+ return
422
+ if category is self._category:
423
+ return
424
+ CategoryObject._refine_category_(self, category)
425
+ category = self._category
426
+
427
+ # This substitutes the class of this parent to a subclass
428
+ # which also subclasses the parent_class of the category.
429
+ # However, we only do so if we do not have an extension class.
430
+ if can_assign_class(self):
431
+ # We tested in the very beginning that this parent
432
+ # had its category initialised. Hence, the class
433
+ # is already a dynamic class.
434
+ base = self.__class__.__base__
435
+ # documentation transfer is handled by dynamic_class
436
+ self.__class__ = dynamic_class(
437
+ "%s_with_category" % base.__name__,
438
+ (base, category.parent_class),
439
+ doccls=base)
440
+ # If the element class has already been assigned, it
441
+ # needs to be erased now.
442
+ try:
443
+ del self.__dict__['element_class']
444
+ del self.__dict__['_abstract_element_class']
445
+ except (AttributeError, KeyError):
446
+ pass
447
+ if hash_old != -1 and hash_old != hash(self):
448
+ print(f'hash of {type(self)} changed in Parent._refine_category_ during refinement')
449
+
450
+ def _unset_category(self):
451
+ """
452
+ Remove the information on ``self``'s category.
453
+
454
+ .. NOTE::
455
+
456
+ This may change ``self``'s class!
457
+
458
+ EXAMPLES:
459
+
460
+ Let us create a parent in the category of rings::
461
+
462
+ sage: class MyParent(Parent):
463
+ ....: def __init__(self):
464
+ ....: Parent.__init__(self, category=Rings())
465
+ ....:
466
+ sage: P = MyParent()
467
+ sage: P.category()
468
+ Category of rings
469
+
470
+ Of course, its category is initialised::
471
+
472
+ sage: P._is_category_initialized()
473
+ True
474
+
475
+ We may now refine the category to the category of fields.
476
+ Note that this changes the class::
477
+
478
+ sage: C = type(P)
479
+ sage: C == MyParent
480
+ False
481
+ sage: P._refine_category_(Fields())
482
+ sage: P.category()
483
+ Category of fields
484
+ sage: C == type(P)
485
+ False
486
+
487
+ Now we may have noticed that the category refinement was a
488
+ mistake. We do not need to worry, because we can undo category
489
+ initialisation totally::
490
+
491
+ sage: P._unset_category()
492
+ sage: P._is_category_initialized()
493
+ False
494
+ sage: type(P) == MyParent
495
+ True
496
+
497
+ Hence, we can now initialise the parent again in the original
498
+ category, i.e., the category of rings. We find that not only
499
+ the category, but also the class of the parent is brought back
500
+ to what it was after the original category initialisation::
501
+
502
+ sage: P._init_category_(Rings())
503
+ sage: type(P) == C
504
+ True
505
+ """
506
+ self._category = None
507
+ if can_assign_class(self):
508
+ while issubclass(self.__class__, Sets_parent_class):
509
+ self.__class__ = self.__class__.__base__
510
+
511
+ @lazy_attribute
512
+ def _abstract_element_class(self):
513
+ """
514
+ An abstract class for the elements of this parent.
515
+
516
+ By default, this is the element class provided by the category
517
+ of the parent.
518
+
519
+ .. SEEALSO::
520
+
521
+ - :meth:`sage.categories.homset.Homset._abstract_element_class`
522
+ - :meth:`element_class`
523
+ - :meth:`Element.__getattr__`
524
+
525
+ EXAMPLES::
526
+
527
+ sage: S = Semigroups().example()
528
+ sage: S.category()
529
+ Category of semigroups
530
+ sage: S._abstract_element_class
531
+ <class 'sage.categories.semigroups.Semigroups.element_class'>
532
+ """
533
+ return self.category().element_class
534
+
535
+ # This probably should go into Sets().Parent
536
+ @lazy_attribute
537
+ def element_class(self):
538
+ """
539
+ The (default) class for the elements of this parent.
540
+
541
+ FIXME's and design issues:
542
+
543
+ - If self.Element is "trivial enough", should we optimize it away with:
544
+ self.element_class = dynamic_class("%s.element_class"%self.__class__.__name__, (category.element_class,), self.Element)
545
+ - This should lookup for Element classes in all super classes
546
+ """
547
+ try: # if hasattr(self, 'Element'):
548
+ return self.__make_element_class__(self.Element,
549
+ name="%s.element_class" % self.__class__.__name__,
550
+ module=self.__class__.__module__)
551
+ except AttributeError: # else:
552
+ return NotImplemented
553
+
554
+ def __make_element_class__(self, cls, name=None, module=None, inherit=None):
555
+ """
556
+ A utility to construct classes for the elements of this
557
+ parent, with appropriate inheritance from the element class of
558
+ the category.
559
+
560
+ It used to be the case that this did not work for extension
561
+ types, which used to never support a ``__dict__`` for instances.
562
+ So for backwards compatibility, we only use dynamic classes by
563
+ default if the class has a nonzero ``__dictoffset__``. But it
564
+ works regardless: just pass ``inherit=True`` to
565
+ ``__make_element_class__``. See also :issue:`24715`.
566
+
567
+ When we do not use a dynamic element class, the ``__getattr__``
568
+ implementation from :class:`Element` provides fake
569
+ inheritance from categories.
570
+ """
571
+ if not isinstance(cls, type):
572
+ raise TypeError(f"element class {cls!r} should be a type")
573
+ if inherit is None:
574
+ inherit = (cls.__dictoffset__ != 0)
575
+ if inherit:
576
+ if name is None:
577
+ name = "%s_with_category" % cls.__name__
578
+ cls = dynamic_class(name, (cls, self._abstract_element_class))
579
+ if module is not None:
580
+ cls.__module__ = module
581
+ return cls
582
+
583
+ def _set_element_constructor(self):
584
+ """
585
+ This function is used in translating from the old to the new coercion model.
586
+
587
+ It is called from sage.structure.parent_old.Parent.__init__
588
+ when an old style parent provides a _element_constructor_ method.
589
+
590
+ It just asserts that this _element_constructor_ is callable and
591
+ also sets self._element_init_pass_parent
592
+
593
+ EXAMPLES::
594
+
595
+ sage: k = GF(5)
596
+ sage: k._set_element_constructor()
597
+ """
598
+ try:
599
+ _element_constructor_ = self._element_constructor_
600
+ except (AttributeError, TypeError):
601
+ # Remark: A TypeError can actually occur;
602
+ # it is a possible reason for "hasattr" to return False
603
+ return
604
+ assert callable(_element_constructor_)
605
+ self._element_constructor = _element_constructor_
606
+ self._element_init_pass_parent = guess_pass_parent(self, self._element_constructor)
607
+
608
+ def category(self):
609
+ """
610
+ EXAMPLES::
611
+
612
+ sage: P = Parent()
613
+ sage: P.category()
614
+ Category of sets
615
+ sage: class MyParent(Parent):
616
+ ....: def __init__(self): pass
617
+ sage: MyParent().category()
618
+ Category of sets
619
+ """
620
+ if self._category is None:
621
+ # COERCE TODO: we should not need this
622
+ self._category = Sets()
623
+ return self._category
624
+
625
+ def _test_category(self, **options):
626
+ """
627
+ Run generic tests on the method :meth:`.category`.
628
+
629
+ See also: :class:`TestSuite`.
630
+
631
+ EXAMPLES::
632
+
633
+ sage: C = Sets().example()
634
+ sage: C._test_category()
635
+
636
+ Let us now write a parent with broken categories:
637
+
638
+ sage: class MyParent(Parent):
639
+ ....: def __init__(self):
640
+ ....: pass
641
+ sage: P = MyParent()
642
+ sage: P._test_category()
643
+ Traceback (most recent call last):
644
+ ...
645
+ AssertionError: category of <__main__.MyParent object ...> improperly initialized
646
+
647
+ To fix this, :meth:`MyParent.__init__` should initialize the
648
+ category of ``self`` by calling :meth:`._init_category` or
649
+ ``Parent.__init__(self, category = ...)``.
650
+ """
651
+ tester = self._tester(**options)
652
+ SageObject._test_category(self, tester=tester)
653
+ category = self.category()
654
+ tester.assertTrue(category.is_subcategory(Sets()))
655
+ # Tests that self inherits methods from the categories
656
+ if can_assign_class(self):
657
+ # For usual Python classes, that should be done with
658
+ # standard inheritance
659
+ tester.assertTrue(isinstance(self, category.parent_class),
660
+ _LazyString("category of %s improperly initialized", (self,), {}))
661
+ else:
662
+ # For extension types we just check that inheritance
663
+ # occurs on one specific method.
664
+ # _test_an_element from Sets().ParentMethods is a good
665
+ # candidate because it's unlikely to be overriden in self.
666
+ tester.assertTrue(hasattr(self, "_test_an_element"),
667
+ _LazyString("category of %s improperly initialized", (self,), {}))
668
+
669
+ def _test_eq(self, **options):
670
+ """
671
+ Test that ``self`` is equal to ``self`` and different to ``None``.
672
+
673
+ See also: :class:`TestSuite`.
674
+
675
+ TESTS::
676
+
677
+ sage: O = Parent()
678
+ sage: O._test_eq()
679
+
680
+ Let us now write a broken class method::
681
+
682
+ sage: class CCls(Parent):
683
+ ....: def __eq__(self, other):
684
+ ....: return True
685
+ sage: CCls()._test_eq()
686
+ Traceback (most recent call last):
687
+ ...
688
+ AssertionError: broken equality: <__main__.CCls object at ...> == None
689
+
690
+ Let us now break inequality::
691
+
692
+ sage: class CCls(Parent):
693
+ ....: def __ne__(self, other):
694
+ ....: return True
695
+ sage: CCls()._test_eq()
696
+ Traceback (most recent call last):
697
+ ...
698
+ AssertionError: broken non-equality: <__main__.CCls object at ...> != itself
699
+ """
700
+ tester = self._tester(**options)
701
+
702
+ # We do not use assertEqual / assertNonEqual in order to be
703
+ # 100% sure we indeed call the operators == and !=, whatever
704
+ # the version of Python is (see #11236)
705
+ tester.assertTrue(self == self,
706
+ _LazyString("broken equality: %s == itself is False", (self,), {}))
707
+ tester.assertFalse(self == None,
708
+ _LazyString("broken equality: %s == None", (self,), {}))
709
+ tester.assertFalse(self != self,
710
+ _LazyString("broken non-equality: %s != itself", (self,), {}))
711
+ tester.assertTrue(self != None,
712
+ _LazyString("broken non-equality: %s != None is False", (self,), {}))
713
+
714
+ cdef int init_coerce(self, bint warn=True) except -1:
715
+ if self._coerce_from_hash is None:
716
+ if warn:
717
+ raise AssertionError(f"unexpected call of init_coerce() for {type(self)}")
718
+ self._initial_coerce_list = []
719
+ self._initial_action_list = []
720
+ self._initial_convert_list = []
721
+ self._coerce_from_list = []
722
+ self._registered_domains = []
723
+ self._coerce_from_hash = MonoDict()
724
+ self._action_list = []
725
+ self._convert_from_list = []
726
+ self._convert_from_hash = MonoDict()
727
+ self._embedding = None
728
+
729
+ def _introspect_coerce(self):
730
+ """
731
+ Used for debugging the coercion model.
732
+
733
+ EXAMPLES::
734
+
735
+ sage: sorted(QQ._introspect_coerce().items())
736
+ [('_action_list', []),
737
+ ('_coerce_from_hash', <sage.structure.coerce_dict.MonoDict object at ...>),
738
+ ('_coerce_from_list', []),
739
+ ('_convert_from_hash', <sage.structure.coerce_dict.MonoDict object at ...>),
740
+ ('_convert_from_list', [...]),
741
+ ('_element_init_pass_parent', False),
742
+ ('_embedding', None),
743
+ ('_initial_action_list', []),
744
+ ('_initial_coerce_list', []),
745
+ ('_initial_convert_list', [])]
746
+ """
747
+ return {
748
+ '_coerce_from_list': self._coerce_from_list,
749
+ '_coerce_from_hash': self._coerce_from_hash,
750
+ '_action_list': self._action_list,
751
+ '_convert_from_list': self._convert_from_list,
752
+ '_convert_from_hash': self._convert_from_hash,
753
+ '_embedding': self._embedding,
754
+ '_initial_coerce_list': self._initial_coerce_list,
755
+ '_initial_action_list': self._initial_action_list,
756
+ '_initial_convert_list': self._initial_convert_list,
757
+ '_element_init_pass_parent': self._element_init_pass_parent,
758
+ }
759
+
760
+ def __getstate__(self):
761
+ """
762
+ Used for pickling.
763
+
764
+ TESTS::
765
+
766
+ sage: loads(dumps(RR['x'])) == RR['x']
767
+ True
768
+ """
769
+ d = CategoryObject.__getstate__(self)
770
+ d['_embedding'] = self._embedding
771
+ d['_element_constructor'] = self._element_constructor
772
+ d['_convert_method_name'] = self._convert_method_name
773
+ d['_element_init_pass_parent'] = self._element_init_pass_parent
774
+ d['_initial_coerce_list'] = self._initial_coerce_list
775
+ d['_initial_action_list'] = self._initial_action_list
776
+ d['_initial_convert_list'] = self._initial_convert_list
777
+ return d
778
+
779
+ def __setstate__(self, d):
780
+ """
781
+ Used for pickling.
782
+
783
+ TESTS::
784
+
785
+ sage: loads(dumps(CDF['x'])) == CDF['x'] # needs sage.rings.complex_double
786
+ True
787
+ """
788
+ CategoryObject.__setstate__(self, d)
789
+ try:
790
+ version = d['_pickle_version']
791
+ except KeyError:
792
+ version = 0
793
+ if version == 1:
794
+ self.init_coerce(False) # Really, do we want to init this with the same initial data as before?
795
+ self._populate_coercion_lists_(coerce_list=d['_initial_coerce_list'] or [],
796
+ action_list=d['_initial_action_list'] or [],
797
+ convert_list=d['_initial_convert_list'] or [],
798
+ embedding=d['_embedding'],
799
+ convert_method_name=d['_convert_method_name'],
800
+ element_constructor=d['_element_constructor'],
801
+ init_no_parent=not d['_element_init_pass_parent'],
802
+ unpickling=True)
803
+
804
+ def _repr_option(self, key):
805
+ """
806
+ Metadata about the :meth:`_repr_` output.
807
+
808
+ INPUT:
809
+
810
+ - ``key`` -- string; a key for different metadata informations
811
+ that can be inquired about
812
+
813
+ Valid ``key`` arguments are:
814
+
815
+ - ``'ascii_art'``: The :meth:`_repr_` output is multi-line
816
+ ascii art and each line must be printed starting at the same
817
+ column, or the meaning is lost.
818
+
819
+ - ``'element_ascii_art'``: same but for the output of the
820
+ elements. Used in :mod:`sage.repl.display.formatter`.
821
+
822
+ - ``'element_is_atomic'``: the elements print atomically, that
823
+ is, parenthesis are not required when *printing* out any of
824
+ `x - y`, `x + y`, `x^y` and `x/y`.
825
+
826
+ OUTPUT: boolean
827
+
828
+ EXAMPLES::
829
+
830
+ sage: ZZ._repr_option('ascii_art')
831
+ False
832
+ sage: MatrixSpace(ZZ, 2)._repr_option('element_ascii_art') # needs sage.modules
833
+ True
834
+ """
835
+ if not isinstance(key, str):
836
+ raise ValueError('key must be a string')
837
+ defaults = {'ascii_art': False,
838
+ 'element_ascii_art': False,
839
+ 'element_is_atomic': False}
840
+ return defaults[key]
841
+
842
+ def __call__(self, x=0, *args, **kwds):
843
+ """
844
+ This is the generic call method for all parents.
845
+
846
+ When called, it will find a map based on the Parent (or type) of x.
847
+ If a coercion exists, it will always be chosen. This map will
848
+ then be called (with the arguments and keywords if any).
849
+
850
+ By default this will dispatch as quickly as possible to
851
+ :meth:`_element_constructor_` though faster pathways are
852
+ possible if so desired.
853
+
854
+ TESTS:
855
+
856
+ We check that the invariant
857
+
858
+ ::
859
+
860
+ self._element_init_pass_parent == guess_pass_parent(self, self._element_constructor)
861
+
862
+ is preserved (see :issue:`5979`)::
863
+
864
+ sage: class MyParent(Parent):
865
+ ....: def _element_constructor_(self, x):
866
+ ....: print("{} {}".format(self, x))
867
+ ....: return sage.structure.element.Element(parent = self)
868
+ ....: def _repr_(self):
869
+ ....: return "my_parent"
870
+ sage: my_parent = MyParent()
871
+ sage: x = my_parent("bla")
872
+ my_parent bla
873
+ sage: x.parent() # indirect doctest
874
+ my_parent
875
+
876
+ sage: x = my_parent() # shouldn't this one raise an error?
877
+ my_parent 0
878
+ sage: x = my_parent(3) # todo: not implemented why does this one fail???
879
+ my_parent 3
880
+ """
881
+ if self._element_constructor is None:
882
+ raise NotImplementedError(f"cannot construct elements of {self}")
883
+ cdef R = parent(x)
884
+ cdef bint no_extra_args = (not args and not kwds)
885
+ if R is self and no_extra_args:
886
+ return x
887
+
888
+ # Here we inline the first part of convert_map_from for speed.
889
+ # (Yes, the virtual function overhead can matter.)
890
+ if self._convert_from_hash is None: # this is because parent.__init__() does not always get called
891
+ self.init_coerce()
892
+ cdef map.Map mor
893
+ try:
894
+ mor = <map.Map> self._convert_from_hash.get(R)
895
+ except KeyError:
896
+ mor = <map.Map> self._internal_convert_map_from(R)
897
+
898
+ if mor is not None:
899
+ if no_extra_args:
900
+ return mor._call_(x)
901
+ else:
902
+ return mor._call_with_args(x, args, kwds)
903
+
904
+ raise TypeError(_LazyString("No conversion defined from %s to %s", (R, self), {}))
905
+
906
+ def __mul__(self, x):
907
+ """
908
+ This is a multiplication method that more or less directly
909
+ calls another attribute ``_mul_`` (single underscore). This
910
+ is because ``__mul__`` cannot be implemented via inheritance
911
+ from the parent methods of the category, but ``_mul_`` can
912
+ be inherited. This is, e.g., used when creating twosided
913
+ ideals of matrix algebras. See :issue:`7797`.
914
+
915
+ EXAMPLES::
916
+
917
+ sage: MS = MatrixSpace(QQ, 2, 2) # needs sage.modules
918
+
919
+ This matrix space is in fact an algebra, and in particular
920
+ it is a ring, from the point of view of categories::
921
+
922
+ sage: MS.category() # needs sage.modules
923
+ Category of infinite finite dimensional algebras with basis
924
+ over (number fields and quotient fields and metric spaces)
925
+ sage: MS in Rings() # needs sage.modules
926
+ True
927
+
928
+ However, its class does not inherit from the base class
929
+ ``Ring``::
930
+
931
+ sage: isinstance(MS, Ring) # needs sage.modules
932
+ False
933
+
934
+ Its ``_mul_`` method is inherited from the category, and
935
+ can be used to create a left or right ideal::
936
+
937
+ sage: # needs sage.modules
938
+ sage: MS._mul_.__module__
939
+ 'sage.categories.rings'
940
+ sage: MS * MS.1 # indirect doctest
941
+ Left Ideal
942
+ (
943
+ [0 1]
944
+ [0 0]
945
+ )
946
+ of Full MatrixSpace of 2 by 2 dense matrices over Rational Field
947
+ sage: MS * [MS.1, 2]
948
+ Left Ideal
949
+ (
950
+ [0 1]
951
+ [0 0],
952
+ <BLANKLINE>
953
+ [2 0]
954
+ [0 2]
955
+ )
956
+ of Full MatrixSpace of 2 by 2 dense matrices over Rational Field
957
+ sage: MS.1 * MS
958
+ Right Ideal
959
+ (
960
+ [0 1]
961
+ [0 0]
962
+ )
963
+ of Full MatrixSpace of 2 by 2 dense matrices over Rational Field
964
+ sage: [MS.1, 2] * MS
965
+ Right Ideal
966
+ (
967
+ [0 1]
968
+ [0 0],
969
+ <BLANKLINE>
970
+ [2 0]
971
+ [0 2]
972
+ )
973
+ of Full MatrixSpace of 2 by 2 dense matrices over Rational Field
974
+ """
975
+ # generic multiplication method. It defers to
976
+ # _mul_, which may be defined via categories.
977
+ _mul_ = None
978
+ switch = False
979
+ try:
980
+ if isinstance(self, Parent):
981
+ _mul_ = self._mul_
982
+ except AttributeError:
983
+ pass
984
+ if _mul_ is None:
985
+ try:
986
+ if isinstance(x, Parent):
987
+ _mul_ = x._mul_
988
+ switch = True
989
+ except AttributeError:
990
+ pass
991
+ if _mul_ is None:
992
+ raise TypeError(_LazyString("For implementing multiplication, provide the method '_mul_' for %s resp. %s", (self, x), {}))
993
+ if switch:
994
+ return _mul_(self, switch_sides=True)
995
+ return _mul_(x)
996
+
997
+ def __pow__(self, x, mod):
998
+ """
999
+ Power function.
1000
+
1001
+ The default implementation of ``__pow__`` on parent redirects to the
1002
+ super class (in case of multiple inheritance) or to the category. This
1003
+ redirection is necessary when the parent is a Cython class (aka
1004
+ extension class) because in that case the parent class does not inherit
1005
+ from the ``ParentMethods`` of the category.
1006
+
1007
+ Concrete implementations of parents can freely overwrite this default
1008
+ method.
1009
+
1010
+ TESTS::
1011
+
1012
+ sage: # needs sage.modules
1013
+ sage: ZZ^3
1014
+ Ambient free module of rank 3 over the principal ideal domain
1015
+ Integer Ring
1016
+ sage: QQ^3
1017
+ Vector space of dimension 3 over Rational Field
1018
+ sage: QQ['x']^3
1019
+ Ambient free module of rank 3 over the principal ideal domain
1020
+ Univariate Polynomial Ring in x over Rational Field
1021
+ sage: IntegerModRing(6)^3
1022
+ Ambient free module of rank 3 over Ring of integers modulo 6
1023
+
1024
+ sage: 3^ZZ
1025
+ Traceback (most recent call last):
1026
+ ...
1027
+ TypeError: unsupported operand parent(s) for ^: 'Integer Ring' and '<class 'sage.rings.integer_ring.IntegerRing_class'>'
1028
+ sage: Partitions(3)^3 # needs sage.modules
1029
+ Traceback (most recent call last):
1030
+ ...
1031
+ TypeError: unsupported operand type(s) for ** or pow(): 'Partitions_n_with_category' and 'int'
1032
+
1033
+ Check multiple inheritance::
1034
+
1035
+ sage: class A:
1036
+ ....: def __pow__(self, n):
1037
+ ....: return 'Apow'
1038
+ sage: class MyParent(A, Parent):
1039
+ ....: pass
1040
+ sage: MyParent()^2
1041
+ 'Apow'
1042
+ """
1043
+ if mod is not None or not isinstance(self, Parent):
1044
+ return NotImplemented
1045
+ try:
1046
+ # get __pow__ from super class
1047
+ meth = super().__pow__
1048
+ except AttributeError:
1049
+ # get __pow__ from category in case the parent is a Cython class
1050
+ try:
1051
+ meth = (<Parent> self).getattr_from_category('__pow__')
1052
+ except AttributeError:
1053
+ return NotImplemented
1054
+ return meth(x)
1055
+
1056
+ #############################################################################
1057
+ # Containment testing
1058
+ #############################################################################
1059
+ def __contains__(self, x):
1060
+ r"""
1061
+ ``True`` if there is an element of ``self`` that is equal to ``x``
1062
+ under ``==``, or if ``x`` is already an element of ``self``. Also,
1063
+ ``True`` in other cases involving the Symbolic Ring, which is handled
1064
+ specially.
1065
+
1066
+ For many structures we test this by using :meth:`__call__` and
1067
+ then testing equality between ``x`` and the result.
1068
+
1069
+ The Symbolic Ring is treated differently because it is
1070
+ ultra-permissive about letting other rings coerce in, but
1071
+ ultra-strict about doing comparisons.
1072
+
1073
+ EXAMPLES::
1074
+
1075
+ sage: 2 in Integers(7)
1076
+ True
1077
+ sage: 2 in ZZ
1078
+ True
1079
+ sage: Integers(7)(3) in ZZ
1080
+ True
1081
+ sage: 3/1 in ZZ
1082
+ True
1083
+ sage: 5 in QQ
1084
+ True
1085
+ sage: I in RR # needs sage.rings.real_mpfr sage.symbolic
1086
+ False
1087
+ sage: RIF(1, 2) in RIF # needs sage.rings.real_interval_field
1088
+ True
1089
+
1090
+ sage: # needs sage.symbolic
1091
+ sage: SR(2) in ZZ
1092
+ True
1093
+ sage: pi in RIF # there is no element of RIF equal to pi
1094
+ False
1095
+ sage: sqrt(2) in CC
1096
+ True
1097
+ sage: pi in RR
1098
+ True
1099
+ sage: pi in CC
1100
+ True
1101
+ sage: pi in RDF
1102
+ True
1103
+ sage: pi in CDF
1104
+ True
1105
+
1106
+ Note that we have
1107
+
1108
+ ::
1109
+
1110
+ sage: 3/2 in RIF # needs sage.rings.real_interval_field
1111
+ True
1112
+
1113
+ because ``3/2`` has an exact representation in ``RIF`` (i.e. can be
1114
+ represented as an interval that contains exactly one value)::
1115
+
1116
+ sage: RIF(3/2).is_exact() # needs sage.rings.real_interval_field
1117
+ True
1118
+
1119
+ On the other hand, we have
1120
+
1121
+ ::
1122
+
1123
+ sage: 2/3 in RIF # needs sage.rings.real_interval_field
1124
+ False
1125
+
1126
+ because ``2/3`` has no exact representation in ``RIF``. Since
1127
+ ``RIF(2/3)`` is a nontrivial interval, it cannot be equal to anything
1128
+ (not even itself)::
1129
+
1130
+ sage: RIF(2/3).is_exact() # needs sage.rings.real_interval_field
1131
+ False
1132
+ sage: RIF(2/3).endpoints() # needs sage.rings.real_interval_field
1133
+ (0.666666666666666, 0.666666666666667)
1134
+ sage: RIF(2/3) == RIF(2/3) # needs sage.rings.real_interval_field
1135
+ False
1136
+
1137
+ TESTS:
1138
+
1139
+ Check that :issue:`13824` is fixed::
1140
+
1141
+ sage: 4/3 in GF(3)
1142
+ False
1143
+ sage: 15/50 in GF(25, 'a') # needs sage.rings.finite_rings
1144
+ False
1145
+ sage: 7/4 in Integers(4)
1146
+ False
1147
+ sage: 15/36 in Integers(6)
1148
+ False
1149
+
1150
+ Check that :issue:`32078` is fixed::
1151
+
1152
+ sage: P = Frac(ZZ['x,y'])
1153
+ sage: P(1) in ZZ # needs sage.libs.singular
1154
+ True
1155
+ sage: P(1/2) in ZZ # needs sage.libs.singular
1156
+ False
1157
+
1158
+ Check that :issue:`24209` is fixed::
1159
+
1160
+ sage: I in QQbar # needs sage.rings.number_field
1161
+ True
1162
+ sage: sqrt(-1) in QQbar # needs sage.rings.number_field sage.symbolic
1163
+ True
1164
+ """
1165
+ P = parent(x)
1166
+ if P is self or P == self:
1167
+ return True
1168
+ try:
1169
+ x2 = self(x)
1170
+ EQ = (x2 == x)
1171
+ if EQ is True:
1172
+ return True
1173
+ elif EQ is False:
1174
+ return False
1175
+ elif EQ:
1176
+ return True
1177
+ else:
1178
+ from sage.structure.element import Expression
1179
+ return isinstance(EQ, Expression)
1180
+ # if comparing gives an Expression, then it must be an equation.
1181
+ # We return *true* here, even though the equation
1182
+ # EQ must have evaluated to False for us to get to
1183
+ # this point. The reason is because... in practice
1184
+ # SR is ultra-permissive about letting other rings
1185
+ # coerce in, but ultra-strict about doing
1186
+ # comparisons.
1187
+ except (TypeError, ValueError, ArithmeticError):
1188
+ return False
1189
+
1190
+ cpdef coerce(self, x):
1191
+ """
1192
+ Return x as an element of ``self``, if and only if there is a
1193
+ canonical coercion from the parent of x to ``self``.
1194
+
1195
+ EXAMPLES::
1196
+
1197
+ sage: QQ.coerce(ZZ(2))
1198
+ 2
1199
+ sage: ZZ.coerce(QQ(2))
1200
+ Traceback (most recent call last):
1201
+ ...
1202
+ TypeError: no canonical coercion from Rational Field to Integer Ring
1203
+
1204
+ We make an exception for zero::
1205
+
1206
+ sage: V = GF(7)^7 # needs sage.modules
1207
+ sage: V.coerce(0) # needs sage.modules
1208
+ (0, 0, 0, 0, 0, 0, 0)
1209
+ """
1210
+ cdef R = parent(x)
1211
+ if R is self:
1212
+ return x
1213
+ mor = self._internal_coerce_map_from(R)
1214
+ if mor is None:
1215
+ if is_Integer(x) and not x:
1216
+ try:
1217
+ return self(0)
1218
+ except Exception:
1219
+ _record_exception()
1220
+ raise TypeError(_LazyString("no canonical coercion from %s to %s", (parent(x), self), {}))
1221
+ else:
1222
+ return (<map.Map>mor)._call_(x)
1223
+
1224
+ def __bool__(self):
1225
+ """
1226
+ By default, all Parents are treated as ``True`` when used in an if
1227
+ statement. Override this method if other behavior is desired
1228
+ (for example, for empty sets).
1229
+
1230
+ EXAMPLES::
1231
+
1232
+ sage: if ZZ: print("Yes")
1233
+ Yes
1234
+ """
1235
+ return True
1236
+
1237
+ # Should be moved and merged into the EnumeratedSets() category (#12955)
1238
+ def __getitem__(self, n):
1239
+ """
1240
+ Return the `n`-th item or slice `n` of ``self``,
1241
+ by getting ``self`` as a list.
1242
+
1243
+ EXAMPLES::
1244
+
1245
+ sage: VectorSpace(GF(7), 3)[:10] # needs sage.modules
1246
+ [(0, 0, 0),
1247
+ (1, 0, 0),
1248
+ (2, 0, 0),
1249
+ (3, 0, 0),
1250
+ (4, 0, 0),
1251
+ (5, 0, 0),
1252
+ (6, 0, 0),
1253
+ (0, 1, 0),
1254
+ (1, 1, 0),
1255
+ (2, 1, 0)]
1256
+
1257
+ TESTS:
1258
+
1259
+ We test the workaround described in :issue:`12956` to let categories
1260
+ override this default implementation::
1261
+
1262
+ sage: class As(Category):
1263
+ ....: def super_categories(self): return [Sets()]
1264
+ ....: class ParentMethods:
1265
+ ....: def __getitem__(self, n):
1266
+ ....: return 'coucou'
1267
+ sage: class A(Parent):
1268
+ ....: def __init__(self):
1269
+ ....: Parent.__init__(self, category=As())
1270
+ sage: a = A()
1271
+ sage: a[1]
1272
+ 'coucou'
1273
+ """
1274
+ try:
1275
+ meth = super().__getitem__
1276
+ except AttributeError:
1277
+ # needed when self is a Cython object
1278
+ try:
1279
+ meth = self.getattr_from_category('__getitem__')
1280
+ except AttributeError:
1281
+ return self.list()[n]
1282
+ return meth(n)
1283
+
1284
+ #########################################################################
1285
+ # Generators and Homomorphisms
1286
+ #########################################################################
1287
+
1288
+ def _is_valid_homomorphism_(self, codomain, im_gens, base_map=None):
1289
+ r"""
1290
+ Return ``True`` if ``im_gens`` defines a valid homomorphism
1291
+ from ``self`` to ``codomain``; otherwise return ``False``.
1292
+
1293
+ If determining whether or not a homomorphism is valid has not
1294
+ been implemented for this ring, then a :exc:`NotImplementedError`
1295
+ exception is raised.
1296
+ """
1297
+ raise NotImplementedError("Verification of correctness of homomorphisms from %s not yet implemented." % self)
1298
+
1299
+ def Hom(self, codomain, category=None):
1300
+ r"""
1301
+ Return the homspace ``Hom(self, codomain, category)``.
1302
+
1303
+ INPUT:
1304
+
1305
+ - ``codomain`` -- a parent
1306
+ - ``category`` -- a category or ``None`` (default: ``None``)
1307
+ If ``None``, the meet of the category of ``self`` and
1308
+ ``codomain`` is used.
1309
+
1310
+ OUTPUT:
1311
+
1312
+ The homspace of all homomorphisms from ``self`` to
1313
+ ``codomain`` in the category ``category``.
1314
+
1315
+ .. SEEALSO:: :func:`~sage.categories.homset.Hom`
1316
+
1317
+ EXAMPLES::
1318
+
1319
+ sage: R.<x,y> = PolynomialRing(QQ, 2)
1320
+ sage: R.Hom(QQ)
1321
+ Set of Homomorphisms from Multivariate Polynomial Ring in x, y over Rational Field to Rational Field
1322
+
1323
+ Homspaces are defined for very general Sage objects, even elements of familiar rings::
1324
+
1325
+ sage: n = 5; Hom(n,7)
1326
+ Set of Morphisms from 5 to 7 in Category of elements of Integer Ring
1327
+ sage: z=(2/3); Hom(z,8/1)
1328
+ Set of Morphisms from 2/3 to 8 in Category of elements of Rational Field
1329
+
1330
+ This example illustrates the optional third argument::
1331
+
1332
+ sage: QQ.Hom(ZZ, Sets())
1333
+ Set of Morphisms from Rational Field to Integer Ring in Category of sets
1334
+
1335
+ A parent may specify how to construct certain homsets by
1336
+ implementing a method :meth:`_Hom_`(codomain, category).
1337
+ See :func:`~sage.categories.homset.Hom` for details.
1338
+ """
1339
+ from sage.categories.homset import Hom
1340
+ return Hom(self, codomain, category)
1341
+
1342
+ def hom(self, im_gens, codomain=None, check=None, base_map=None, category=None, **kwds):
1343
+ r"""
1344
+ Return the unique homomorphism from ``self`` to ``codomain`` that
1345
+ sends ``self.gens()`` to the entries of ``im_gens``.
1346
+
1347
+ This raises a :exc:`TypeError` if there is no such homomorphism.
1348
+
1349
+ INPUT:
1350
+
1351
+ - ``im_gens`` -- the images in the codomain of the generators
1352
+ of this object under the homomorphism
1353
+
1354
+ - ``codomain`` -- the codomain of the homomorphism
1355
+
1356
+ - ``base_map`` -- a map from the base ring to the codomain; if not
1357
+ given, coercion is used
1358
+
1359
+ - ``check`` -- whether to verify that the images of generators
1360
+ extend to define a map (using only canonical coercions)
1361
+
1362
+ OUTPUT: a homomorphism ``self --> codomain``
1363
+
1364
+ .. NOTE::
1365
+
1366
+ As a shortcut, one can also give an object X instead of
1367
+ ``im_gens``, in which case return the (if it exists)
1368
+ natural map to X.
1369
+
1370
+ EXAMPLES:
1371
+
1372
+ Polynomial Ring: We first illustrate construction of a few
1373
+ homomorphisms involving a polynomial ring::
1374
+
1375
+ sage: R.<x> = PolynomialRing(ZZ)
1376
+ sage: f = R.hom([5], QQ)
1377
+ sage: f(x^2 - 19)
1378
+ 6
1379
+
1380
+ sage: R.<x> = PolynomialRing(QQ)
1381
+ sage: f = R.hom([5], GF(7))
1382
+ Traceback (most recent call last):
1383
+ ...
1384
+ ValueError: relations do not all (canonically) map to 0
1385
+ under map determined by images of generators
1386
+
1387
+ sage: # needs sage.rings.finite_rings
1388
+ sage: R.<x> = PolynomialRing(GF(7))
1389
+ sage: f = R.hom([3], GF(49,'a'))
1390
+ sage: f
1391
+ Ring morphism:
1392
+ From: Univariate Polynomial Ring in x over Finite Field of size 7
1393
+ To: Finite Field in a of size 7^2
1394
+ Defn: x |--> 3
1395
+ sage: f(x + 6)
1396
+ 2
1397
+ sage: f(x^2 + 1)
1398
+ 3
1399
+
1400
+ Natural morphism::
1401
+
1402
+ sage: f = ZZ.hom(GF(5))
1403
+ sage: f(7)
1404
+ 2
1405
+ sage: f
1406
+ Natural morphism:
1407
+ From: Integer Ring
1408
+ To: Finite Field of size 5
1409
+
1410
+ There might not be a natural morphism, in which case a
1411
+ :exc:`TypeError` is raised::
1412
+
1413
+ sage: QQ.hom(ZZ)
1414
+ Traceback (most recent call last):
1415
+ ...
1416
+ TypeError: natural coercion morphism from Rational Field to Integer Ring not defined
1417
+ """
1418
+ if isinstance(im_gens, Parent):
1419
+ return self.Hom(im_gens).natural_map()
1420
+ from sage.structure.sequence import Sequence_generic, Sequence
1421
+ if codomain is None:
1422
+ im_gens = Sequence(im_gens)
1423
+ codomain = im_gens.universe()
1424
+ if isinstance(im_gens, Sequence_generic):
1425
+ im_gens = list(im_gens)
1426
+ # Not all homsets accept category/check/base_map as arguments
1427
+ if check is not None:
1428
+ kwds['check'] = check
1429
+ if base_map is not None:
1430
+ # Ideally we would have machinery here to determine
1431
+ # how the base map affects the category of the resulting
1432
+ # morphism. But for now it's not clear how to do this,
1433
+ # so we leave the category as the default for now.
1434
+ kwds['base_map'] = base_map
1435
+ Hom_kwds = {} if category is None else {'category': category}
1436
+ return self.Hom(codomain, **Hom_kwds)(im_gens, **kwds)
1437
+
1438
+ #################################################################################
1439
+ # New Coercion support functionality
1440
+ #################################################################################
1441
+
1442
+ def _populate_coercion_lists_(self,
1443
+ coerce_list=[],
1444
+ action_list=[],
1445
+ convert_list=[],
1446
+ embedding=None,
1447
+ convert_method_name=None,
1448
+ element_constructor=None,
1449
+ init_no_parent=None,
1450
+ bint unpickling=False):
1451
+ """
1452
+ This function allows one to specify coercions, actions, conversions
1453
+ and embeddings involving this parent.
1454
+
1455
+ IT SHOULD ONLY BE CALLED DURING THE __INIT__ method, often at the end.
1456
+
1457
+ INPUT:
1458
+
1459
+ - ``coerce_list`` -- list of coercion Morphisms to ``self`` and
1460
+ parents with canonical coercions to ``self``
1461
+
1462
+ - ``action_list`` -- list of actions on and by ``self``
1463
+
1464
+ - ``convert_list`` -- list of conversion Maps to ``self`` and
1465
+ parents with conversions to ``self``
1466
+
1467
+ - ``embedding`` -- a single Morphism from ``self``
1468
+
1469
+ - ``convert_method_name`` -- a name to look for that other elements
1470
+ can implement to create elements of ``self`` (e.g. ``_integer_``)
1471
+
1472
+ - ``init_no_parent`` -- if ``True`` omit passing ``self`` in as the
1473
+ first argument of element_constructor for conversion. This
1474
+ is useful if parents are unique, or element_constructor is a
1475
+ bound method (this latter case can be detected automatically).
1476
+ """
1477
+ self.init_coerce(False)
1478
+
1479
+ if not unpickling:
1480
+ if element_constructor is not None:
1481
+ raise ValueError("element_constructor can only be given when unpickling is True")
1482
+ try:
1483
+ element_constructor = self._element_constructor_
1484
+ except AttributeError:
1485
+ raise RuntimeError("an _element_constructor_ method must be defined")
1486
+ self._element_constructor = element_constructor
1487
+ self._element_init_pass_parent = guess_pass_parent(self, element_constructor)
1488
+
1489
+ if not isinstance(coerce_list, list):
1490
+ raise ValueError(_LazyString("%s_populate_coercion_lists_: coerce_list is type %s, must be list", (type(coerce_list), type(self)), {}))
1491
+ if not isinstance(action_list, list):
1492
+ raise ValueError(_LazyString("%s_populate_coercion_lists_: action_list is type %s, must be list", (type(action_list), type(self)), {}))
1493
+ if not isinstance(convert_list, list):
1494
+ raise ValueError(_LazyString("%s_populate_coercion_lists_: convert_list is type %s, must be list", (type(convert_list), type(self)), {}))
1495
+
1496
+ self._initial_coerce_list = copy(coerce_list)
1497
+ self._initial_action_list = copy(action_list)
1498
+ self._initial_convert_list = copy(convert_list)
1499
+
1500
+ self._convert_method_name = convert_method_name
1501
+ if init_no_parent is not None:
1502
+ self._element_init_pass_parent = not init_no_parent
1503
+
1504
+ for mor in coerce_list:
1505
+ self.register_coercion(mor)
1506
+ for action in action_list:
1507
+ self.register_action(action)
1508
+ for mor in convert_list:
1509
+ self.register_conversion(mor)
1510
+ if embedding is not None:
1511
+ self.register_embedding(embedding)
1512
+
1513
+ def _unset_coercions_used(self):
1514
+ r"""
1515
+ Pretend that this parent has never been interrogated by the coercion
1516
+ model, so that it is possible to add coercions, conversions, and
1517
+ actions. Does not remove any existing embedding.
1518
+
1519
+ WARNING::
1520
+
1521
+ For internal use only!
1522
+ """
1523
+ self._coercions_used = False
1524
+ coercion_model.reset_cache()
1525
+
1526
+ def _unset_embedding(self):
1527
+ r"""
1528
+ Pretend that this parent has never been interrogated by the
1529
+ coercion model, and remove any existing embedding.
1530
+
1531
+ WARNING::
1532
+
1533
+ This does *not* make it safe to add an entirely new embedding! It
1534
+ is possible that a `Parent` has cached information about the
1535
+ existing embedding; that cached information *is not* removed by
1536
+ this call.
1537
+
1538
+ For internal use only!
1539
+ """
1540
+ self._embedding = None
1541
+ self._unset_coercions_used()
1542
+
1543
+ def _is_coercion_cached(self, domain):
1544
+ r"""
1545
+ Test whether the coercion from ``domain`` is already cached.
1546
+
1547
+ EXAMPLES::
1548
+
1549
+ sage: R.<XX> = QQ
1550
+ sage: R._remove_from_coerce_cache(QQ)
1551
+ sage: R._is_coercion_cached(QQ)
1552
+ False
1553
+ sage: _ = R.coerce_map_from(QQ)
1554
+ sage: R._is_coercion_cached(QQ)
1555
+ True
1556
+ """
1557
+ return domain in self._coerce_from_hash
1558
+
1559
+ def _is_conversion_cached(self, domain):
1560
+ r"""
1561
+ Test whether the conversion from ``domain`` is already set.
1562
+
1563
+ EXAMPLES::
1564
+
1565
+ sage: P = Parent()
1566
+ sage: P._is_conversion_cached(P)
1567
+ False
1568
+ sage: P.convert_map_from(P)
1569
+ Identity endomorphism of <sage.structure.parent.Parent object at ...>
1570
+ sage: P._is_conversion_cached(P)
1571
+ True
1572
+ """
1573
+ return domain in self._convert_from_hash
1574
+
1575
+ def _remove_from_coerce_cache(self, domain):
1576
+ r"""
1577
+ Remove the coercion and the conversion from ``domain`` to ``self`` from
1578
+ the cache.
1579
+
1580
+ EXAMPLES::
1581
+
1582
+ sage: R.<XX> = QQ
1583
+ sage: R._remove_from_coerce_cache(QQ)
1584
+ sage: R._is_coercion_cached(QQ)
1585
+ False
1586
+ sage: _ = R.coerce_map_from(QQ)
1587
+ sage: R._is_coercion_cached(QQ)
1588
+ True
1589
+ sage: R._remove_from_coerce_cache(QQ)
1590
+ sage: R._is_coercion_cached(QQ)
1591
+ False
1592
+ sage: R._is_conversion_cached(QQ)
1593
+ False
1594
+ """
1595
+ try:
1596
+ del self._coerce_from_hash[domain]
1597
+ except KeyError:
1598
+ pass
1599
+ try:
1600
+ del self._convert_from_hash[domain]
1601
+ except KeyError:
1602
+ pass
1603
+
1604
+ cpdef register_coercion(self, mor):
1605
+ r"""
1606
+ Update the coercion model to use `mor : P \to \text{self}` to coerce
1607
+ from a parent ``P`` into ``self``.
1608
+
1609
+ For safety, an error is raised if another coercion has already
1610
+ been registered or discovered between ``P`` and ``self``.
1611
+
1612
+ EXAMPLES::
1613
+
1614
+ sage: K.<a> = ZZ['a']
1615
+ sage: L.<b> = ZZ['b']
1616
+ sage: L_into_K = L.hom([-a]) # non-trivial automorphism
1617
+ sage: K.register_coercion(L_into_K)
1618
+
1619
+ sage: K(0) + b
1620
+ -a
1621
+ sage: a + b
1622
+ 0
1623
+ sage: K(b) # check that convert calls coerce first; normally this is just a
1624
+ -a
1625
+
1626
+ sage: L(0) + a in K # this goes through the coercion mechanism of K
1627
+ True
1628
+ sage: L(a) in L # this still goes through the convert mechanism of L
1629
+ True
1630
+
1631
+ sage: K.register_coercion(L_into_K)
1632
+ Traceback (most recent call last):
1633
+ ...
1634
+ AssertionError: coercion from Univariate Polynomial Ring in b over Integer Ring to Univariate Polynomial Ring in a over Integer Ring already registered or discovered
1635
+
1636
+ TESTS:
1637
+
1638
+ We check that :issue:`29517` has been fixed::
1639
+
1640
+ sage: A.<x> = ZZ[]
1641
+ sage: B.<y> = ZZ[]
1642
+ sage: B.has_coerce_map_from(A)
1643
+ False
1644
+ sage: B.register_coercion(A.hom([y]))
1645
+ sage: x + y
1646
+ 2*y
1647
+ """
1648
+ if isinstance(mor, map.Map):
1649
+ if mor.codomain() is not self:
1650
+ raise ValueError(_LazyString("Map's codomain must be self (%s) is not (%s)", (self, mor.codomain()), {}))
1651
+ elif isinstance(mor, (type, Parent)):
1652
+ mor = self._generic_coerce_map(mor)
1653
+ else:
1654
+ raise TypeError(_LazyString("coercions must be parents or maps (got %s)", (mor,), {}))
1655
+ D = mor.domain()
1656
+
1657
+ assert not (self._coercions_used and D in self._coerce_from_hash and
1658
+ self._coerce_from_hash.get(D) is not None), "coercion from {} to {} already registered or discovered".format(D, self)
1659
+ assert not (self._coercions_used and D in self._convert_from_hash), "conversion from %s to %s already registered or discovered" % (D, self)
1660
+
1661
+ mor._is_coercion = True
1662
+ self._coerce_from_list.append(mor)
1663
+ self._registered_domains.append(D)
1664
+ self._coerce_from_hash.set(D, mor)
1665
+
1666
+ cpdef register_action(self, action):
1667
+ r"""
1668
+ Update the coercion model to use ``action`` to act on ``self``.
1669
+
1670
+ ``action`` should be of type ``sage.categories.action.Action``.
1671
+
1672
+ EXAMPLES::
1673
+
1674
+ sage: import sage.categories.action
1675
+ sage: import operator
1676
+
1677
+ sage: class SymmetricGroupAction(sage.categories.action.Action):
1678
+ ....: "Act on a multivariate polynomial ring by permuting the generators."
1679
+ ....: def __init__(self, G, M, is_left=True):
1680
+ ....: sage.categories.action.Action.__init__(self, G, M, is_left, operator.mul)
1681
+ ....:
1682
+ ....: def _act_(self, g, a):
1683
+ ....: D = {}
1684
+ ....: for k, v in a.monomial_coefficients().items():
1685
+ ....: nk = [0]*len(k)
1686
+ ....: for i in range(len(k)):
1687
+ ....: nk[g(i+1)-1] = k[i]
1688
+ ....: D[tuple(nk)] = v
1689
+ ....: return a.parent()(D)
1690
+
1691
+ sage: # needs sage.groups
1692
+ sage: R.<x, y, z> = QQ['x, y, z']
1693
+ sage: G = SymmetricGroup(3)
1694
+ sage: act = SymmetricGroupAction(G, R)
1695
+ sage: t = x + 2*y + 3*z
1696
+
1697
+ sage: # needs sage.groups
1698
+ sage: act(G((1, 2)), t)
1699
+ 2*x + y + 3*z
1700
+ sage: act(G((2, 3)), t)
1701
+ x + 3*y + 2*z
1702
+ sage: act(G((1, 2, 3)), t)
1703
+ 3*x + y + 2*z
1704
+
1705
+ This should fail, since we have not registered the left
1706
+ action::
1707
+
1708
+ sage: G((1,2)) * t # needs sage.groups
1709
+ Traceback (most recent call last):
1710
+ ...
1711
+ TypeError: ...
1712
+
1713
+ Now let's make it work::
1714
+
1715
+ sage: # needs sage.groups
1716
+ sage: R._unset_coercions_used()
1717
+ sage: R.register_action(act)
1718
+ sage: G((1, 2)) * t
1719
+ 2*x + y + 3*z
1720
+ """
1721
+ if self._coercions_used:
1722
+ raise RuntimeError("actions and coercions must be registered before use")
1723
+ from sage.categories.action import Action
1724
+ if not isinstance(action, Action):
1725
+ raise TypeError("actions must be actions")
1726
+ if action.actor() is not self and action.domain() is not self:
1727
+ raise ValueError("action must involve self")
1728
+ self._action_list.append(action)
1729
+
1730
+ cpdef register_conversion(self, mor):
1731
+ r"""
1732
+ Update the coercion model to use `\text{mor} : P \to \text{self}` to convert
1733
+ from ``P`` into ``self``.
1734
+
1735
+ EXAMPLES::
1736
+
1737
+ sage: K.<a> = ZZ['a']
1738
+ sage: M.<c> = ZZ['c']
1739
+ sage: M_into_K = M.hom([a]) # trivial automorphism
1740
+ sage: K._unset_coercions_used()
1741
+ sage: K.register_conversion(M_into_K)
1742
+
1743
+ sage: K(c)
1744
+ a
1745
+ sage: K(0) + c
1746
+ Traceback (most recent call last):
1747
+ ...
1748
+ TypeError: ...
1749
+ """
1750
+ assert not (self._coercions_used and mor.domain() in self._convert_from_hash), "conversion from %s to %s already registered or discovered" % (mor.domain(), self)
1751
+ if isinstance(mor, map.Map):
1752
+ if mor.codomain() is not self:
1753
+ raise ValueError("Map's codomain must be self")
1754
+ self._convert_from_list.append(mor)
1755
+ self._convert_from_hash.set(mor.domain(), mor)
1756
+ elif isinstance(mor, (Parent, type)):
1757
+ t = mor
1758
+ mor = self._generic_convert_map(mor)
1759
+ self._convert_from_list.append(mor)
1760
+ self._convert_from_hash.set(t, mor)
1761
+ self._convert_from_hash.set(mor.domain(), mor)
1762
+ else:
1763
+ raise TypeError("conversions must be parents or maps")
1764
+
1765
+ cpdef register_embedding(self, embedding):
1766
+ r"""
1767
+ Add embedding to coercion model.
1768
+
1769
+ This method updates the coercion model to use
1770
+ `\text{embedding} : \text{self} \to P` to embed ``self`` into
1771
+ the parent ``P``.
1772
+
1773
+ There can only be one embedding registered; it can only be registered
1774
+ once; and it must be registered before using this parent in the
1775
+ coercion model.
1776
+
1777
+ EXAMPLES::
1778
+
1779
+ sage: S3 = AlternatingGroup(3) # needs sage.groups
1780
+ sage: G = SL(3, QQ) # needs sage.groups sage.modules
1781
+ sage: p = S3[2]; p.matrix() # needs sage.groups sage.modules
1782
+ [0 0 1]
1783
+ [1 0 0]
1784
+ [0 1 0]
1785
+
1786
+ In general one cannot mix matrices and permutations::
1787
+
1788
+ sage: # needs sage.groups sage.modules
1789
+ sage: G(p)
1790
+ Traceback (most recent call last):
1791
+ ...
1792
+ TypeError: unable to convert (1,3,2) to a rational
1793
+ sage: phi = S3.hom(lambda p: G(p.matrix()), codomain=G)
1794
+ sage: phi(p)
1795
+ [0 0 1]
1796
+ [1 0 0]
1797
+ [0 1 0]
1798
+ sage: S3._unset_coercions_used()
1799
+ sage: S3.register_embedding(phi)
1800
+
1801
+ By :issue:`14711`, coerce maps should be copied when using outside of
1802
+ the coercion system::
1803
+
1804
+ sage: phi = copy(S3.coerce_embedding()); phi # needs sage.groups sage.modules
1805
+ Generic morphism:
1806
+ From: Alternating group of order 3!/2 as a permutation group
1807
+ To: Special Linear Group of degree 3 over Rational Field
1808
+ sage: phi(p) # needs sage.groups sage.modules
1809
+ [0 0 1]
1810
+ [1 0 0]
1811
+ [0 1 0]
1812
+
1813
+ This does not work since matrix groups are still old-style
1814
+ parents (see :issue:`14014`)::
1815
+
1816
+ sage: G(p) # not implemented # needs sage.groups
1817
+
1818
+ Though one can have a permutation act on the rows of a matrix::
1819
+
1820
+ sage: G(1) * p # needs sage.groups sage.modules
1821
+ [0 0 1]
1822
+ [1 0 0]
1823
+ [0 1 0]
1824
+
1825
+ Some more advanced examples::
1826
+
1827
+ sage: # needs sage.rings.number_field
1828
+ sage: x = QQ['x'].0
1829
+ sage: t = abs(ZZ.random_element(10^6))
1830
+ sage: K = NumberField(x^2 + 2*3*7*11, "a"+str(t))
1831
+ sage: a = K.gen()
1832
+ sage: K_into_MS = K.hom([a.matrix()])
1833
+ sage: K._unset_coercions_used()
1834
+ sage: K.register_embedding(K_into_MS)
1835
+
1836
+ sage: # needs sage.rings.number_field
1837
+ sage: L = NumberField(x^2 + 2*3*7*11*19*31,
1838
+ ....: "b" + str(abs(ZZ.random_element(10^6))))
1839
+ sage: b = L.gen()
1840
+ sage: L_into_MS = L.hom([b.matrix()])
1841
+ sage: L._unset_coercions_used()
1842
+ sage: L.register_embedding(L_into_MS)
1843
+
1844
+ sage: K.coerce_embedding()(a) # needs sage.rings.number_field
1845
+ [ 0 1]
1846
+ [-462 0]
1847
+ sage: L.coerce_embedding()(b) # needs sage.rings.number_field
1848
+ [ 0 1]
1849
+ [-272118 0]
1850
+
1851
+ sage: a.matrix() * b.matrix() # needs sage.rings.number_field
1852
+ [-272118 0]
1853
+ [ 0 -462]
1854
+ sage: a.matrix() * b.matrix() # needs sage.rings.number_field
1855
+ [-272118 0]
1856
+ [ 0 -462]
1857
+ """
1858
+ assert not self._coercions_used, "coercions must all be registered up before use"
1859
+ assert self._embedding is None, "only one embedding allowed"
1860
+
1861
+ if isinstance(embedding, map.Map):
1862
+ if embedding.domain() is not self:
1863
+ raise ValueError("embedding's domain must be self")
1864
+ self._embedding = embedding
1865
+ elif isinstance(embedding, Parent):
1866
+ self._embedding = embedding._generic_coerce_map(self)
1867
+ elif embedding is not None:
1868
+ raise TypeError("embedding must be a parent or map")
1869
+ self._embedding._make_weak_references()
1870
+
1871
+ def coerce_embedding(self):
1872
+ """
1873
+ Return the embedding of ``self`` into some other parent, if such a
1874
+ parent exists.
1875
+
1876
+ This does not mean that there are no coercion maps from ``self`` into
1877
+ other fields, this is simply a specific morphism specified out of
1878
+ ``self`` and usually denotes a special relationship (e.g. sub-objects,
1879
+ choice of completion, etc.)
1880
+
1881
+ EXAMPLES::
1882
+
1883
+ sage: # needs sage.rings.number_field
1884
+ sage: x = polygen(ZZ, 'x')
1885
+ sage: K.<a> = NumberField(x^3 + x^2 + 1, embedding=1)
1886
+ sage: K.coerce_embedding()
1887
+ Generic morphism:
1888
+ From: Number Field in a with defining polynomial x^3 + x^2 + 1
1889
+ with a = -1.465571231876768?
1890
+ To: Real Lazy Field
1891
+ Defn: a -> -1.465571231876768?
1892
+ sage: K.<a> = NumberField(x^3 + x^2 + 1, embedding=CC.gen())
1893
+ sage: K.coerce_embedding()
1894
+ Generic morphism:
1895
+ From: Number Field in a with defining polynomial x^3 + x^2 + 1
1896
+ with a = 0.2327856159383841? + 0.7925519925154479?*I
1897
+ To: Complex Lazy Field
1898
+ Defn: a -> 0.2327856159383841? + 0.7925519925154479?*I
1899
+ """
1900
+ return copy(self._embedding) # It might be overkill to make a copy here
1901
+
1902
+ cpdef _generic_coerce_map(self, S):
1903
+ r"""
1904
+ Return a default coercion map based on the data provided to
1905
+ :meth:`_populate_coercion_lists_`.
1906
+
1907
+ This method differs from :meth:`_generic_convert_map` only in setting
1908
+ the category for the map to the meet of the category of this parent
1909
+ and ``S``.
1910
+
1911
+ EXAMPLES::
1912
+
1913
+ sage: QQ['x']._generic_coerce_map(ZZ)
1914
+ Conversion map:
1915
+ From: Integer Ring
1916
+ To: Univariate Polynomial Ring in x over Rational Field
1917
+
1918
+ TESTS:
1919
+
1920
+ We check that :issue:`23184` has been resolved::
1921
+
1922
+ sage: QQ['x', 'y']._generic_coerce_map(QQ).category_for()
1923
+ Category of infinite unique factorization domains
1924
+ sage: QQ[['x']].coerce_map_from(QQ).category_for()
1925
+ Category of euclidean domains
1926
+ """
1927
+ if isinstance(S, type):
1928
+ category = None
1929
+ else:
1930
+ category = self.category()._meet_(S.category())
1931
+ return self._generic_convert_map(S, category=category)
1932
+
1933
+ cpdef _generic_convert_map(self, S, category=None):
1934
+ r"""
1935
+ Return the default conversion map based on the data provided to
1936
+ :meth:`_populate_coercion_lists_`.
1937
+
1938
+ This is called when :meth:`_coerce_map_from_` returns ``True``.
1939
+
1940
+ If a ``convert_method_name`` is provided, it creates a
1941
+ ``NamedConvertMap``, otherwise it creates a
1942
+ ``DefaultConvertMap`` or ``DefaultConvertMap_unique``
1943
+ depending on whether or not init_no_parent is set.
1944
+
1945
+ EXAMPLES::
1946
+
1947
+ sage: QQ['x']._generic_convert_map(SR) # needs sage.symbolic
1948
+ Conversion via _polynomial_ method map:
1949
+ From: Symbolic Ring
1950
+ To: Univariate Polynomial Ring in x over Rational Field
1951
+ sage: GF(11)._generic_convert_map(GF(7))
1952
+ Conversion map:
1953
+ From: Finite Field of size 7
1954
+ To: Finite Field of size 11
1955
+ sage: ZZ._generic_convert_map(RDF)
1956
+ Conversion via _integer_ method map:
1957
+ From: Real Double Field
1958
+ To: Integer Ring
1959
+
1960
+ TESTS:
1961
+
1962
+ We check that :issue:`23184` has been resolved::
1963
+
1964
+ sage: QQ[['x']].coerce_map_from(QQ).category_for()
1965
+ Category of euclidean domains
1966
+ """
1967
+ m = self._convert_method_name
1968
+ if m is not None:
1969
+ f = self.convert_method_map(S, m)
1970
+ if f is not None:
1971
+ return f
1972
+ if self._element_init_pass_parent:
1973
+ # deprecation(26879)
1974
+ return DefaultConvertMap(S, self, category=category)
1975
+ else:
1976
+ return DefaultConvertMap_unique(S, self, category=category)
1977
+
1978
+ def _convert_method_map(self, S, method_name=None):
1979
+ """
1980
+ Return a map to convert from ``S`` to ``self`` using a convert
1981
+ method like ``_integer_`` on elements of ``S``.
1982
+
1983
+ OUTPUT: either an instance of :class:`NamedConvertMap` or
1984
+ ``None`` if ``S`` does not have the method.
1985
+ """
1986
+ # NOTE: in Cython code, call convert_method_map() directly
1987
+ if method_name is None:
1988
+ method_name = self._convert_method_name
1989
+ return self.convert_method_map(S, method_name)
1990
+
1991
+ cdef convert_method_map(self, S, method_name):
1992
+ # Cython implementation of _convert_method_map()
1993
+ cdef Parent P
1994
+ if isinstance(S, Parent):
1995
+ P = <Parent>S
1996
+ try:
1997
+ element_cls = P.Element
1998
+ except AttributeError:
1999
+ element_cls = type(P.an_element())
2000
+ else:
2001
+ element_cls = S
2002
+ if hasattr(element_cls, method_name):
2003
+ return NamedConvertMap(S, self, method_name)
2004
+ else:
2005
+ return None
2006
+
2007
+ def _coerce_map_via(self, v, S):
2008
+ """
2009
+ This attempts to construct a morphism from ``S`` to ``self`` by passing
2010
+ through one of the items in ``v`` (tried in order).
2011
+
2012
+ ``S`` may appear in the list, in which case algorithm will never
2013
+ progress beyond that point.
2014
+
2015
+ This is useful when defining ``_coerce_map_from_``.
2016
+
2017
+ INPUT:
2018
+
2019
+ - ``v`` -- list (iterator) of parents with coercions into ``self``;
2020
+ there *must* be maps provided from each item in the list to ``self``
2021
+
2022
+ - ``S`` -- the starting parent
2023
+
2024
+ EXAMPLES:
2025
+
2026
+ By :issue:`14711`, coerce maps should be copied for usage outside
2027
+ of the coercion system::
2028
+
2029
+ sage: copy(CDF._coerce_map_via([ZZ, RR, CC], int)) # needs sage.rings.complex_double
2030
+ Composite map:
2031
+ From: Set of Python objects of class 'int'
2032
+ To: Complex Double Field
2033
+ Defn: Native morphism:
2034
+ From: Set of Python objects of class 'int'
2035
+ To: Integer Ring
2036
+ then
2037
+ Native morphism:
2038
+ From: Integer Ring
2039
+ To: Complex Double Field
2040
+
2041
+ sage: copy(CDF._coerce_map_via([ZZ, RR, CC], QQ)) # needs sage.rings.complex_double
2042
+ Composite map:
2043
+ From: Rational Field
2044
+ To: Complex Double Field
2045
+ Defn: Generic map:
2046
+ From: Rational Field
2047
+ To: Real Field with 53 bits of precision
2048
+ then
2049
+ Native morphism:
2050
+ From: Real Field with 53 bits of precision
2051
+ To: Complex Double Field
2052
+
2053
+ sage: copy(CDF._coerce_map_via([ZZ, RR, CC], CC)) # needs sage.rings.complex_double
2054
+ Generic map:
2055
+ From: Complex Field with 53 bits of precision
2056
+ To: Complex Double Field
2057
+ """
2058
+ cdef Parent R
2059
+ for R in v:
2060
+ if R is None:
2061
+ continue
2062
+ if R is S:
2063
+ return self._internal_coerce_map_from(R)
2064
+ connecting = R._internal_coerce_map_from(S)
2065
+ if connecting is not None:
2066
+ return self._internal_coerce_map_from(R) * connecting
2067
+
2068
+ cpdef bint has_coerce_map_from(self, S) except -2:
2069
+ """
2070
+ Return ``True`` if there is a natural map from ``S`` to ``self``.
2071
+ Otherwise, return ``False``.
2072
+
2073
+ EXAMPLES::
2074
+
2075
+ sage: RDF.has_coerce_map_from(QQ)
2076
+ True
2077
+ sage: RDF.has_coerce_map_from(QQ['x'])
2078
+ False
2079
+ sage: RDF['x'].has_coerce_map_from(QQ['x'])
2080
+ True
2081
+ sage: RDF['x,y'].has_coerce_map_from(QQ['x'])
2082
+ True
2083
+ """
2084
+ if S is self:
2085
+ return True
2086
+ elif S == self:
2087
+ if debug.unique_parent_warnings:
2088
+ print("Warning: non-unique parents %s" % (type(S)))
2089
+ return True
2090
+ return self._internal_coerce_map_from(S) is not None
2091
+
2092
+ cpdef _coerce_map_from_(self, S):
2093
+ """
2094
+ Override this method to specify coercions beyond those specified
2095
+ in ``coerce_list``.
2096
+
2097
+ If no such coercion exists, return ``None`` or ``False``. Otherwise, it
2098
+ may return either an actual Map to use for the coercion, a callable
2099
+ (in which case it will be wrapped in a Map), or ``True`` (in which case
2100
+ a generic map will be provided).
2101
+ """
2102
+ try:
2103
+ # Try possible _coerce_map_from_() methods defined in
2104
+ # ParentMethods classes of categories.
2105
+ return super(Parent, self)._coerce_map_from_(S)
2106
+ except AttributeError:
2107
+ return None
2108
+
2109
+ cpdef coerce_map_from(self, S):
2110
+ """
2111
+ Return a :class:`Map` object to coerce from ``S`` to ``self`` if one
2112
+ exists, or ``None`` if no such coercion exists.
2113
+
2114
+ EXAMPLES:
2115
+
2116
+ By :issue:`12313`, a special kind of weak key dictionary is used to
2117
+ store coercion and conversion maps, namely
2118
+ :class:`~sage.structure.coerce_dict.MonoDict`. In that way, a memory
2119
+ leak was fixed that would occur in the following test::
2120
+
2121
+ sage: import gc
2122
+ sage: _ = gc.collect()
2123
+ sage: K = GF(1<<55,'t') # needs sage.rings.finite_rings
2124
+ sage: for i in range(50): # needs sage.rings.finite_rings sage.schemes
2125
+ ....: a = K.random_element()
2126
+ ....: E = EllipticCurve(j=a)
2127
+ ....: b = K.has_coerce_map_from(E)
2128
+ sage: _ = gc.collect()
2129
+ sage: len([x for x in gc.get_objects() if isinstance(x, type(E))]) # needs sage.rings.finite_rings sage.schemes
2130
+ 1
2131
+
2132
+ TESTS:
2133
+
2134
+ The following was fixed in :issue:`12969`::
2135
+
2136
+ sage: # needs sage.combinat sage.modules
2137
+ sage: R = QQ['q,t'].fraction_field()
2138
+ sage: Sym = SymmetricFunctions(R)
2139
+ sage: H = Sym.macdonald().H()
2140
+ sage: P = Sym.macdonald().P()
2141
+ sage: m = Sym.monomial()
2142
+ sage: Ht = Sym.macdonald().Ht()
2143
+ sage: phi = m.coerce_map_from(P)
2144
+ """
2145
+ return copy(self._internal_coerce_map_from(S))
2146
+
2147
+ cpdef _internal_coerce_map_from(self, S):
2148
+ """
2149
+ Return the :class:`Map` object to coerce from ``S`` to ``self`` that
2150
+ is used internally by the coercion system if one exists, or ``None``
2151
+ if no such coercion exists.
2152
+
2153
+ EXAMPLES:
2154
+
2155
+ By :issue:`14711`, coerce maps should be copied when using them
2156
+ outside of the coercion system, because they may become defunct
2157
+ by garbage collection::
2158
+
2159
+ sage: ZZ._internal_coerce_map_from(int)
2160
+ (map internal to coercion system -- copy before use)
2161
+ Native morphism:
2162
+ From: Set of Python objects of class 'int'
2163
+ To: Integer Ring
2164
+ sage: copy(ZZ._internal_coerce_map_from(int))
2165
+ Native morphism:
2166
+ From: Set of Python objects of class 'int'
2167
+ To: Integer Ring
2168
+ sage: copy(QQ._internal_coerce_map_from(ZZ))
2169
+ Natural morphism:
2170
+ From: Integer Ring
2171
+ To: Rational Field
2172
+
2173
+ sage: # needs sage.combinat sage.modules
2174
+ sage: R = QQ['q,t'].fraction_field()
2175
+ sage: Sym = SymmetricFunctions(R)
2176
+ sage: P = Sym.macdonald().P()
2177
+ sage: Ht = Sym.macdonald().Ht()
2178
+ sage: Ht._internal_coerce_map_from(P)
2179
+ (map internal to coercion system -- copy before use)
2180
+ Composite map:
2181
+ From: Symmetric Functions over Fraction Field of Multivariate Polynomial Ring in q, t over Rational Field in the Macdonald P basis
2182
+ To: Symmetric Functions over Fraction Field of Multivariate Polynomial Ring in q, t over Rational Field in the Macdonald Ht basis
2183
+ sage: copy(Ht._internal_coerce_map_from(P))
2184
+ Composite map:
2185
+ From: Symmetric Functions over Fraction Field of Multivariate Polynomial Ring in q, t over Rational Field in the Macdonald P basis
2186
+ To: Symmetric Functions over Fraction Field of Multivariate Polynomial Ring in q, t over Rational Field in the Macdonald Ht basis
2187
+ Defn: Generic morphism:
2188
+ From: Symmetric Functions over Fraction Field of Multivariate Polynomial Ring in q, t over Rational Field in the Macdonald P basis
2189
+ To: Symmetric Functions over Fraction Field of Multivariate Polynomial Ring in q, t over Rational Field in the Macdonald J basis
2190
+ then
2191
+ Generic morphism:
2192
+ From: Symmetric Functions over Fraction Field of Multivariate Polynomial Ring in q, t over Rational Field in the Macdonald J basis
2193
+ To: Symmetric Functions over Fraction Field of Multivariate Polynomial Ring in q, t over Rational Field in the Schur basis
2194
+ then
2195
+ Generic morphism:
2196
+ From: Symmetric Functions over Fraction Field of Multivariate Polynomial Ring in q, t over Rational Field in the Schur basis
2197
+ To: Symmetric Functions over Fraction Field of Multivariate Polynomial Ring in q, t over Rational Field in the Macdonald Ht basis
2198
+
2199
+ The following was fixed in :issue:`4740`::
2200
+
2201
+ sage: F = GF(13)
2202
+ sage: F._internal_coerce_map_from(F) is F._internal_coerce_map_from(F)
2203
+ True
2204
+ """
2205
+ if not good_as_coerce_domain(S):
2206
+ return None
2207
+ self._coercions_used = True
2208
+ cdef map.Map mor
2209
+
2210
+ if isinstance(S, Set_PythonType_class):
2211
+ return self._internal_coerce_map_from(S._type)
2212
+ if self._coerce_from_hash is None: # this is because parent.__init__() does not always get called
2213
+ self.init_coerce(False)
2214
+
2215
+ try:
2216
+ return self._coerce_from_hash.get(S)
2217
+ except KeyError:
2218
+ pass
2219
+
2220
+ if S is self:
2221
+ from sage.categories.homset import Hom
2222
+ mor = Hom(self, self).identity()
2223
+ mor._is_coercion = True
2224
+ self._coerce_from_hash.set(S, mor)
2225
+ return mor
2226
+
2227
+ if S == self:
2228
+ # non-unique parents
2229
+ if debug.unique_parent_warnings:
2230
+ print("Warning: non-unique parents %s" % (type(S)))
2231
+ mor = self._generic_coerce_map(S)
2232
+ mor._is_coercion = True
2233
+ self._coerce_from_hash.set(S, mor)
2234
+ mor._make_weak_references()
2235
+ return mor
2236
+
2237
+ try:
2238
+ _register_pair(self, S, "coerce")
2239
+ mor = self.discover_coerce_map_from(S)
2240
+ # if mor is not None:
2241
+ # # Need to check that this morphism does not connect previously unconnected parts of the coercion diagram
2242
+ # if self._embedding is not None and not self._embedding.codomain().has_coerce_map_from(S):
2243
+ # # The following if statement may call this function with self and S. If so, we want to return None,
2244
+ # # so that it does not use this path for the existence of a coercion path.
2245
+ # # We disable this for now because it is too strict
2246
+ # pass
2247
+ # # mor = None
2248
+ # if mor is not None:
2249
+ # # NOTE: this line is what makes the coercion detection stateful
2250
+ # # self._coerce_from_list.append(mor)
2251
+ # pass
2252
+ # It may be that the only coercion from S to self is
2253
+ # via another parent X. But if the pair (S,X) is temporarily
2254
+ # disregarded (using _register_pair, to avoid infinite recursion)
2255
+ # then we are not allowed to cache the absence of a coercion
2256
+ # from S to self. See #12969
2257
+ if (mor is not None) or _may_cache_none(self, S, "coerce"):
2258
+ self._coerce_from_hash.set(S, mor)
2259
+ if mor is not None:
2260
+ mor._is_coercion = True
2261
+ mor._make_weak_references()
2262
+ return mor
2263
+ except CoercionException as ex:
2264
+ _record_exception()
2265
+ return None
2266
+ finally:
2267
+ _unregister_pair(self, S, "coerce")
2268
+
2269
+ cdef discover_coerce_map_from(self, S):
2270
+ """
2271
+ Precedence for discovering a coercion ``S -> self`` goes as follows:
2272
+
2273
+ 1. If ``S`` has an embedding into ``self``, return that embedding.
2274
+
2275
+ 2. If ``self._coerce_map_from_(S)`` is not exactly one of
2276
+
2277
+ - DefaultConvertMap
2278
+ - DefaultConvertMap_unique
2279
+ - NamedConvertMap
2280
+
2281
+ return this map.
2282
+
2283
+ 3. Traverse the coercion lists looking for another map
2284
+ returning the map from step (2) if none is found.
2285
+
2286
+ 4. If ``S`` has an embedding into some parent ``T``, look for
2287
+ ``T -> self`` and return composition.
2288
+
2289
+ In the future, multiple paths may be discovered and compared.
2290
+
2291
+ TESTS:
2292
+
2293
+ Regression test for :issue:`12919` (probably not 100% robust)::
2294
+
2295
+ sage: class P(Parent):
2296
+ ....: def __init__(self):
2297
+ ....: Parent.__init__(self, category=Sets())
2298
+ ....: Element=ElementWrapper
2299
+ sage: A = P(); a = A('a')
2300
+ sage: B = P(); b = B('b')
2301
+ sage: C = P(); c = C('c')
2302
+ sage: D = P(); d = D('d')
2303
+ sage: Hom(A, B)(lambda x: b).register_as_coercion()
2304
+ sage: Hom(B, A)(lambda x: a).register_as_coercion()
2305
+ sage: Hom(C, B)(lambda x: b).register_as_coercion()
2306
+ sage: Hom(D, C)(lambda x: c).register_as_coercion()
2307
+ sage: A(d)
2308
+ 'a'
2309
+
2310
+ Another test::
2311
+
2312
+ sage: # needs sage.rings.number_field
2313
+ sage: x = polygen(ZZ, 'x')
2314
+ sage: K = NumberField([x^2 - 2, x^2 - 3], 'a,b')
2315
+ sage: M = K.absolute_field('c')
2316
+ sage: M_to_K, K_to_M = M.structure()
2317
+ sage: M.register_coercion(K_to_M)
2318
+ sage: K.register_coercion(M_to_K)
2319
+ sage: phi = M.coerce_map_from(QQ)
2320
+ sage: p = QQ.random_element()
2321
+ sage: c = phi(p) - p; c
2322
+ 0
2323
+ sage: c.parent() is M
2324
+ True
2325
+ sage: K.coerce_map_from(QQ)
2326
+ Coercion map:
2327
+ From: Rational Field
2328
+ To: Number Field in a with defining polynomial x^2 - 2 over its base field
2329
+
2330
+ Test that :issue:`17981` is fixed::
2331
+
2332
+ sage: class P(Parent):
2333
+ ....: def __init__(self):
2334
+ ....: Parent.__init__(self, category=Sets())
2335
+ ....: def _coerce_map_from_(self, A):
2336
+ ....: if A == ZZ:
2337
+ ....: return lambda x: self.element_class(self, x)
2338
+ ....: return False
2339
+ ....: Element=ElementWrapper
2340
+ sage: X = P()
2341
+ sage: X.has_coerce_map_from(ZZ)
2342
+ True
2343
+
2344
+ Check that :issue:`14982` is fixed, and more generally that we discover
2345
+ sensible coercion paths in the presence of embeddings::
2346
+
2347
+ sage: # needs sage.rings.number_field
2348
+ sage: K.<a> = NumberField(x^2 + 1/2, embedding=CC(0, 1))
2349
+ sage: L = NumberField(x^2 + 2, 'b', embedding=1/a)
2350
+ sage: PolynomialRing(L, 'x').coerce_map_from(L)
2351
+ Polynomial base injection morphism:
2352
+ From: Number Field in b with defining polynomial x^2 + 2 with b = -2*a
2353
+ To: Univariate Polynomial Ring in x over Number Field in b
2354
+ with defining polynomial x^2 + 2 with b = -2*a
2355
+ sage: PolynomialRing(K, 'x').coerce_map_from(L)
2356
+ Composite map:
2357
+ From: Number Field in b with defining polynomial x^2 + 2 with b = -2*a
2358
+ To: Univariate Polynomial Ring in x over Number Field in a
2359
+ with defining polynomial x^2 + 1/2 with a = 0.7071067811865475?*I
2360
+ Defn: Generic morphism:
2361
+ From: Number Field in b with defining polynomial x^2 + 2 with b = -2*a
2362
+ To: Number Field in a with defining polynomial x^2 + 1/2 with a = 0.7071067811865475?*I
2363
+ Defn: b -> -2*a
2364
+ then
2365
+ Polynomial base injection morphism:
2366
+ From: Number Field in a with defining polynomial x^2 + 1/2 with a = 0.7071067811865475?*I
2367
+ To: Univariate Polynomial Ring in x over Number Field in a
2368
+ with defining polynomial x^2 + 1/2 with a = 0.7071067811865475?*I
2369
+ sage: MatrixSpace(L, 2, 2).coerce_map_from(L)
2370
+ Coercion map:
2371
+ From: Number Field in b with defining polynomial x^2 + 2 with b = -2*a
2372
+ To: Full MatrixSpace of 2 by 2 dense matrices over Number Field in b
2373
+ with defining polynomial x^2 + 2 with b = -2*a
2374
+ sage: PowerSeriesRing(L, 'x').coerce_map_from(L)
2375
+ Coercion map:
2376
+ From: Number Field in b with defining polynomial x^2 + 2 with b = -2*a
2377
+ To: Power Series Ring in x over Number Field in b
2378
+ with defining polynomial x^2 + 2 with b = -2*a
2379
+ """
2380
+ if isinstance(S, Parent) and (<Parent>S)._embedding is not None:
2381
+ if (<Parent>S)._embedding.codomain() is self:
2382
+ return (<Parent>S)._embedding
2383
+
2384
+ user_provided_mor = self._coerce_map_from_(S)
2385
+
2386
+ if user_provided_mor is None or user_provided_mor is False:
2387
+ best_mor = None
2388
+ elif user_provided_mor is True:
2389
+ best_mor = self._generic_coerce_map(S)
2390
+ if not isinstance(best_mor, DefaultConvertMap):
2391
+ return best_mor
2392
+ # Continue searching for better maps. If there is something
2393
+ # better in the list, return that instead. This is so, for
2394
+ # example, _coerce_map_from_ can return True but still take
2395
+ # advantage of the _populate_coercion_lists_ data.
2396
+ elif isinstance(user_provided_mor, map.Map):
2397
+ return user_provided_mor
2398
+ elif callable(user_provided_mor):
2399
+ return CallableConvertMap(S, self, user_provided_mor)
2400
+ else:
2401
+ raise TypeError(
2402
+ _LazyString("_coerce_map_from_ must return None, a boolean, a callable, or an explicit Map (called on %s, got %s)",
2403
+ (type(self), type(user_provided_mor)), {}))
2404
+
2405
+ from sage.categories.homset import Hom
2406
+
2407
+ cdef map.Map mor
2408
+ cdef int num_paths = 1
2409
+ # this is the number of paths we find before settling on the best (the one with lowest coerce_cost).
2410
+ # setting this to 1 will make it return the first path found.
2411
+
2412
+ cdef int mor_found = 0
2413
+ cdef Parent D
2414
+ # Recurse. Note that if S is the domain of one of the maps in self._coerce_from_list,
2415
+ # we will have stuck the map into _coerce_map_hash and thus returned it already.
2416
+ for mor in self._coerce_from_list:
2417
+ D = mor.domain()
2418
+ if D is self:
2419
+ continue
2420
+ if D is S:
2421
+ if best_mor is None or mor._coerce_cost < best_mor._coerce_cost:
2422
+ best_mor = mor
2423
+ mor_found += 1
2424
+ if mor_found >= num_paths:
2425
+ return best_mor
2426
+ else:
2427
+ connecting = None
2428
+ if EltPair(D, S, "coerce") not in _coerce_test_dict:
2429
+ connecting = D._internal_coerce_map_from(S)
2430
+ if connecting is not None:
2431
+ mor = mor * connecting
2432
+ if best_mor is None or mor._coerce_cost < best_mor._coerce_cost:
2433
+ best_mor = mor
2434
+ mor_found += 1
2435
+ if mor_found >= num_paths:
2436
+ return best_mor
2437
+
2438
+ if best_mor is not None:
2439
+ return best_mor
2440
+
2441
+ if isinstance(S, Parent) and (<Parent>S)._embedding is not None:
2442
+ connecting = self._internal_coerce_map_from((<Parent>S)._embedding.codomain())
2443
+ if connecting is not None:
2444
+ return (<Parent>S)._embedding.post_compose(connecting)
2445
+
2446
+ cpdef convert_map_from(self, S):
2447
+ """
2448
+ This function returns a :class:`Map` from `S` to ``self``,
2449
+ which may or may not succeed on all inputs.
2450
+ If a coercion map from S to ``self`` exists,
2451
+ then the it will be returned. If a coercion from ``self`` to `S` exists,
2452
+ then it will attempt to return a section of that map.
2453
+
2454
+ Under the new coercion model, this is the fastest way to convert
2455
+ elements of `S` to elements of ``self`` (short of manually constructing
2456
+ the elements) and is used by :meth:`__call__`.
2457
+
2458
+ EXAMPLES::
2459
+
2460
+ sage: m = ZZ.convert_map_from(QQ)
2461
+ sage: m
2462
+ Generic map:
2463
+ From: Rational Field
2464
+ To: Integer Ring
2465
+ sage: m(-35/7)
2466
+ -5
2467
+ sage: parent(m(-35/7))
2468
+ Integer Ring
2469
+ """
2470
+ return copy(self._internal_convert_map_from(S))
2471
+
2472
+ cpdef _internal_convert_map_from(self, S):
2473
+ """
2474
+ This function returns a :class:`Map` from `S` to ``self``,
2475
+ which may or may not succeed on all inputs.
2476
+ If a coercion map from S to ``self`` exists,
2477
+ then the it will be returned. If a coercion from ``self`` to `S` exists,
2478
+ then it will attempt to return a section of that map.
2479
+
2480
+ Under the new coercion model, this is the fastest way to convert
2481
+ elements of `S` to elements of ``self`` (short of manually constructing
2482
+ the elements) and is used by :func:`__call__`.
2483
+
2484
+ EXAMPLES::
2485
+
2486
+ sage: m = ZZ._internal_convert_map_from(QQ)
2487
+ sage: m
2488
+ (map internal to coercion system -- copy before use)
2489
+ Generic map:
2490
+ From: Rational Field
2491
+ To: Integer Ring
2492
+ sage: m(-35/7)
2493
+ -5
2494
+ sage: parent(m(-35/7))
2495
+ Integer Ring
2496
+ """
2497
+ if not good_as_convert_domain(S):
2498
+ return None
2499
+ if self._convert_from_hash is None: # this is because parent.__init__() does not always get called
2500
+ self.init_coerce()
2501
+ try:
2502
+ return self._convert_from_hash.get(S)
2503
+ except KeyError:
2504
+ mor = self.discover_convert_map_from(S)
2505
+ # Before Issue #14711, the morphism has been
2506
+ # put both into _convert_from_list and into
2507
+ # _convert_from_hash. But there is no reason
2508
+ # to have a double book-keeping, specifically
2509
+ # if one of them is by strong references!
2510
+ self._convert_from_hash.set(S, mor)
2511
+ # Moreover, again by #14711, the morphism should
2512
+ # only keep weak references to domain and codomain,
2513
+ # to allow them being garbage collected.
2514
+ if mor is not None:
2515
+ mor._make_weak_references()
2516
+ return mor
2517
+
2518
+ cdef discover_convert_map_from(self, S):
2519
+
2520
+ cdef map.Map mor = self._internal_coerce_map_from(S)
2521
+ if mor is not None:
2522
+ return mor
2523
+
2524
+ if isinstance(S, Parent):
2525
+ mor = S._internal_coerce_map_from(self)
2526
+ if mor is not None:
2527
+ mor = mor.section()
2528
+ if mor is not None:
2529
+ return mor
2530
+
2531
+ user_provided_mor = self._convert_map_from_(S)
2532
+
2533
+ if user_provided_mor is not None:
2534
+ if isinstance(user_provided_mor, map.Map):
2535
+ return user_provided_mor
2536
+ elif callable(user_provided_mor):
2537
+ return CallableConvertMap(S, self, user_provided_mor)
2538
+ else:
2539
+ raise TypeError(
2540
+ _LazyString("_convert_map_from_ must return a map or callable (called on %s, got %s)",
2541
+ (type(self), type(user_provided_mor)), {}))
2542
+
2543
+ mor = self._generic_convert_map(S)
2544
+ return mor
2545
+
2546
+ cpdef _convert_map_from_(self, S):
2547
+ """
2548
+ Override this method to provide additional conversions beyond those
2549
+ given in ``convert_list``.
2550
+
2551
+ This function is called after coercions are attempted. If there is a
2552
+ coercion morphism in the opposite direction, one should consider
2553
+ adding a section method to that.
2554
+
2555
+ This MUST return a Map from ``S`` to ``self``, or ``None``. If ``None``
2556
+ is returned then a generic map will be provided.
2557
+ """
2558
+ return None
2559
+
2560
+ cpdef get_action(self, S, op=operator.mul, bint self_on_left=True, self_el=None, S_el=None):
2561
+ """
2562
+ Return an action of ``self`` on ``S`` or ``S`` on ``self``.
2563
+
2564
+ To provide additional actions, override :meth:`_get_action_`.
2565
+
2566
+ .. WARNING::
2567
+
2568
+ This is not the method that you typically want to call.
2569
+ Instead, call ``coercion_model.get_action(...)`` which
2570
+ caches results (this ``Parent.get_action`` method does not).
2571
+
2572
+ TESTS::
2573
+
2574
+ sage: M = QQ['y']^3 # needs sage.modules
2575
+ sage: M.get_action(ZZ['x']['y']) # needs sage.modules
2576
+ Right scalar multiplication
2577
+ by Univariate Polynomial Ring in y
2578
+ over Univariate Polynomial Ring in x over Integer Ring
2579
+ on Ambient free module of rank 3 over the principal ideal domain
2580
+ Univariate Polynomial Ring in y over Rational Field
2581
+ sage: print(M.get_action(ZZ['x'])) # needs sage.modules
2582
+ None
2583
+ """
2584
+ action = self._get_action_(S, op, self_on_left)
2585
+ if action is None:
2586
+ action = self.discover_action(S, op, self_on_left, self_el, S_el)
2587
+
2588
+ if action is not None:
2589
+ from sage.categories.action import Action
2590
+ if not isinstance(action, Action):
2591
+ raise TypeError("_get_action_ must return None or an Action")
2592
+
2593
+ self._action_hash.set(S, op, self_on_left, action)
2594
+ return action
2595
+
2596
+ cdef discover_action(self, S, op, bint self_on_left, self_el=None, S_el=None):
2597
+ """
2598
+ TESTS::
2599
+
2600
+ sage: # needs sage.schemes
2601
+ sage: E = EllipticCurve([1,0])
2602
+ sage: coercion_model.get_action(E, ZZ, operator.mul)
2603
+ Right action by Integer Ring on Elliptic Curve defined by y^2 = x^3 + x over Rational Field
2604
+ sage: coercion_model.get_action(ZZ, E, operator.mul)
2605
+ Left action by Integer Ring on Elliptic Curve defined by y^2 = x^3 + x over Rational Field
2606
+ sage: coercion_model.get_action(E, int, operator.mul)
2607
+ Right action by Integer Ring on Elliptic Curve defined by y^2 = x^3 + x over Rational Field
2608
+ with precomposition on right by Native morphism:
2609
+ From: Set of Python objects of class 'int'
2610
+ To: Integer Ring
2611
+ sage: coercion_model.get_action(int, E, operator.mul)
2612
+ Left action by Integer Ring on Elliptic Curve defined by y^2 = x^3 + x over Rational Field
2613
+ with precomposition on left by Native morphism:
2614
+ From: Set of Python objects of class 'int'
2615
+ To: Integer Ring
2616
+
2617
+ ::
2618
+
2619
+ sage: # needs sage.rings.complex_double
2620
+ sage: R.<x> = CDF[]
2621
+ sage: coercion_model.get_action(R, ZZ, operator.pow)
2622
+ Right Integer Powering by Integer Ring
2623
+ on Univariate Polynomial Ring in x over Complex Double Field
2624
+ sage: print(coercion_model.get_action(ZZ, R, operator.pow))
2625
+ None
2626
+ sage: coercion_model.get_action(R, int, operator.pow)
2627
+ Right Integer Powering by Set of Python objects of class 'int'
2628
+ on Univariate Polynomial Ring in x over Complex Double Field
2629
+ sage: print(coercion_model.get_action(int, R, operator.pow))
2630
+ None
2631
+ sage: coercion_model.get_action(R, IntegerModRing(7), operator.pow)
2632
+ Right Integer Powering by Ring of integers modulo 7
2633
+ on Univariate Polynomial Ring in x over Complex Double Field
2634
+
2635
+ ::
2636
+
2637
+ sage: print(coercion_model.get_action(E, ZZ, operator.pow)) # needs sage.schemes
2638
+ None
2639
+
2640
+ ::
2641
+
2642
+ With Pull Request #37369, registered multiplication actions by
2643
+ `ZZ` are also discovered and used when a Python ``int`` is multiplied.
2644
+ Previously, it was only discovering the generic Integer Multiplication
2645
+ Action that all additive groups have. As a result, optimised
2646
+ implementations, such as the use of Pari for scalar multiplication of points
2647
+ on elliptic curves over Finite Fields, was not used if an ``int``
2648
+ multiplied a point, resulting in a 10x slowdown for large characteristic::
2649
+
2650
+ sage: # needs sage.schemes
2651
+ sage: E = EllipticCurve(GF(17),[1,1])
2652
+ sage: coercion_model.discover_action(ZZ, E, operator.mul)
2653
+ Left action by Integer Ring on Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 17
2654
+ sage: coercion_model.discover_action(int, E, operator.mul)
2655
+ Left action by Integer Ring on Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 17
2656
+ with precomposition on left by Native morphism:
2657
+ From: Set of Python objects of class 'int'
2658
+ To: Integer Ring
2659
+ """
2660
+ # G acts on S, G -> G', R -> S => G' acts on R (?)
2661
+ # NO! ZZ[x,y] acts on Matrices(ZZ[x]) but ZZ[y] does not.
2662
+ # What may be true is that if the action's destination is S, then this can be allowed.
2663
+ # Note: a is either None or a sample elements of self.
2664
+ # If needed, it will be passed to Left/RightModuleAction.
2665
+ from sage.categories.action import Action, PrecomposedAction
2666
+ from sage.categories.homset import Hom
2667
+ cdef Parent R
2668
+
2669
+ for action in self._action_list:
2670
+ if isinstance(action, Action) and action.operation() is op:
2671
+ if self_on_left:
2672
+ if action.left_domain() is not self:
2673
+ continue
2674
+ R = action.right_domain()
2675
+ else:
2676
+ if action.right_domain() is not self:
2677
+ continue
2678
+ R = action.left_domain()
2679
+ else:
2680
+ continue
2681
+ if R is S:
2682
+ return action
2683
+ else:
2684
+ connecting = R._internal_coerce_map_from(S) # S -> R
2685
+ if connecting is not None:
2686
+ if self_on_left:
2687
+ return PrecomposedAction(action, None, connecting)
2688
+ else:
2689
+ return PrecomposedAction(action, connecting, None)
2690
+
2691
+ if op is operator.mul: # elements define special action methods.
2692
+ try:
2693
+ _register_pair(self, S, "action") # avoid possible infinite loops
2694
+
2695
+ # detect actions defined by _rmul_, _lmul_, _act_on_, and _acted_upon_ methods
2696
+ from sage.structure.coerce_actions import detect_element_action
2697
+ action = detect_element_action(self, S, self_on_left, self_el, S_el)
2698
+ if action is not None:
2699
+ return action
2700
+
2701
+ if parent_is_integers(S) and not self.has_coerce_map_from(S):
2702
+ # Try the above again, but first coerce integer-like type to Integer
2703
+ # with a connecting coercion
2704
+ global _Integer
2705
+ if _Integer is None:
2706
+ from sage.rings.integer import Integer as _Integer
2707
+ ZZ_el = _Integer(S_el)
2708
+ ZZ = ZZ_el.parent()
2709
+
2710
+ # Now we check if there's an element action from Integers
2711
+ action = detect_element_action(self, ZZ, self_on_left, self_el, ZZ_el)
2712
+
2713
+ # When this is not None, we can do the Precomposed action
2714
+ if action is not None:
2715
+ # Compute the coercion from whatever S is to the Integer class
2716
+ # This should always work because parent_is_integers(S) is True
2717
+ # but it fails when S is gmpy2.mpz.
2718
+ # TODO: should we also patch _internal_coerce_map_from so that
2719
+ # there's a map from gmpy2.mpz to ZZ?
2720
+ connecting = ZZ._internal_coerce_map_from(S)
2721
+ if connecting is not None:
2722
+ if self_on_left:
2723
+ action = PrecomposedAction(action, None, connecting)
2724
+ else:
2725
+ action = PrecomposedAction(action, connecting, None)
2726
+ return action
2727
+
2728
+ # Otherwise, we do the most basic IntegerMulAction
2729
+ from sage.structure.coerce_actions import IntegerMulAction
2730
+ try:
2731
+ return IntegerMulAction(S, self, not self_on_left, self_el)
2732
+ except TypeError:
2733
+ _record_exception()
2734
+ finally:
2735
+ _unregister_pair(self, S, "action")
2736
+ elif self_on_left and op is operator.pow:
2737
+ S_is_int = parent_is_integers(S)
2738
+ if not S_is_int:
2739
+ from sage.rings.abc import IntegerModRing
2740
+ if isinstance(S, IntegerModRing):
2741
+ # We allow powering by an IntegerMod by treating it
2742
+ # as an integer.
2743
+ #
2744
+ # TODO: this makes sense in a few cases that we want
2745
+ # to support. But in general this should not be
2746
+ # allowed. See Issue #15709
2747
+ S_is_int = True
2748
+ if S_is_int:
2749
+ from sage.structure.coerce_actions import IntegerPowAction
2750
+ try:
2751
+ return IntegerPowAction(S, self, False, self_el)
2752
+ except TypeError:
2753
+ _record_exception()
2754
+
2755
+ cpdef _get_action_(self, S, op, bint self_on_left):
2756
+ """
2757
+ Override this method to provide an action of ``self`` on ``S`` or ``S``
2758
+ on ``self`` beyond what was specified in ``action_list``.
2759
+
2760
+ This must return an action which accepts an element of ``self`` and an
2761
+ element of ``S`` (in the order specified by ``self_on_left``).
2762
+ """
2763
+ return None
2764
+
2765
+ # TODO: remove once all parents in Sage will inherit properly from
2766
+ # Sets().ParentMethods.an_element
2767
+ cpdef an_element(self):
2768
+ r"""
2769
+ Return a (preferably typical) element of this parent.
2770
+
2771
+ This is used both for illustration and testing purposes. If
2772
+ the set ``self`` is empty, :meth:`an_element` raises the
2773
+ exception :exc:`EmptySetError`.
2774
+
2775
+ This calls :meth:`_an_element_` (which see), and caches the
2776
+ result. Parent are thus encouraged to override :meth:`_an_element_`.
2777
+
2778
+ EXAMPLES::
2779
+
2780
+ sage: CDF.an_element() # needs sage.rings.complex_double
2781
+ 1.0*I
2782
+ sage: ZZ[['t']].an_element()
2783
+ t
2784
+
2785
+ In case the set is empty, an :exc:`EmptySetError` is raised::
2786
+
2787
+ sage: Set([]).an_element()
2788
+ Traceback (most recent call last):
2789
+ ...
2790
+ EmptySetError
2791
+ """
2792
+ # _cache_an_element, not _cache__an_element, to prevent a possible
2793
+ # conflict with @cached_method
2794
+ if self._cache_an_element is None:
2795
+ self._cache_an_element = self._an_element_()
2796
+ return self._cache_an_element
2797
+
2798
+ def _an_element_(self):
2799
+ """
2800
+ Return an element of ``self``.
2801
+
2802
+ Want it in sufficient generality
2803
+ that poorly-written functions will not work when they are not
2804
+ supposed to. This is cached so does not have to be super fast.
2805
+
2806
+ EXAMPLES::
2807
+
2808
+ sage: QQ._an_element_()
2809
+ 1/2
2810
+ sage: ZZ['x,y,z']._an_element_()
2811
+ x
2812
+
2813
+ TESTS:
2814
+
2815
+ Since ``Parent`` comes before the parent classes provided by
2816
+ categories in the hierarchy of classes, we make sure that this
2817
+ default implementation of :meth:`_an_element_` does not
2818
+ override some provided by the categories. Eventually, this
2819
+ default implementation should be moved into the categories to
2820
+ avoid this workaround::
2821
+
2822
+ sage: S = FiniteEnumeratedSet([1,2,3])
2823
+ sage: S.category()
2824
+ Category of facade finite enumerated sets
2825
+ sage: super(Parent, S)._an_element_
2826
+ Cached version of <function ..._an_element_from_iterator at ...>
2827
+ sage: S._an_element_()
2828
+ 1
2829
+ sage: S = FiniteEnumeratedSet([])
2830
+ sage: S._an_element_()
2831
+ Traceback (most recent call last):
2832
+ ...
2833
+ EmptySetError
2834
+ """
2835
+ try:
2836
+ return super()._an_element_()
2837
+ except EmptySetError:
2838
+ raise
2839
+ except Exception:
2840
+ _record_exception()
2841
+ pass
2842
+
2843
+ try:
2844
+ return self.gen(0)
2845
+ except Exception:
2846
+ _record_exception()
2847
+ pass
2848
+
2849
+ try:
2850
+ return self.gen()
2851
+ except Exception:
2852
+ _record_exception()
2853
+ pass
2854
+
2855
+ from sage.rings.infinity import infinity
2856
+ for x in ['_an_element_', 'pi', 1.2, 2, 1, 0, infinity]:
2857
+ # This weird looking list is to try to get an element
2858
+ # which does not coerce other places.
2859
+ try:
2860
+ return self(x)
2861
+ except (TypeError, NameError, NotImplementedError, AttributeError, ValueError):
2862
+ _record_exception()
2863
+
2864
+ raise NotImplementedError(_LazyString("please implement _an_element_ for %s", (self,), {}))
2865
+
2866
+ cpdef bint is_exact(self) except -2:
2867
+ """
2868
+ Test whether elements of this parent are represented exactly.
2869
+
2870
+ .. NOTE::
2871
+
2872
+ This defaults to true, so even if it does return ``True``
2873
+ you have no guarantee (unless the parent has properly
2874
+ overloaded this).
2875
+
2876
+ OUTPUT:
2877
+
2878
+ Return ``True`` if elements of this parent are represented exactly, i.e.,
2879
+ there is no precision loss when doing arithmetic.
2880
+
2881
+ EXAMPLES::
2882
+
2883
+ sage: QQ.is_exact()
2884
+ True
2885
+ sage: ZZ.is_exact()
2886
+ True
2887
+ sage: Qp(7).is_exact() # needs sage.rings.padics
2888
+ False
2889
+ sage: Zp(7, type='capped-abs').is_exact() # needs sage.rings.padics
2890
+ False
2891
+ """
2892
+ return True
2893
+
2894
+ @cached_method
2895
+ def _is_numerical(self):
2896
+ r"""
2897
+ Test if elements of this parent can be numerically evaluated as complex
2898
+ numbers (in a canonical way).
2899
+
2900
+ EXAMPLES::
2901
+
2902
+ sage: QuadraticField(-1)._is_numerical() # needs sage.rings.number_field
2903
+ True
2904
+ sage: QQ._is_numerical()
2905
+ True
2906
+ sage: [RR._is_numerical(), CC._is_numerical()] # needs sage.rings.real_mpfr
2907
+ [True, True]
2908
+ sage: SR._is_numerical() # needs sage.symbolic
2909
+ False
2910
+ sage: [R._is_numerical() for R in [QQ['x'], QQ[['x']]]]
2911
+ [False, False]
2912
+ sage: [R._is_numerical() for R in [RBF, CBF]] # needs sage.libs.flint
2913
+ [False, False]
2914
+ sage: [R._is_numerical() for R in [RIF, CIF]] # needs sage.rings.real_interval_field
2915
+ [False, False]
2916
+ """
2917
+ try:
2918
+ from sage.rings.complex_mpfr import ComplexField
2919
+ from sage.rings.real_mpfr import mpfr_prec_min
2920
+ except ImportError:
2921
+ pass
2922
+ else:
2923
+ return ComplexField(mpfr_prec_min()).has_coerce_map_from(self)
2924
+
2925
+ try:
2926
+ from sage.rings.complex_double import CDF
2927
+ except ImportError:
2928
+ pass
2929
+ else:
2930
+ return CDF.has_coerce_map_from(self)
2931
+
2932
+ from sage.rings.real_double import RDF
2933
+ return RDF.has_coerce_map_from(self)
2934
+
2935
+ @cached_method
2936
+ def _is_real_numerical(self):
2937
+ r"""
2938
+ Test if elements of this parent can be numerically evaluated as real
2939
+ numbers (in a canonical way).
2940
+
2941
+ EXAMPLES::
2942
+
2943
+ sage: QuadraticField(2)._is_real_numerical() # needs sage.rings.number_field
2944
+ True
2945
+ sage: [QQ._is_real_numerical(), ZZ._is_real_numerical()]
2946
+ [True, True]
2947
+ sage: [RR._is_real_numerical(), RLF._is_real_numerical()] # needs sage.rings.real_mpfr
2948
+ [True, True]
2949
+ sage: QuadraticField(-1)._is_real_numerical() # needs sage.rings.number_field
2950
+ False
2951
+ sage: CC._is_real_numerical() # needs sage.rings.real_mpfr
2952
+ False
2953
+ sage: SR._is_real_numerical() # needs sage.symbolic
2954
+ False
2955
+ sage: [R._is_real_numerical() for R in [QQ['x'], QQ[['x']]]]
2956
+ [False, False]
2957
+ sage: [R._is_real_numerical() for R in [RBF, CBF]] # needs sage.libs.flint
2958
+ [False, False]
2959
+ sage: [R._is_real_numerical() for R in [RIF, CIF]] # needs sage.libs.flint
2960
+ [False, False]
2961
+ """
2962
+ try:
2963
+ from sage.rings.real_mpfr import RealField, mpfr_prec_min
2964
+ except ImportError:
2965
+ pass
2966
+ else:
2967
+ return RealField(mpfr_prec_min()).has_coerce_map_from(self)
2968
+
2969
+ from sage.rings.real_double import RDF
2970
+ return RDF.has_coerce_map_from(self)
2971
+
2972
+ ############################################################################
2973
+ # Set base class --
2974
+ ############################################################################
2975
+
2976
+ cdef class Set_generic(Parent):
2977
+ """
2978
+ Abstract base class for sets.
2979
+
2980
+ TESTS::
2981
+
2982
+ sage: Set(QQ).category()
2983
+ Category of infinite sets
2984
+ """
2985
+ def object(self):
2986
+ """
2987
+ Return the underlying object of ``self``.
2988
+
2989
+ EXAMPLES::
2990
+
2991
+ sage: Set(QQ).object()
2992
+ Rational Field
2993
+ """
2994
+ return self
2995
+
2996
+ def __bool__(self):
2997
+ """
2998
+ A set is considered ``True`` unless it is empty, in which case it is
2999
+ considered to be ``False``.
3000
+
3001
+ EXAMPLES::
3002
+
3003
+ sage: bool(Set(QQ))
3004
+ True
3005
+ sage: bool(Set(GF(3)))
3006
+ True
3007
+ """
3008
+ return not (self.is_finite() and len(self) == 0)
3009
+
3010
+
3011
+ # These functions are to guarantee that user defined _lmul_, _rmul_,
3012
+ # _act_on_, _acted_upon_ do not in turn call __mul__ on their
3013
+ # arguments, leading to an infinite loop.
3014
+
3015
+ cdef dict _coerce_test_dict = {}
3016
+
3017
+ cdef class EltPair:
3018
+ cdef x, y, tag
3019
+
3020
+ def __init__(self, x, y, tag):
3021
+ self.x = x
3022
+ self.y = y
3023
+ self.tag = tag
3024
+
3025
+ def __richcmp__(EltPair self, EltPair other, int op):
3026
+ cdef bint eq = self.x is other.x and self.y is other.y and self.tag is other.tag
3027
+ if op in [Py_EQ, Py_GE, Py_LE]:
3028
+ return eq
3029
+ else:
3030
+ return not eq
3031
+
3032
+ def __hash__(self):
3033
+ """
3034
+ EXAMPLES::
3035
+
3036
+ sage: from sage.structure.parent import EltPair
3037
+ sage: a = EltPair(ZZ, QQ, "coerce")
3038
+ sage: b = EltPair(ZZ, QQ, "coerce")
3039
+ sage: hash(a) == hash(b)
3040
+ True
3041
+
3042
+ TESTS:
3043
+
3044
+ Verify that :issue:`16341` has been resolved::
3045
+
3046
+ sage: K.<a> = Qq(9) # needs sage.rings.padics
3047
+ sage: E = EllipticCurve_from_j(0).base_extend(K) # needs sage.rings.padics sage.schemes
3048
+ sage: E.get_action(ZZ) # needs sage.rings.padics sage.schemes
3049
+ Right action by Integer Ring
3050
+ on Elliptic Curve defined by y^2 + (1+O(3^20))*y = x^3
3051
+ over 3-adic Unramified Extension Field in a
3052
+ defined by x^2 + 2*x + 2
3053
+ """
3054
+ return hash((id(self.x), id(self.y), id(self.tag)))
3055
+
3056
+ def short_repr(self):
3057
+ return self.tag, hex(<long><void*>self.x), hex(<long><void*>self.y)
3058
+
3059
+ def __repr__(self):
3060
+ return "%r: %r (%r), %r (%r)" % (self.tag, self.x, type(self.x), self.y, type(self.y))
3061
+
3062
+ cdef bint _may_cache_none(x, y, tag) except -1:
3063
+ # Are we allowed to cache the absence of a coercion
3064
+ # from y to x? We are only allowed, if y is *not*
3065
+ # part of any coerce path that is temporarily disregarded,
3066
+ # with the only exception of the path from y to x.
3067
+ # See #12969.
3068
+ cdef EltPair P
3069
+ for P in _coerce_test_dict:
3070
+ if (P.y is y) and (P.x is not x) and (P.tag is tag):
3071
+ return 0
3072
+ return 1
3073
+
3074
+ cdef bint _register_pair(x, y, tag) except -1:
3075
+ # Means: We will temporarily disregard coercions from
3076
+ # y to x when looking for a coercion path by depth first
3077
+ # search. This is to avoid infinite recursion.
3078
+ both = EltPair(x, y, tag)
3079
+
3080
+ if both in _coerce_test_dict:
3081
+ xp = type(x) if isinstance(x, Parent) else parent(x)
3082
+ yp = type(y) if isinstance(y, Parent) else parent(y)
3083
+ raise CoercionException(
3084
+ _LazyString("Infinite loop in action of %s (parent %s) and %s (parent %s)!",
3085
+ (x, xp, y, yp), {}))
3086
+ _coerce_test_dict[both] = True
3087
+ return 0
3088
+
3089
+ cdef bint _unregister_pair(x, y, tag) except -1:
3090
+ try:
3091
+ _coerce_test_dict.pop(EltPair(x, y, tag), None)
3092
+ except (ValueError, CoercionException):
3093
+ pass