passagemath-objects 10.8.1a3__cp314-cp314-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (283) hide show
  1. passagemath_objects/__init__.py +3 -0
  2. passagemath_objects-10.8.1a3.dist-info/DELVEWHEEL +2 -0
  3. passagemath_objects-10.8.1a3.dist-info/METADATA +114 -0
  4. passagemath_objects-10.8.1a3.dist-info/RECORD +283 -0
  5. passagemath_objects-10.8.1a3.dist-info/WHEEL +5 -0
  6. passagemath_objects-10.8.1a3.dist-info/top_level.txt +3 -0
  7. passagemath_objects.libs/libgmp-10-60021eeab4282b29024e43b2b1412b53.dll +0 -0
  8. sage/all__sagemath_objects.py +46 -0
  9. sage/arith/all__sagemath_objects.py +5 -0
  10. sage/arith/long.pxd +411 -0
  11. sage/arith/numerical_approx.cp314-win_amd64.pyd +0 -0
  12. sage/arith/numerical_approx.pxd +35 -0
  13. sage/arith/numerical_approx.pyx +75 -0
  14. sage/arith/power.cp314-win_amd64.pyd +0 -0
  15. sage/arith/power.pxd +31 -0
  16. sage/arith/power.pyx +127 -0
  17. sage/categories/action.cp314-win_amd64.pyd +0 -0
  18. sage/categories/action.pxd +29 -0
  19. sage/categories/action.pyx +641 -0
  20. sage/categories/algebra_functor.py +745 -0
  21. sage/categories/all__sagemath_objects.py +33 -0
  22. sage/categories/basic.py +71 -0
  23. sage/categories/cartesian_product.py +292 -0
  24. sage/categories/category.py +3379 -0
  25. sage/categories/category_cy_helper.cp314-win_amd64.pyd +0 -0
  26. sage/categories/category_cy_helper.pxd +8 -0
  27. sage/categories/category_cy_helper.pyx +322 -0
  28. sage/categories/category_singleton.cp314-win_amd64.pyd +0 -0
  29. sage/categories/category_singleton.pxd +3 -0
  30. sage/categories/category_singleton.pyx +343 -0
  31. sage/categories/category_types.py +637 -0
  32. sage/categories/category_with_axiom.py +2889 -0
  33. sage/categories/covariant_functorial_construction.py +700 -0
  34. sage/categories/facade_sets.py +228 -0
  35. sage/categories/functor.cp314-win_amd64.pyd +0 -0
  36. sage/categories/functor.pxd +7 -0
  37. sage/categories/functor.pyx +659 -0
  38. sage/categories/homset.py +1289 -0
  39. sage/categories/homsets.py +364 -0
  40. sage/categories/isomorphic_objects.py +73 -0
  41. sage/categories/map.cp314-win_amd64.pyd +0 -0
  42. sage/categories/map.pxd +34 -0
  43. sage/categories/map.pyx +2106 -0
  44. sage/categories/morphism.cp314-win_amd64.pyd +0 -0
  45. sage/categories/morphism.pxd +14 -0
  46. sage/categories/morphism.pyx +895 -0
  47. sage/categories/objects.py +167 -0
  48. sage/categories/primer.py +1695 -0
  49. sage/categories/pushout.py +4847 -0
  50. sage/categories/quotients.py +64 -0
  51. sage/categories/realizations.py +200 -0
  52. sage/categories/sets_cat.py +3305 -0
  53. sage/categories/sets_with_partial_maps.py +52 -0
  54. sage/categories/subobjects.py +64 -0
  55. sage/categories/subquotients.py +21 -0
  56. sage/categories/with_realizations.py +311 -0
  57. sage/cpython/__init__.py +22 -0
  58. sage/cpython/_py2_random.py +619 -0
  59. sage/cpython/all.py +3 -0
  60. sage/cpython/atexit.cp314-win_amd64.pyd +0 -0
  61. sage/cpython/atexit.pyx +269 -0
  62. sage/cpython/builtin_types.cp314-win_amd64.pyd +0 -0
  63. sage/cpython/builtin_types.pyx +7 -0
  64. sage/cpython/cython_metaclass.cp314-win_amd64.pyd +0 -0
  65. sage/cpython/cython_metaclass.h +117 -0
  66. sage/cpython/cython_metaclass.pxd +3 -0
  67. sage/cpython/cython_metaclass.pyx +130 -0
  68. sage/cpython/debug.cp314-win_amd64.pyd +0 -0
  69. sage/cpython/debug.pyx +302 -0
  70. sage/cpython/dict_del_by_value.cp314-win_amd64.pyd +0 -0
  71. sage/cpython/dict_del_by_value.pxd +9 -0
  72. sage/cpython/dict_del_by_value.pyx +191 -0
  73. sage/cpython/dict_internal.h +80 -0
  74. sage/cpython/getattr.cp314-win_amd64.pyd +0 -0
  75. sage/cpython/getattr.pxd +9 -0
  76. sage/cpython/getattr.pyx +439 -0
  77. sage/cpython/pycore_long.h +97 -0
  78. sage/cpython/pycore_long.pxd +10 -0
  79. sage/cpython/python_debug.h +44 -0
  80. sage/cpython/python_debug.pxd +47 -0
  81. sage/cpython/pyx_visit.h +13 -0
  82. sage/cpython/string.cp314-win_amd64.pyd +0 -0
  83. sage/cpython/string.pxd +76 -0
  84. sage/cpython/string.pyx +34 -0
  85. sage/cpython/string_impl.h +60 -0
  86. sage/cpython/type.cp314-win_amd64.pyd +0 -0
  87. sage/cpython/type.pxd +2 -0
  88. sage/cpython/type.pyx +40 -0
  89. sage/cpython/wrapperdescr.pxd +67 -0
  90. sage/ext/all__sagemath_objects.py +3 -0
  91. sage/ext/ccobject.h +64 -0
  92. sage/ext/cplusplus.pxd +17 -0
  93. sage/ext/mod_int.h +30 -0
  94. sage/ext/mod_int.pxd +24 -0
  95. sage/ext/stdsage.pxd +39 -0
  96. sage/groups/all__sagemath_objects.py +1 -0
  97. sage/groups/group.cp314-win_amd64.pyd +0 -0
  98. sage/groups/group.pxd +14 -0
  99. sage/groups/group.pyx +296 -0
  100. sage/groups/old.cp314-win_amd64.pyd +0 -0
  101. sage/groups/old.pxd +14 -0
  102. sage/groups/old.pyx +219 -0
  103. sage/libs/all__sagemath_objects.py +3 -0
  104. sage/libs/gmp/__init__.py +1 -0
  105. sage/libs/gmp/all.pxd +6 -0
  106. sage/libs/gmp/binop.pxd +23 -0
  107. sage/libs/gmp/misc.pxd +8 -0
  108. sage/libs/gmp/mpf.pxd +88 -0
  109. sage/libs/gmp/mpn.pxd +57 -0
  110. sage/libs/gmp/mpq.pxd +57 -0
  111. sage/libs/gmp/mpz.pxd +202 -0
  112. sage/libs/gmp/pylong.cp314-win_amd64.pyd +0 -0
  113. sage/libs/gmp/pylong.pxd +12 -0
  114. sage/libs/gmp/pylong.pyx +150 -0
  115. sage/libs/gmp/random.pxd +25 -0
  116. sage/libs/gmp/randomize.pxd +59 -0
  117. sage/libs/gmp/types.pxd +53 -0
  118. sage/libs/gmpxx.pxd +19 -0
  119. sage/misc/abstract_method.py +276 -0
  120. sage/misc/all__sagemath_objects.py +43 -0
  121. sage/misc/bindable_class.py +253 -0
  122. sage/misc/c3_controlled.cp314-win_amd64.pyd +0 -0
  123. sage/misc/c3_controlled.pxd +2 -0
  124. sage/misc/c3_controlled.pyx +1402 -0
  125. sage/misc/cachefunc.cp314-win_amd64.pyd +0 -0
  126. sage/misc/cachefunc.pxd +43 -0
  127. sage/misc/cachefunc.pyx +3801 -0
  128. sage/misc/call.py +188 -0
  129. sage/misc/classcall_metaclass.cp314-win_amd64.pyd +0 -0
  130. sage/misc/classcall_metaclass.pxd +14 -0
  131. sage/misc/classcall_metaclass.pyx +599 -0
  132. sage/misc/constant_function.cp314-win_amd64.pyd +0 -0
  133. sage/misc/constant_function.pyx +130 -0
  134. sage/misc/decorators.py +739 -0
  135. sage/misc/fast_methods.cp314-win_amd64.pyd +0 -0
  136. sage/misc/fast_methods.pxd +20 -0
  137. sage/misc/fast_methods.pyx +351 -0
  138. sage/misc/flatten.py +90 -0
  139. sage/misc/fpickle.cp314-win_amd64.pyd +0 -0
  140. sage/misc/fpickle.pyx +176 -0
  141. sage/misc/function_mangling.cp314-win_amd64.pyd +0 -0
  142. sage/misc/function_mangling.pxd +11 -0
  143. sage/misc/function_mangling.pyx +308 -0
  144. sage/misc/inherit_comparison.cp314-win_amd64.pyd +0 -0
  145. sage/misc/inherit_comparison.pxd +5 -0
  146. sage/misc/inherit_comparison.pyx +105 -0
  147. sage/misc/instancedoc.cp314-win_amd64.pyd +0 -0
  148. sage/misc/instancedoc.pyx +331 -0
  149. sage/misc/lazy_attribute.cp314-win_amd64.pyd +0 -0
  150. sage/misc/lazy_attribute.pyx +607 -0
  151. sage/misc/lazy_format.py +132 -0
  152. sage/misc/lazy_import.cp314-win_amd64.pyd +0 -0
  153. sage/misc/lazy_import.pxd +13 -0
  154. sage/misc/lazy_import.pyx +1307 -0
  155. sage/misc/lazy_import_cache.py +36 -0
  156. sage/misc/lazy_list.cp314-win_amd64.pyd +0 -0
  157. sage/misc/lazy_list.pxd +19 -0
  158. sage/misc/lazy_list.pyx +1187 -0
  159. sage/misc/lazy_string.cp314-win_amd64.pyd +0 -0
  160. sage/misc/lazy_string.pxd +7 -0
  161. sage/misc/lazy_string.pyx +546 -0
  162. sage/misc/misc.py +980 -0
  163. sage/misc/misc_c.cp314-win_amd64.pyd +0 -0
  164. sage/misc/misc_c.pxd +3 -0
  165. sage/misc/misc_c.pyx +765 -0
  166. sage/misc/namespace_package.py +37 -0
  167. sage/misc/nested_class.cp314-win_amd64.pyd +0 -0
  168. sage/misc/nested_class.pxd +3 -0
  169. sage/misc/nested_class.pyx +394 -0
  170. sage/misc/persist.cp314-win_amd64.pyd +0 -0
  171. sage/misc/persist.pyx +1279 -0
  172. sage/misc/prandom.py +418 -0
  173. sage/misc/randstate.cp314-win_amd64.pyd +0 -0
  174. sage/misc/randstate.pxd +31 -0
  175. sage/misc/randstate.pyx +1096 -0
  176. sage/misc/repr.py +203 -0
  177. sage/misc/reset.cp314-win_amd64.pyd +0 -0
  178. sage/misc/reset.pyx +196 -0
  179. sage/misc/sage_ostools.cp314-win_amd64.pyd +0 -0
  180. sage/misc/sage_ostools.pyx +323 -0
  181. sage/misc/sage_timeit.py +275 -0
  182. sage/misc/sage_timeit_class.cp314-win_amd64.pyd +0 -0
  183. sage/misc/sage_timeit_class.pyx +120 -0
  184. sage/misc/sage_unittest.py +639 -0
  185. sage/misc/sageinspect.py +2792 -0
  186. sage/misc/session.cp314-win_amd64.pyd +0 -0
  187. sage/misc/session.pyx +392 -0
  188. sage/misc/superseded.py +576 -0
  189. sage/misc/test_nested_class.py +228 -0
  190. sage/misc/timing.py +264 -0
  191. sage/misc/unknown.py +222 -0
  192. sage/misc/verbose.py +253 -0
  193. sage/misc/weak_dict.cp314-win_amd64.pyd +0 -0
  194. sage/misc/weak_dict.pxd +15 -0
  195. sage/misc/weak_dict.pyx +1197 -0
  196. sage/modules/all__sagemath_objects.py +1 -0
  197. sage/modules/module.cp314-win_amd64.pyd +0 -0
  198. sage/modules/module.pxd +5 -0
  199. sage/modules/module.pyx +329 -0
  200. sage/rings/all__sagemath_objects.py +3 -0
  201. sage/rings/integer_fake.h +22 -0
  202. sage/rings/integer_fake.pxd +55 -0
  203. sage/rings/integer_fake.pyi +8 -0
  204. sage/sets/all__sagemath_objects.py +3 -0
  205. sage/sets/pythonclass.cp314-win_amd64.pyd +0 -0
  206. sage/sets/pythonclass.pxd +9 -0
  207. sage/sets/pythonclass.pyx +247 -0
  208. sage/structure/__init__.py +13 -0
  209. sage/structure/all.py +30 -0
  210. sage/structure/category_object.cp314-win_amd64.pyd +0 -0
  211. sage/structure/category_object.pxd +28 -0
  212. sage/structure/category_object.pyx +1090 -0
  213. sage/structure/coerce.cp314-win_amd64.pyd +0 -0
  214. sage/structure/coerce.pxd +44 -0
  215. sage/structure/coerce.pyx +2113 -0
  216. sage/structure/coerce_actions.cp314-win_amd64.pyd +0 -0
  217. sage/structure/coerce_actions.pxd +27 -0
  218. sage/structure/coerce_actions.pyx +988 -0
  219. sage/structure/coerce_dict.cp314-win_amd64.pyd +0 -0
  220. sage/structure/coerce_dict.pxd +51 -0
  221. sage/structure/coerce_dict.pyx +1557 -0
  222. sage/structure/coerce_exceptions.py +23 -0
  223. sage/structure/coerce_maps.cp314-win_amd64.pyd +0 -0
  224. sage/structure/coerce_maps.pxd +24 -0
  225. sage/structure/coerce_maps.pyx +656 -0
  226. sage/structure/debug_options.cp314-win_amd64.pyd +0 -0
  227. sage/structure/debug_options.pxd +6 -0
  228. sage/structure/debug_options.pyx +54 -0
  229. sage/structure/dynamic_class.py +541 -0
  230. sage/structure/element.cp314-win_amd64.pyd +0 -0
  231. sage/structure/element.pxd +271 -0
  232. sage/structure/element.pyx +4584 -0
  233. sage/structure/element_wrapper.cp314-win_amd64.pyd +0 -0
  234. sage/structure/element_wrapper.pxd +12 -0
  235. sage/structure/element_wrapper.pyx +582 -0
  236. sage/structure/factorization.py +1457 -0
  237. sage/structure/factorization_integer.py +154 -0
  238. sage/structure/factory.cp314-win_amd64.pyd +0 -0
  239. sage/structure/factory.pyx +863 -0
  240. sage/structure/formal_sum.py +489 -0
  241. sage/structure/gens_py.py +73 -0
  242. sage/structure/global_options.py +1725 -0
  243. sage/structure/indexed_generators.py +863 -0
  244. sage/structure/list_clone.cp314-win_amd64.pyd +0 -0
  245. sage/structure/list_clone.pxd +65 -0
  246. sage/structure/list_clone.pyx +1867 -0
  247. sage/structure/list_clone_demo.cp314-win_amd64.pyd +0 -0
  248. sage/structure/list_clone_demo.pyx +248 -0
  249. sage/structure/list_clone_timings.py +179 -0
  250. sage/structure/list_clone_timings_cy.cp314-win_amd64.pyd +0 -0
  251. sage/structure/list_clone_timings_cy.pyx +86 -0
  252. sage/structure/mutability.cp314-win_amd64.pyd +0 -0
  253. sage/structure/mutability.pxd +21 -0
  254. sage/structure/mutability.pyx +346 -0
  255. sage/structure/nonexact.py +69 -0
  256. sage/structure/parent.cp314-win_amd64.pyd +0 -0
  257. sage/structure/parent.pxd +112 -0
  258. sage/structure/parent.pyx +3087 -0
  259. sage/structure/parent_base.cp314-win_amd64.pyd +0 -0
  260. sage/structure/parent_base.pxd +13 -0
  261. sage/structure/parent_base.pyx +35 -0
  262. sage/structure/parent_gens.cp314-win_amd64.pyd +0 -0
  263. sage/structure/parent_gens.pxd +22 -0
  264. sage/structure/parent_gens.pyx +374 -0
  265. sage/structure/parent_old.cp314-win_amd64.pyd +0 -0
  266. sage/structure/parent_old.pxd +24 -0
  267. sage/structure/parent_old.pyx +278 -0
  268. sage/structure/proof/__init__.py +1 -0
  269. sage/structure/proof/all.py +243 -0
  270. sage/structure/proof/proof.py +300 -0
  271. sage/structure/richcmp.cp314-win_amd64.pyd +0 -0
  272. sage/structure/richcmp.pxd +212 -0
  273. sage/structure/richcmp.pyx +494 -0
  274. sage/structure/sage_object.cp314-win_amd64.pyd +0 -0
  275. sage/structure/sage_object.pxd +3 -0
  276. sage/structure/sage_object.pyx +1088 -0
  277. sage/structure/sage_object_test.py +19 -0
  278. sage/structure/sequence.py +937 -0
  279. sage/structure/set_factories.py +1178 -0
  280. sage/structure/set_factories_example.py +527 -0
  281. sage/structure/support_view.py +164 -0
  282. sage/structure/test_factory.py +56 -0
  283. sage/structure/unique_representation.py +1443 -0
@@ -0,0 +1,2113 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ r"""
3
+ The coercion model
4
+
5
+ The coercion model manages how elements of one parent get related to elements
6
+ of another. For example, the integer 2 can canonically be viewed as an element
7
+ of the rational numbers. (The parent of a non-element is its Python type.)
8
+
9
+ ::
10
+
11
+ sage: ZZ(2).parent()
12
+ Integer Ring
13
+ sage: QQ(2).parent()
14
+ Rational Field
15
+
16
+ The most prominent role of the coercion model is to make sense of binary
17
+ operations between elements that have distinct parents. It does this by
18
+ finding a parent where both elements make sense, and doing the operation
19
+ there. For example::
20
+
21
+ sage: a = 1/2; a.parent()
22
+ Rational Field
23
+ sage: b = ZZ['x'].gen(); b.parent()
24
+ Univariate Polynomial Ring in x over Integer Ring
25
+ sage: a + b
26
+ x + 1/2
27
+ sage: (a + b).parent()
28
+ Univariate Polynomial Ring in x over Rational Field
29
+
30
+ If there is a coercion (see below) from one of the parents to the other,
31
+ the operation is always performed in the codomain of that coercion. Otherwise
32
+ a reasonable attempt to create a new parent with coercion maps from both
33
+ original parents is made. The results of these discoveries are cached.
34
+ On failure, a :exc:`TypeError` is always raised.
35
+
36
+ Some arithmetic operations (such as multiplication) can indicate an action
37
+ rather than arithmetic in a common parent. For example::
38
+
39
+ sage: # needs database_cremona_mini_ellcurve sage.schemes
40
+ sage: E = EllipticCurve('37a')
41
+ sage: P = E(0,0)
42
+ sage: 5*P
43
+ (1/4 : -5/8 : 1)
44
+
45
+ where there is action of `\ZZ` on the points of `E` given by the additive
46
+ group law. Parents can specify how they act on or are acted upon by other
47
+ parents.
48
+
49
+ There are two kinds of ways to get from one parent to another, coercions and
50
+ conversions.
51
+
52
+ Coercions are canonical (possibly modulo a finite number of
53
+ deterministic choices) morphisms, and the set of all coercions between
54
+ all parents forms a commuting diagram (modulo possibly rounding
55
+ issues). `\ZZ \rightarrow \QQ` is an example of a
56
+ coercion. These are invoked implicitly by the coercion model.
57
+
58
+ Conversions try to construct an element out of their input if at all possible.
59
+ Examples include sections of coercions, creating an element from a string or
60
+ list, etc. and may fail on some inputs of a given type while succeeding on
61
+ others (i.e. they may not be defined on the whole domain). Conversions are
62
+ always explicitly invoked, and never used by the coercion model to resolve
63
+ binary operations.
64
+
65
+ For more information on how to specify coercions, conversions, and actions,
66
+ see the documentation for :class:`Parent`.
67
+ """
68
+
69
+ # ****************************************************************************
70
+ # Copyright (C) 2007 Robert Bradshaw <robertwb@math.washington.edu>
71
+ #
72
+ # This program is free software: you can redistribute it and/or modify
73
+ # it under the terms of the GNU General Public License as published by
74
+ # the Free Software Foundation, either version 2 of the License, or
75
+ # (at your option) any later version.
76
+ # https://www.gnu.org/licenses/
77
+ # ****************************************************************************
78
+
79
+ from cpython.object cimport (PyTypeObject, PyObject_CallObject,
80
+ PyObject_RichCompare, Py_TYPE,
81
+ Py_EQ, Py_NE, Py_LT, Py_LE, Py_GT)
82
+ from cpython.weakref cimport PyWeakref_GET_OBJECT, PyWeakref_NewRef
83
+ from libc.string cimport strncmp
84
+ cimport gmpy2
85
+
86
+ cdef mul, truediv
87
+ from operator import mul, truediv
88
+
89
+ from sage.structure.richcmp cimport rich_to_bool, revop
90
+ from sage.structure.sage_object cimport SageObject
91
+ from sage.structure.parent cimport Parent_richcmp_element_without_coercion
92
+ from sage.structure.element cimport bin_op_exception, parent, Element
93
+ from sage.structure.coerce_exceptions import CoercionException
94
+ from sage.rings.integer_fake cimport is_Integer
95
+ from sage.categories.map cimport Map
96
+ from sage.categories.morphism import IdentityMorphism
97
+ from sage.categories.action cimport Action, PrecomposedAction
98
+ from sage.sets.pythonclass cimport Set_PythonType
99
+
100
+ import traceback
101
+
102
+ from fractions import Fraction
103
+ cdef type FractionType = <type>Fraction
104
+
105
+ cpdef py_scalar_parent(py_type):
106
+ """
107
+ Return the Sage equivalent of the given python type, if one exists.
108
+ If there is no equivalent, return ``None``.
109
+
110
+ EXAMPLES::
111
+
112
+ sage: from sage.structure.coerce import py_scalar_parent
113
+ sage: py_scalar_parent(int)
114
+ Integer Ring
115
+ sage: py_scalar_parent(float)
116
+ Real Double Field
117
+ sage: py_scalar_parent(complex) # needs sage.rings.complex_double
118
+ Complex Double Field
119
+ sage: py_scalar_parent(bool)
120
+ Integer Ring
121
+ sage: py_scalar_parent(dict),
122
+ (None,)
123
+
124
+ sage: import fractions
125
+ sage: py_scalar_parent(fractions.Fraction)
126
+ Rational Field
127
+
128
+ sage: # needs numpy
129
+ sage: import numpy
130
+ sage: py_scalar_parent(numpy.int16)
131
+ Integer Ring
132
+ sage: py_scalar_parent(numpy.int32)
133
+ Integer Ring
134
+ sage: py_scalar_parent(numpy.uint64)
135
+ Integer Ring
136
+ sage: py_scalar_parent(numpy.double)
137
+ Real Double Field
138
+
139
+ sage: import gmpy2
140
+ sage: py_scalar_parent(gmpy2.mpz)
141
+ Integer Ring
142
+ sage: py_scalar_parent(gmpy2.mpq)
143
+ Rational Field
144
+ sage: py_scalar_parent(gmpy2.mpfr)
145
+ Real Double Field
146
+ sage: py_scalar_parent(gmpy2.mpc) # needs sage.rings.complex_double
147
+ Complex Double Field
148
+
149
+ sage: # needs mpmath
150
+ sage: import mpmath
151
+ sage: py_scalar_parent(mpmath.mpf)
152
+ Real Double Field
153
+ sage: py_scalar_parent(mpmath.mpc) # needs sage.rings.complex_double
154
+ Complex Double Field
155
+ """
156
+ if issubclass(py_type, int):
157
+ import sage.rings.integer_ring
158
+ return sage.rings.integer_ring.ZZ
159
+ if py_type is FractionType:
160
+ import sage.rings.rational_field
161
+ return sage.rings.rational_field.QQ
162
+ if issubclass(py_type, float):
163
+ import sage.rings.real_double
164
+ return sage.rings.real_double.RDF
165
+ if issubclass(py_type, complex):
166
+ import sage.rings.complex_double
167
+ return sage.rings.complex_double.CDF
168
+ if is_numpy_type(py_type):
169
+ import numpy
170
+ if issubclass(py_type, numpy.integer):
171
+ import sage.rings.integer_ring
172
+ return sage.rings.integer_ring.ZZ
173
+ if issubclass(py_type, numpy.floating):
174
+ import sage.rings.real_double
175
+ return sage.rings.real_double.RDF
176
+ if issubclass(py_type, numpy.complexfloating):
177
+ import sage.rings.complex_double
178
+ return sage.rings.complex_double.CDF
179
+ return None
180
+ if issubclass(py_type, gmpy2.mpz):
181
+ import sage.rings.integer_ring
182
+ return sage.rings.integer_ring.ZZ
183
+ if issubclass(py_type, gmpy2.mpq):
184
+ import sage.rings.rational_field
185
+ return sage.rings.rational_field.QQ
186
+ if issubclass(py_type, gmpy2.mpfr):
187
+ import sage.rings.real_double
188
+ return sage.rings.real_double.RDF
189
+ if issubclass(py_type, gmpy2.mpc):
190
+ import sage.rings.complex_double
191
+ return sage.rings.complex_double.CDF
192
+ if is_mpmath_type(py_type):
193
+ import mpmath
194
+ if issubclass(py_type, mpmath.mpf):
195
+ from sage.rings.real_double import RDF
196
+ return RDF
197
+ if issubclass(py_type, mpmath.mpc):
198
+ from sage.rings.complex_double import CDF
199
+ return CDF
200
+ return None
201
+ return None
202
+
203
+ cpdef py_scalar_to_element(x):
204
+ """
205
+ Convert ``x`` to a Sage :class:`~sage.structure.element.Element` if possible.
206
+
207
+ If ``x`` was already an :class:`~sage.structure.element.Element` or if there is no obvious
208
+ conversion possible, just return ``x`` itself.
209
+
210
+ EXAMPLES::
211
+
212
+ sage: from sage.structure.coerce import py_scalar_to_element
213
+ sage: x = py_scalar_to_element(42)
214
+ sage: x, parent(x)
215
+ (42, Integer Ring)
216
+ sage: x = py_scalar_to_element(int(42))
217
+ sage: x, parent(x)
218
+ (42, Integer Ring)
219
+ sage: x = py_scalar_to_element(float(42))
220
+ sage: x, parent(x)
221
+ (42.0, Real Double Field)
222
+ sage: x = py_scalar_to_element(complex(42)) # needs sage.rings.complex_double
223
+ sage: x, parent(x) # needs sage.rings.complex_double
224
+ (42.0, Complex Double Field)
225
+ sage: py_scalar_to_element('hello')
226
+ 'hello'
227
+
228
+ sage: from fractions import Fraction
229
+ sage: f = Fraction(int(2^100), int(3^100))
230
+ sage: py_scalar_to_element(f)
231
+ 1267650600228229401496703205376/515377520732011331036461129765621272702107522001
232
+
233
+ Note that bools are converted to 0 or 1::
234
+
235
+ sage: py_scalar_to_element(False), py_scalar_to_element(True)
236
+ (0, 1)
237
+
238
+ Test gmpy2's types::
239
+
240
+ sage: import gmpy2
241
+ sage: x = py_scalar_to_element(gmpy2.mpz(42))
242
+ sage: x, parent(x)
243
+ (42, Integer Ring)
244
+ sage: x = py_scalar_to_element(gmpy2.mpq('3/4'))
245
+ sage: x, parent(x)
246
+ (3/4, Rational Field)
247
+ sage: x = py_scalar_to_element(gmpy2.mpfr(42.57))
248
+ sage: x, parent(x)
249
+ (42.57, Real Double Field)
250
+ sage: x = py_scalar_to_element(gmpy2.mpc(int(42), int(42))) # needs sage.rings.complex_double
251
+ sage: x, parent(x) # needs sage.rings.complex_double
252
+ (42.0 + 42.0*I, Complex Double Field)
253
+
254
+ Test compatibility with :func:`py_scalar_parent`::
255
+
256
+ sage: from sage.structure.coerce import py_scalar_parent
257
+ sage: elt = [True, int(42), float(42), complex(42)]
258
+ sage: for x in elt: # needs sage.rings.complex_double
259
+ ....: assert py_scalar_parent(type(x)) == py_scalar_to_element(x).parent()
260
+
261
+ sage: import numpy # needs numpy
262
+ sage: elt = [numpy.int8('-12'), numpy.uint8('143'), # needs numpy sage.symbolic
263
+ ....: numpy.int16('-33'), numpy.uint16('122'),
264
+ ....: numpy.int32('-19'), numpy.uint32('44'),
265
+ ....: numpy.int64('-3'), numpy.uint64('552'),
266
+ ....: numpy.float16('-1.23'), numpy.float32('-2.22'),
267
+ ....: numpy.float64('-3.412'), numpy.complex64(1.2+I),
268
+ ....: numpy.complex128(-2+I)]
269
+ sage: for x in elt: # needs numpy sage.symbolic
270
+ ....: assert py_scalar_parent(type(x)) == py_scalar_to_element(x).parent()
271
+
272
+ sage: elt = [gmpy2.mpz(42), gmpy2.mpq('3/4'),
273
+ ....: gmpy2.mpfr(42.57), gmpy2.mpc(int(42), int(42))]
274
+ sage: for x in elt: # needs sage.rings.complex_double
275
+ ....: assert py_scalar_parent(type(x)) == py_scalar_to_element(x).parent()
276
+ """
277
+ if isinstance(x, Element):
278
+ return x
279
+ elif isinstance(x, int):
280
+ from sage.rings.integer import Integer
281
+ return Integer(x)
282
+ elif type(x) is FractionType:
283
+ from sage.rings.rational import Rational
284
+ return Rational(x)
285
+ elif isinstance(x, float):
286
+ from sage.rings.real_double import RDF
287
+ return RDF(x)
288
+ elif isinstance(x, complex):
289
+ from sage.rings.complex_double import CDF
290
+ return CDF(x)
291
+ elif is_numpy_type(type(x)):
292
+ import numpy
293
+ if isinstance(x, numpy.integer):
294
+ from sage.rings.integer import Integer
295
+ return Integer(x)
296
+ elif isinstance(x, numpy.floating):
297
+ from sage.rings.real_double import RDF
298
+ return RDF(x)
299
+ elif isinstance(x, numpy.complexfloating):
300
+ from sage.rings.complex_double import CDF
301
+ return CDF(x)
302
+ else:
303
+ return x
304
+ elif type(x) is gmpy2.mpz:
305
+ from sage.rings.integer import Integer
306
+ return Integer(x)
307
+ elif type(x) is gmpy2.mpq:
308
+ from sage.rings.rational import Rational
309
+ return Rational(x)
310
+ elif type(x) is gmpy2.mpfr:
311
+ from sage.rings.real_double import RDF
312
+ return RDF(x)
313
+ elif type(x) is gmpy2.mpc:
314
+ from sage.rings.complex_double import CDF
315
+ return CDF(x)
316
+ else:
317
+ return x
318
+
319
+
320
+ cpdef bint parent_is_integers(P) except -1:
321
+ """
322
+ Check whether the type or parent represents the ring of integers.
323
+
324
+ EXAMPLES::
325
+
326
+ sage: from sage.structure.coerce import parent_is_integers
327
+ sage: parent_is_integers(int)
328
+ True
329
+ sage: parent_is_integers(float)
330
+ False
331
+ sage: parent_is_integers(bool)
332
+ True
333
+ sage: parent_is_integers(dict)
334
+ False
335
+
336
+ sage: import numpy # needs numpy
337
+ sage: parent_is_integers(numpy.int16) # needs numpy
338
+ True
339
+ sage: parent_is_integers(numpy.uint64) # needs numpy
340
+ True
341
+ sage: parent_is_integers(float)
342
+ False
343
+
344
+ sage: import gmpy2
345
+ sage: parent_is_integers(gmpy2.mpz)
346
+ True
347
+ sage: parent_is_integers(gmpy2.mpq)
348
+ False
349
+
350
+ Ensure (:issue:`27893`) is fixed::
351
+
352
+ sage: K.<f> = QQ[]
353
+ sage: gmpy2.mpz(2) * f
354
+ 2*f
355
+ """
356
+ if isinstance(P, type):
357
+ if issubclass(P, int):
358
+ return True
359
+ elif is_numpy_type(P):
360
+ from numpy import integer
361
+ return issubclass(P, integer)
362
+ elif issubclass(P, gmpy2.mpz):
363
+ return True
364
+ else:
365
+ return False
366
+ else:
367
+ from sage.rings.integer_ring import ZZ
368
+ return P is ZZ
369
+
370
+
371
+ def parent_is_numerical(P):
372
+ r"""
373
+ Test if elements of the parent or type ``P`` can be numerically evaluated
374
+ as complex numbers (in a canonical way).
375
+
376
+ EXAMPLES::
377
+
378
+ sage: from sage.structure.coerce import parent_is_numerical
379
+ sage: import gmpy2
380
+ sage: [parent_is_numerical(R) for R in [QQ, int, complex, gmpy2.mpc]] # needs sage.rings.complex_double
381
+ [True, True, True, True]
382
+ sage: [parent_is_numerical(R) for R in [RR, CC]] # needs sage.rings.real_mpfr
383
+ [True, True]
384
+ sage: parent_is_numerical(QuadraticField(-1)) # needs sage.rings.number_field
385
+ True
386
+ sage: import numpy; parent_is_numerical(numpy.complexfloating) # needs numpy
387
+ True
388
+ sage: parent_is_numerical(SR) # needs sage.symbolic
389
+ False
390
+ sage: [parent_is_numerical(R) for R in [QQ['x'], QQ[['x']], str]]
391
+ [False, False, False]
392
+ sage: [parent_is_numerical(R) for R in [RIF, RBF, CIF, CBF]] # needs sage.libs.flint
393
+ [False, False, False, False]
394
+ """
395
+ if not isinstance(P, Parent):
396
+ P = py_scalar_parent(P)
397
+ if P is None:
398
+ return False
399
+ return P._is_numerical()
400
+
401
+
402
+ def parent_is_real_numerical(P):
403
+ r"""
404
+ Test if elements of the parent or type ``P`` can be numerically evaluated
405
+ as real numbers (in a canonical way).
406
+
407
+ EXAMPLES::
408
+
409
+ sage: from sage.structure.coerce import parent_is_real_numerical
410
+ sage: import gmpy2
411
+ sage: [parent_is_real_numerical(R) for R in [RR, QQ, ZZ, RLF, int, float, gmpy2.mpq]]
412
+ [True, True, True, True, True, True, True]
413
+ sage: parent_is_real_numerical(QuadraticField(2)) # needs sage.rings.number_field
414
+ True
415
+ sage: import numpy; parent_is_real_numerical(numpy.integer) # needs numpy
416
+ True
417
+ sage: parent_is_real_numerical(QuadraticField(-1)) # needs sage.rings.number_field
418
+ False
419
+ sage: [parent_is_real_numerical(R) # needs numpy
420
+ ....: for R in [CC, complex, gmpy2.mpc, numpy.complexfloating]]
421
+ [False, False, False, False]
422
+ sage: [parent_is_real_numerical(R) for R in [QQ['x'], QQ[['x']], str]]
423
+ [False, False, False]
424
+ sage: parent_is_real_numerical(SR) # needs sage.symbolic
425
+ False
426
+ sage: [parent_is_real_numerical(R) for R in [RIF, RBF, CIF, CBF]] # needs sage.libs.flint
427
+ [False, False, False, False]
428
+ """
429
+ if not isinstance(P, Parent):
430
+ P = py_scalar_parent(P)
431
+ if P is None:
432
+ return False
433
+ return P._is_real_numerical()
434
+
435
+
436
+ cpdef bint is_numpy_type(t) noexcept:
437
+ """
438
+ Return ``True`` if and only if `t` is a type whose name starts
439
+ with ``numpy.``
440
+
441
+ EXAMPLES::
442
+
443
+ sage: from sage.structure.coerce import is_numpy_type
444
+
445
+ sage: # needs numpy
446
+ sage: import numpy
447
+ sage: is_numpy_type(numpy.int16)
448
+ True
449
+ sage: is_numpy_type(numpy.floating)
450
+ True
451
+ sage: is_numpy_type(numpy.ndarray)
452
+ True
453
+ sage: is_numpy_type(numpy.matrix)
454
+ True
455
+
456
+ sage: is_numpy_type(int)
457
+ False
458
+ sage: is_numpy_type(Integer)
459
+ False
460
+ sage: is_numpy_type(Sudoku) # needs sage.combinat
461
+ False
462
+ sage: is_numpy_type(None)
463
+ False
464
+
465
+ TESTS:
466
+
467
+ This used to crash Sage (:issue:`20715`)::
468
+
469
+ sage: is_numpy_type(object)
470
+ False
471
+ sage: 1 + object()
472
+ Traceback (most recent call last):
473
+ ...
474
+ TypeError: unsupported operand parent(s) for +: 'Integer Ring' and
475
+ '<class 'object'>'
476
+ """
477
+ if not isinstance(t, type):
478
+ return False
479
+ cdef PyTypeObject* T = <PyTypeObject*>t
480
+ if strncmp(T.tp_name, "numpy.", 6) == 0:
481
+ return True
482
+ # Check base type. This is needed to detect numpy.matrix.
483
+ if T.tp_base != NULL and strncmp(T.tp_base.tp_name, "numpy.", 6) == 0:
484
+ return True
485
+ return False
486
+
487
+
488
+ cpdef bint is_mpmath_type(t) noexcept:
489
+ r"""
490
+ Check whether the type ``t`` is a type whose name starts with ``mpmath.``
491
+
492
+ EXAMPLES::
493
+
494
+ sage: # needs mpmath
495
+ sage: from sage.structure.coerce import is_mpmath_type
496
+ sage: is_mpmath_type(int)
497
+ False
498
+ sage: import mpmath
499
+ sage: is_mpmath_type(mpmath.mpc(2))
500
+ False
501
+ sage: is_mpmath_type(type(mpmath.mpc(2)))
502
+ True
503
+ sage: is_mpmath_type(type(mpmath.mpf(2)))
504
+ True
505
+ """
506
+ return isinstance(t, type) and \
507
+ t.__module__.startswith("mpmath.")
508
+
509
+
510
+ cdef class CoercionModel:
511
+ """
512
+ See also :mod:`sage.categories.pushout`
513
+
514
+ EXAMPLES::
515
+
516
+ sage: f = ZZ['t', 'x'].0 + QQ['x'].0 + CyclotomicField(13).gen(); f # needs sage.rings.number_field
517
+ t + x + zeta13
518
+ sage: f.parent() # needs sage.rings.number_field
519
+ Multivariate Polynomial Ring in t, x
520
+ over Cyclotomic Field of order 13 and degree 12
521
+ sage: ZZ['x','y'].0 + ~Frac(QQ['y']).0
522
+ (x*y + 1)/y
523
+ sage: MatrixSpace(ZZ['x'], 2, 2)(2) + ~Frac(QQ['x']).0 # needs sage.modules
524
+ [(2*x + 1)/x 0]
525
+ [ 0 (2*x + 1)/x]
526
+ sage: f = ZZ['x,y,z'].0 + QQ['w,x,z,a'].0; f
527
+ w + x
528
+ sage: f.parent()
529
+ Multivariate Polynomial Ring in w, x, y, z, a over Rational Field
530
+ sage: ZZ['x,y,z'].0 + ZZ['w,x,z,a'].1
531
+ 2*x
532
+
533
+ TESTS:
534
+
535
+ Check that :issue:`8426` is fixed (see also :issue:`18076`)::
536
+
537
+ sage: import numpy # needs numpy
538
+ sage: if int(numpy.version.short_version[0]) > 1: # needs numpy
539
+ ....: __ = numpy.set_printoptions(legacy="1.25")
540
+
541
+ sage: # needs sage.rings.real_mpfr
542
+ sage: x = polygen(RR)
543
+ sage: numpy.float32('1.5') * x # needs numpy
544
+ 1.50000000000000*x
545
+ sage: x * numpy.float32('1.5') # needs numpy
546
+ 1.50000000000000*x
547
+ sage: p = x**3 + 2*x - 1
548
+ sage: p(float('1.2'))
549
+ 3.12800000000000
550
+ sage: p(int('2'))
551
+ 11.0000000000000
552
+
553
+ This used to fail (see :issue:`18076`)::
554
+
555
+ sage: 1/3 + numpy.int8('12') # needs numpy
556
+ 37/3
557
+ sage: -2/3 + numpy.int16('-2') # needs numpy
558
+ -8/3
559
+ sage: 2/5 + numpy.uint8('2') # needs numpy
560
+ 12/5
561
+
562
+ The numpy types do not interact well with the Sage coercion framework. More
563
+ precisely, if a numpy type is the first operand in a binary operation then
564
+ this operation is done in numpy. The result is hence a numpy type::
565
+
566
+ sage: numpy.uint8('2') + 3 # needs numpy
567
+ 5
568
+ sage: type(_) # needs numpy
569
+ <class 'numpy.int32'> # 32-bit
570
+ <class 'numpy.int64'> # 64-bit
571
+
572
+ sage: numpy.int8('12') + 1/3 # needs numpy
573
+ 12.333333333333334
574
+ sage: type(_) # needs numpy
575
+ <class 'numpy.float64'>
576
+
577
+ AUTHOR:
578
+
579
+ - Robert Bradshaw
580
+ """
581
+ def __init__(self):
582
+ """
583
+ EXAMPLES::
584
+
585
+ sage: from sage.structure.coerce import CoercionModel
586
+ sage: cm = CoercionModel()
587
+ sage: x = polygen(ZZ, 'x')
588
+ sage: K = NumberField(x^2 - 2, 'a') # needs sage.rings.number_field
589
+ sage: A = cm.get_action(ZZ, K, operator.mul) # needs sage.rings.number_field
590
+ sage: f, g = cm.coercion_maps(QQ, int)
591
+ sage: f, g = cm.coercion_maps(ZZ, int)
592
+ """
593
+ self.reset_cache()
594
+
595
+ def reset_cache(self):
596
+ """
597
+ Clear the coercion cache.
598
+
599
+ This should have no impact on the result of arithmetic operations, as
600
+ the exact same coercions and actions will be re-discovered when needed.
601
+
602
+ It may be useful for debugging, and may also free some memory.
603
+
604
+ EXAMPLES::
605
+
606
+ sage: cm = sage.structure.element.get_coercion_model()
607
+ sage: len(cm.get_cache()[0]) # random
608
+ 42
609
+ sage: cm.reset_cache()
610
+ sage: cm.get_cache()
611
+ ({}, {})
612
+ """
613
+ # This MUST be a mapping of tuples, where each
614
+ # tuple contains at least two elements that are either
615
+ # None or of type Map.
616
+ self._coercion_maps = TripleDict()
617
+ # This MUST be a mapping to actions.
618
+ self._action_maps = TripleDict()
619
+ # This is a mapping from Parents to Parents, storing the result of division in the given parent.
620
+ self._division_parents = TripleDict()
621
+
622
+ def get_cache(self):
623
+ """
624
+ This returns the current cache of coercion maps and actions, primarily
625
+ useful for debugging and introspection.
626
+
627
+ EXAMPLES::
628
+
629
+ sage: cm = sage.structure.element.get_coercion_model()
630
+ sage: cm.canonical_coercion(1, 2/3)
631
+ (1, 2/3)
632
+ sage: maps, actions = cm.get_cache()
633
+
634
+ Now let us see what happens when we do a binary operations with
635
+ an integer and a rational::
636
+
637
+ sage: left_morphism_ref, right_morphism_ref = maps[ZZ, QQ]
638
+
639
+ Note that by :issue:`14058` the coercion model only stores a weak
640
+ reference to the coercion maps in this case::
641
+
642
+ sage: left_morphism_ref
643
+ <weakref at ...; to 'sage.rings.rational.Z_to_Q' at ...>
644
+
645
+ Moreover, the weakly referenced coercion map uses only a weak
646
+ reference to the codomain::
647
+
648
+ sage: left_morphism_ref()
649
+ (map internal to coercion system -- copy before use)
650
+ Natural morphism:
651
+ From: Integer Ring
652
+ To: Rational Field
653
+
654
+ To get an actual valid map, we simply copy the weakly referenced
655
+ coercion map::
656
+
657
+ sage: print(copy(left_morphism_ref()))
658
+ Natural morphism:
659
+ From: Integer Ring
660
+ To: Rational Field
661
+ sage: print(right_morphism_ref)
662
+ None
663
+
664
+ We can see that it coerces the left operand from an integer to a
665
+ rational, and doesn't do anything to the right.
666
+
667
+ Now for some actions::
668
+
669
+ sage: R.<x> = ZZ['x']
670
+ sage: 1/2 * x
671
+ 1/2*x
672
+ sage: maps, actions = cm.get_cache()
673
+ sage: act = actions[QQ, R, operator.mul]; act
674
+ Left scalar multiplication by Rational Field
675
+ on Univariate Polynomial Ring in x over Integer Ring
676
+ sage: act.actor()
677
+ Rational Field
678
+ sage: act.domain()
679
+ Univariate Polynomial Ring in x over Integer Ring
680
+ sage: act.codomain()
681
+ Univariate Polynomial Ring in x over Rational Field
682
+ sage: act(1/5, x+10)
683
+ 1/5*x + 2
684
+ """
685
+ d1 = {(S, R): mors for (S, R, op), mors in self._coercion_maps.items()}
686
+ d2 = self._action_maps.copy()
687
+ return d1, d2
688
+
689
+ def record_exceptions(self, bint value=True):
690
+ r"""
691
+ Enables (or disables) recording of the exceptions suppressed during
692
+ arithmetic.
693
+
694
+ Each time that record_exceptions is called (either enabling or disabling
695
+ the record), the exception_stack is cleared.
696
+
697
+ TESTS::
698
+
699
+ sage: cm = sage.structure.element.get_coercion_model()
700
+ sage: cm.record_exceptions()
701
+ sage: cm._test_exception_stack()
702
+ sage: cm.exception_stack()
703
+ ['Traceback (most recent call last):\n File "...coerce.pyx", line ...TypeError: just a test']
704
+ sage: cm.record_exceptions(False)
705
+ sage: cm._test_exception_stack()
706
+ sage: cm.exception_stack()
707
+ []
708
+ """
709
+ self._record_exceptions = value
710
+ self._exceptions_cleared = True
711
+ self._exception_stack = []
712
+
713
+ cpdef _record_exception(self):
714
+ r"""
715
+ Push the last exception that occurred onto the stack for later reference,
716
+ for internal use.
717
+
718
+ If the stack has not yet been flagged as cleared, we clear it now (rather
719
+ than wasting time to do so for successful operations).
720
+
721
+ TESTS::
722
+
723
+ sage: cm = sage.structure.element.get_coercion_model()
724
+ sage: cm.record_exceptions()
725
+ sage: 1 + 1/2 + 2 # make sure there aren't any errors hanging around
726
+ 7/2
727
+ sage: cm.exception_stack()
728
+ []
729
+ sage: cm._test_exception_stack()
730
+ sage: cm.exception_stack()
731
+ ['Traceback (most recent call last):\n File "...coerce.pyx", line ...TypeError: just a test']
732
+
733
+ The function _test_exception_stack is executing the following code::
734
+
735
+ try:
736
+ raise TypeError("just a test")
737
+ except TypeError:
738
+ cm._record_exception()
739
+ """
740
+ if not self._record_exceptions:
741
+ return
742
+ if not self._exceptions_cleared:
743
+ self._exception_stack = []
744
+ self._exceptions_cleared = True
745
+ self._exception_stack.append(traceback.format_exc().strip())
746
+
747
+ def _test_exception_stack(self):
748
+ r"""
749
+ A function to test the exception stack.
750
+
751
+ EXAMPLES::
752
+
753
+ sage: cm = sage.structure.element.get_coercion_model()
754
+ sage: cm.record_exceptions()
755
+ sage: 1 + 1/11 # make sure there aren't any errors hanging around
756
+ 12/11
757
+ sage: cm.exception_stack()
758
+ []
759
+ sage: cm._test_exception_stack()
760
+ sage: cm.exception_stack()
761
+ ['Traceback (most recent call last):\n File "...coerce.pyx", line ...TypeError: just a test']
762
+ """
763
+ try:
764
+ raise TypeError("just a test")
765
+ except TypeError:
766
+ self._record_exception()
767
+
768
+ def exception_stack(self):
769
+ r"""
770
+ Return the list of exceptions that were caught in the course of
771
+ executing the last binary operation. Useful for diagnosis when
772
+ user-defined maps or actions raise exceptions that are caught in
773
+ the course of coercion detection.
774
+
775
+ If all went well, this should be the empty list. If things aren't
776
+ happening as you expect, this is a good place to check. See also
777
+ :func:`coercion_traceback`.
778
+
779
+ EXAMPLES::
780
+
781
+ sage: cm = sage.structure.element.get_coercion_model()
782
+ sage: cm.record_exceptions()
783
+ sage: 1/2 + 2
784
+ 5/2
785
+ sage: cm.exception_stack()
786
+ []
787
+ sage: 1/2 + GF(3)(2)
788
+ Traceback (most recent call last):
789
+ ...
790
+ TypeError: unsupported operand parent(s) for +:
791
+ 'Rational Field' and 'Finite Field of size 3'
792
+
793
+ Now see what the actual problem was::
794
+
795
+ sage: import traceback
796
+ sage: cm.exception_stack()
797
+ ['Traceback (most recent call last):...', 'Traceback (most recent call last):...']
798
+ sage: print(cm.exception_stack()[-1])
799
+ Traceback (most recent call last):
800
+ ...
801
+ TypeError: no common canonical parent for objects with parents:
802
+ 'Rational Field' and 'Finite Field of size 3'
803
+
804
+ This is typically accessed via the :func:`coercion_traceback` function.
805
+
806
+ ::
807
+
808
+ sage: coercion_traceback()
809
+ Traceback (most recent call last):
810
+ ...
811
+ TypeError: no common canonical parent for objects with parents:
812
+ 'Rational Field' and 'Finite Field of size 3'
813
+ """
814
+ if not self._exceptions_cleared:
815
+ self._exception_stack = []
816
+ self._exceptions_cleared = True
817
+ return self._exception_stack
818
+
819
+ def explain(self, xp, yp, op=mul, int verbosity=2):
820
+ """
821
+ This function can be used to understand what coercions will happen
822
+ for an arithmetic operation between xp and yp (which may be either
823
+ elements or parents). If the parent of the result can be determined
824
+ then it will be returned.
825
+
826
+ For programmatic usages, use :meth:`canonical_coercion` and
827
+ :meth:`common_parent` instead.
828
+
829
+ EXAMPLES::
830
+
831
+ sage: cm = sage.structure.element.get_coercion_model()
832
+
833
+ sage: cm.explain(ZZ, ZZ)
834
+ Identical parents, arithmetic performed immediately.
835
+ Result lives in Integer Ring
836
+ Integer Ring
837
+
838
+ sage: cm.explain(QQ, int)
839
+ Coercion on right operand via
840
+ Native morphism:
841
+ From: Set of Python objects of class 'int'
842
+ To: Rational Field
843
+ Arithmetic performed after coercions.
844
+ Result lives in Rational Field
845
+ Rational Field
846
+
847
+ sage: R = ZZ['x']
848
+ sage: cm.explain(R, QQ)
849
+ Action discovered.
850
+ Right scalar multiplication by Rational Field
851
+ on Univariate Polynomial Ring in x over Integer Ring
852
+ Result lives in Univariate Polynomial Ring in x over Rational Field
853
+ Univariate Polynomial Ring in x over Rational Field
854
+
855
+ sage: cm.explain(ZZ['x'], QQ, operator.add)
856
+ Coercion on left operand via
857
+ Ring morphism:
858
+ From: Univariate Polynomial Ring in x over Integer Ring
859
+ To: Univariate Polynomial Ring in x over Rational Field
860
+ Defn: Induced from base ring by
861
+ Natural morphism:
862
+ From: Integer Ring
863
+ To: Rational Field
864
+ Coercion on right operand via
865
+ Polynomial base injection morphism:
866
+ From: Rational Field
867
+ To: Univariate Polynomial Ring in x over Rational Field
868
+ Arithmetic performed after coercions.
869
+ Result lives in Univariate Polynomial Ring in x over Rational Field
870
+ Univariate Polynomial Ring in x over Rational Field
871
+
872
+ Sometimes with non-sage types there is not enough information to deduce
873
+ what will actually happen::
874
+
875
+ sage: R100 = RealField(100) # needs sage.rings.real_mpfr
876
+ sage: cm.explain(R100, float, operator.add) # needs sage.rings.real_mpfr
877
+ Right operand is numeric, will attempt coercion in both directions.
878
+ Unknown result parent.
879
+ sage: parent(R100(1) + float(1)) # needs sage.rings.real_mpfr
880
+ <class 'float'>
881
+ sage: cm.explain(QQ, float, operator.add)
882
+ Right operand is numeric, will attempt coercion in both directions.
883
+ Unknown result parent.
884
+ sage: parent(QQ(1) + float(1))
885
+ <class 'float'>
886
+
887
+ Special care is taken to deal with division::
888
+
889
+ sage: cm.explain(ZZ, ZZ, operator.truediv)
890
+ Identical parents, arithmetic performed immediately.
891
+ Result lives in Rational Field
892
+ Rational Field
893
+
894
+ sage: ZZx = ZZ['x']
895
+ sage: QQx = QQ['x']
896
+ sage: cm.explain(ZZx, QQx, operator.truediv)
897
+ Coercion on left operand via
898
+ Ring morphism:
899
+ From: Univariate Polynomial Ring in x over Integer Ring
900
+ To: Univariate Polynomial Ring in x over Rational Field
901
+ Defn: Induced from base ring by
902
+ Natural morphism:
903
+ From: Integer Ring
904
+ To: Rational Field
905
+ Arithmetic performed after coercions.
906
+ Result lives in Fraction Field of Univariate Polynomial Ring in x over Rational Field
907
+ Fraction Field of Univariate Polynomial Ring in x over Rational Field
908
+
909
+ sage: cm.explain(int, ZZ, operator.truediv)
910
+ Coercion on left operand via
911
+ Native morphism:
912
+ From: Set of Python objects of class 'int'
913
+ To: Integer Ring
914
+ Arithmetic performed after coercions.
915
+ Result lives in Rational Field
916
+ Rational Field
917
+
918
+ sage: cm.explain(ZZx, ZZ, operator.truediv)
919
+ Action discovered.
920
+ Right inverse action by Rational Field
921
+ on Univariate Polynomial Ring in x over Integer Ring
922
+ with precomposition on right by Natural morphism:
923
+ From: Integer Ring
924
+ To: Rational Field
925
+ Result lives in Univariate Polynomial Ring in x over Rational Field
926
+ Univariate Polynomial Ring in x over Rational Field
927
+
928
+ .. NOTE::
929
+
930
+ This function is accurate only in so far as :meth:`analyse` is kept
931
+ in sync with the :meth:`bin_op` and
932
+ :meth:`canonical_coercion` which are kept separate for
933
+ maximal efficiency.
934
+ """
935
+ all, res = self.analyse(xp, yp, op)
936
+ indent = " " * 4
937
+ if verbosity >= 2:
938
+ print("\n".join(s if isinstance(s, str)
939
+ else (indent + repr(s).replace("\n", "\n" + indent))
940
+ for s in all))
941
+ elif verbosity >= 1:
942
+ print("\n".join(s for s in all if isinstance(s, str)))
943
+ if verbosity >= 1:
944
+ if res is None:
945
+ print("Unknown result parent.")
946
+ else:
947
+ print("Result lives in {}".format(res))
948
+ return res
949
+
950
+ cpdef analyse(self, xp, yp, op=mul):
951
+ """
952
+ Emulate the process of doing arithmetic between xp and yp, returning
953
+ a list of steps and the parent that the result will live in.
954
+
955
+ The :meth:`explain` method is easier to use, but if one wants access to
956
+ the actual morphism and action objects (rather than their string
957
+ representations), then this is the function to use.
958
+
959
+ For programmatic usages, use :meth:`canonical_coercion` and
960
+ :meth:`common_parent` instead.
961
+
962
+ EXAMPLES::
963
+
964
+ sage: cm = sage.structure.element.get_coercion_model()
965
+ sage: GF7 = GF(7)
966
+ sage: steps, res = cm.analyse(GF7, ZZ)
967
+ sage: steps
968
+ ['Coercion on right operand via',
969
+ Natural morphism:
970
+ From: Integer Ring
971
+ To: Finite Field of size 7,
972
+ 'Arithmetic performed after coercions.']
973
+ sage: res
974
+ Finite Field of size 7
975
+ sage: f = steps[1]; type(f)
976
+ <class 'sage.rings.finite_rings.integer_mod.Integer_to_IntegerMod'>
977
+ sage: f(100)
978
+ 2
979
+ """
980
+ self._exceptions_cleared = False
981
+ res = None
982
+ if not isinstance(xp, type) and not isinstance(xp, Parent):
983
+ xp = parent(xp)
984
+ if not isinstance(yp, type) and not isinstance(yp, Parent):
985
+ yp = parent(yp)
986
+
987
+ all = []
988
+ if xp is yp:
989
+ all.append("Identical parents, arithmetic performed immediately." % xp)
990
+ if op is truediv and isinstance(xp, Parent):
991
+ xp = self.division_parent(xp)
992
+ return all, xp
993
+ if xp == yp:
994
+ all.append("Equal but distinct parents.")
995
+
996
+ action = self.get_action(xp, yp, op)
997
+ if action is not None:
998
+ all.append("Action discovered.")
999
+ all.append(action)
1000
+ return all, action.codomain()
1001
+
1002
+ homs = self.discover_coercion(xp, yp)
1003
+ if homs is not None:
1004
+ x_mor, y_mor = homs
1005
+ if x_mor is not None:
1006
+ x_mor = x_mor.__copy__()
1007
+ all.append("Coercion on left operand via")
1008
+ all.append(x_mor)
1009
+ res = x_mor.codomain()
1010
+ if y_mor is not None:
1011
+ y_mor = y_mor.__copy__()
1012
+ all.append("Coercion on right operand via")
1013
+ all.append(y_mor)
1014
+ if res is not None and res is not y_mor.codomain():
1015
+ raise RuntimeError("BUG in coercion model: codomains not equal", x_mor, y_mor)
1016
+ res = y_mor.codomain()
1017
+ all.append("Arithmetic performed after coercions.")
1018
+ if op is truediv and isinstance(res, Parent):
1019
+ res = self.division_parent(res)
1020
+ return all, res
1021
+
1022
+ if isinstance(yp, Parent) and xp in [int, float, complex, bool]:
1023
+ mor = yp._internal_coerce_map_from(xp)
1024
+ if mor is not None:
1025
+ mor = mor.__copy__()
1026
+ all.append("Coercion on numeric left operand via")
1027
+ all.append(mor)
1028
+ if op is truediv and isinstance(yp, Parent):
1029
+ yp = self.division_parent(yp)
1030
+ return all, yp
1031
+ all.append("Left operand is numeric, will attempt coercion in both directions.")
1032
+ elif type(xp) is type:
1033
+ all.append("Left operand is not Sage element, will try _sage_.")
1034
+
1035
+ if isinstance(xp, Parent) and yp in [int, float, complex, bool]:
1036
+ mor = xp._internal_coerce_map_from(yp)
1037
+ if mor is not None:
1038
+ mor = mor.__copy__()
1039
+ all.append("Coercion on numeric right operand via")
1040
+ all.append(mor)
1041
+ if op is truediv and isinstance(xp, Parent):
1042
+ xp = self.division_parent(xp)
1043
+ return all, xp
1044
+ all.append("Right operand is numeric, will attempt coercion in both directions.")
1045
+ elif type(yp) is type:
1046
+ all.append("Right operand is not Sage element, will try _sage_.")
1047
+
1048
+ return all, None
1049
+
1050
+ def common_parent(self, *args):
1051
+ """
1052
+ Compute a common parent for all the inputs.
1053
+
1054
+ It's essentially an `n`-ary canonical coercion except it can
1055
+ operate on parents rather than just elements.
1056
+
1057
+ INPUT:
1058
+
1059
+ - ``args`` -- set of elements and/or parents
1060
+
1061
+ OUTPUT:
1062
+
1063
+ A :class:`Parent` into which each input should coerce, or raises a
1064
+ :exc:`TypeError` if no such :class:`Parent` can be found.
1065
+
1066
+ EXAMPLES::
1067
+
1068
+ sage: cm = sage.structure.element.get_coercion_model()
1069
+ sage: cm.common_parent(ZZ, QQ)
1070
+ Rational Field
1071
+ sage: cm.common_parent(ZZ, QQ, RR) # needs sage.rings.real_mpfr
1072
+ Real Field with 53 bits of precision
1073
+ sage: ZZT = ZZ[['T']]
1074
+ sage: QQT = QQ['T']
1075
+ sage: cm.common_parent(ZZT, QQT, RDF)
1076
+ Power Series Ring in T over Real Double Field
1077
+ sage: cm.common_parent(4r, 5r)
1078
+ <class 'int'>
1079
+ sage: cm.common_parent(int, float, ZZ)
1080
+ <class 'float'>
1081
+ sage: real_fields = [RealField(prec) for prec in [10,20..100]] # needs sage.rings.real_mpfr
1082
+ sage: cm.common_parent(*real_fields) # needs sage.rings.real_mpfr
1083
+ Real Field with 10 bits of precision
1084
+
1085
+ There are some cases where the ordering does matter, but if a parent
1086
+ can be found it is always the same::
1087
+
1088
+ sage: QQxy = QQ['x,y']
1089
+ sage: QQyz = QQ['y,z']
1090
+ sage: cm.common_parent(QQxy, QQyz) == cm.common_parent(QQyz, QQxy)
1091
+ True
1092
+ sage: QQzt = QQ['z,t']
1093
+ sage: cm.common_parent(QQxy, QQyz, QQzt)
1094
+ Multivariate Polynomial Ring in x, y, z, t over Rational Field
1095
+ sage: cm.common_parent(QQxy, QQzt, QQyz)
1096
+ Traceback (most recent call last):
1097
+ ...
1098
+ TypeError: no common canonical parent for objects with parents:
1099
+ 'Multivariate Polynomial Ring in x, y over Rational Field' and
1100
+ 'Multivariate Polynomial Ring in z, t over Rational Field'
1101
+ """
1102
+ base = None
1103
+ for x in args:
1104
+ if not isinstance(x, Parent) and not isinstance(x, type):
1105
+ x = parent(x)
1106
+ if base is None:
1107
+ base = x
1108
+ if isinstance(base, Parent) and (<Parent>base).has_coerce_map_from(x):
1109
+ continue
1110
+ elif isinstance(x, Parent) and (<Parent>x).has_coerce_map_from(base):
1111
+ base = x
1112
+ else:
1113
+ a = base.an_element() if isinstance(base, Parent) else base(1)
1114
+ b = x.an_element() if isinstance(x, Parent) else x(1)
1115
+ base = parent(self.canonical_coercion(a, b)[0])
1116
+ return base
1117
+
1118
+ cpdef division_parent(self, Parent P):
1119
+ r"""
1120
+ Deduces where the result of division in ``P`` lies by
1121
+ calculating the inverse of ``P.one()`` or ``P.an_element()``.
1122
+
1123
+ The result is cached.
1124
+
1125
+ EXAMPLES::
1126
+
1127
+ sage: cm = sage.structure.element.get_coercion_model()
1128
+ sage: cm.division_parent(ZZ)
1129
+ Rational Field
1130
+ sage: cm.division_parent(QQ)
1131
+ Rational Field
1132
+ sage: ZZx = ZZ['x']
1133
+ sage: cm.division_parent(ZZx)
1134
+ Fraction Field of Univariate Polynomial Ring in x over Integer Ring
1135
+ sage: K = GF(41)
1136
+ sage: cm.division_parent(K)
1137
+ Finite Field of size 41
1138
+ sage: Zmod100 = Integers(100)
1139
+ sage: cm.division_parent(Zmod100)
1140
+ Ring of integers modulo 100
1141
+ sage: S5 = SymmetricGroup(5) # needs sage.groups
1142
+ sage: cm.division_parent(S5) # needs sage.groups
1143
+ Symmetric group of order 5! as a permutation group
1144
+ """
1145
+ try:
1146
+ return self._division_parents.get(P, None, None)
1147
+ except KeyError:
1148
+ pass
1149
+ try:
1150
+ ret = parent(~P.one())
1151
+ except Exception:
1152
+ self._record_exception()
1153
+ ret = parent(~P.an_element())
1154
+ self._division_parents.set(P, None, None, ret)
1155
+ return ret
1156
+
1157
+ cpdef bin_op(self, x, y, op):
1158
+ """
1159
+ Execute the operation ``op`` on `x` and `y`.
1160
+
1161
+ It first looks for an action
1162
+ corresponding to ``op``, and failing that, it tries to coerce `x` and `y`
1163
+ into a common parent and calls ``op`` on them.
1164
+
1165
+ If it cannot make sense of the operation, a :exc:`TypeError` is raised.
1166
+
1167
+ INPUT:
1168
+
1169
+ - ``x`` -- the left operand
1170
+
1171
+ - ``y`` -- the right operand
1172
+
1173
+ - ``op`` -- a python function taking 2 arguments
1174
+
1175
+ .. NOTE::
1176
+
1177
+ ``op`` is often an arithmetic operation, but need not be so.
1178
+
1179
+ EXAMPLES::
1180
+
1181
+ sage: cm = sage.structure.element.get_coercion_model()
1182
+ sage: cm.bin_op(1/2, 5, operator.mul)
1183
+ 5/2
1184
+
1185
+ The operator can be any callable::
1186
+
1187
+ sage: R.<x> = ZZ['x']
1188
+ sage: cm.bin_op(x^2 - 1, x + 1, gcd)
1189
+ x + 1
1190
+
1191
+ Actions are detected and performed::
1192
+
1193
+ sage: M = matrix(ZZ, 2, 2, range(4)) # needs sage.modules
1194
+ sage: V = vector(ZZ, [5,7]) # needs sage.modules
1195
+ sage: cm.bin_op(M, V, operator.mul) # needs sage.modules
1196
+ (7, 31)
1197
+
1198
+ TESTS::
1199
+
1200
+ sage: class Foo():
1201
+ ....: def __rmul__(self, left):
1202
+ ....: return 'hello'
1203
+ sage: H = Foo()
1204
+ sage: print(int(3)*H)
1205
+ hello
1206
+ sage: print(Integer(3)*H)
1207
+ hello
1208
+ sage: print(H*3)
1209
+ Traceback (most recent call last):
1210
+ ...
1211
+ TypeError: unsupported operand parent(s) for *: '<class '__main__.Foo'>' and 'Integer Ring'
1212
+
1213
+ sage: class Nonsense():
1214
+ ....: def __init__(self, s):
1215
+ ....: self.s = s
1216
+ ....: def __repr__(self):
1217
+ ....: return self.s
1218
+ ....: def __mul__(self, x):
1219
+ ....: return Nonsense(self.s + chr(x%256))
1220
+ ....: __add__ = __mul__
1221
+ ....: def __rmul__(self, x):
1222
+ ....: return Nonsense(chr(x%256) + self.s)
1223
+ ....: __radd__ = __rmul__
1224
+ sage: a = Nonsense('blahblah')
1225
+ sage: a*80
1226
+ blahblahP
1227
+ sage: 80*a
1228
+ Pblahblah
1229
+ sage: a+80
1230
+ blahblahP
1231
+ sage: 80+a
1232
+ Pblahblah
1233
+ """
1234
+ self._exceptions_cleared = False
1235
+
1236
+ # If parents are equal, we can just call op()
1237
+ xp = parent(x)
1238
+ yp = parent(y)
1239
+ if xp is yp:
1240
+ return op(x,y)
1241
+
1242
+ # Actions take preference over common-parent coercions
1243
+ try:
1244
+ action = self._action_maps.get(xp, yp, op)
1245
+ except KeyError:
1246
+ action = self.get_action(xp, yp, op, x, y)
1247
+ if action is not None:
1248
+ if (<Action>action)._is_left:
1249
+ return (<Action>action)._act_(x, y)
1250
+ else:
1251
+ return (<Action>action)._act_(y, x)
1252
+
1253
+ # Now coerce to a common parent and do the operation there
1254
+ try:
1255
+ xy = self.canonical_coercion(x, y)
1256
+ except TypeError:
1257
+ self._record_exception()
1258
+ else:
1259
+ return PyObject_CallObject(op, xy)
1260
+
1261
+ if op is mul:
1262
+ # elements may also act on non-elements
1263
+ # (e.g. sequences or parents)
1264
+ if not isinstance(y, Element) or not isinstance(x, Element):
1265
+ try:
1266
+ if hasattr(x, '_act_on_'):
1267
+ res = x._act_on_(y, True)
1268
+ if res is not None: return res
1269
+ except CoercionException:
1270
+ self._record_exception()
1271
+
1272
+ try:
1273
+ if hasattr(x, '_acted_upon_'):
1274
+ res = x._acted_upon_(y, True)
1275
+ if res is not None: return res
1276
+ except CoercionException:
1277
+ self._record_exception()
1278
+
1279
+ try:
1280
+ if hasattr(y, '_act_on_'):
1281
+ res = y._act_on_(x, False)
1282
+ if res is not None: return res
1283
+ except CoercionException:
1284
+ self._record_exception()
1285
+
1286
+ try:
1287
+ if hasattr(y, '_acted_upon_'):
1288
+ res = y._acted_upon_(x, False)
1289
+ if res is not None: return res
1290
+ except CoercionException:
1291
+ self._record_exception()
1292
+
1293
+ if not isinstance(y, Element):
1294
+ op_name = op.__name__
1295
+ mul_method = getattr(y, '__r%s__' % op_name, None)
1296
+ if mul_method is not None:
1297
+ res = mul_method(x)
1298
+ if res is not None and res is not NotImplemented:
1299
+ return res
1300
+
1301
+ # We should really include the underlying error.
1302
+ # This causes so much headache.
1303
+ raise bin_op_exception(op, x, y)
1304
+
1305
+ cpdef canonical_coercion(self, x, y):
1306
+ r"""
1307
+ Given two elements `x` and `y`, with parents `S` and `R` respectively,
1308
+ find a common parent `Z` such that there are coercions
1309
+ `f: S \to Z` and `g: R \to Z` and return `f(x), g(y)`,
1310
+ which will have the same parent.
1311
+
1312
+ Raises a type error if no such `Z` can be found.
1313
+
1314
+ EXAMPLES::
1315
+
1316
+ sage: cm = sage.structure.element.get_coercion_model()
1317
+ sage: cm.canonical_coercion(mod(2, 10), 17)
1318
+ (2, 7)
1319
+
1320
+ sage: # needs sage.modules
1321
+ sage: x, y = cm.canonical_coercion(1/2, matrix(ZZ, 2, 2, range(4)))
1322
+ sage: x
1323
+ [1/2 0]
1324
+ [ 0 1/2]
1325
+ sage: y
1326
+ [0 1]
1327
+ [2 3]
1328
+ sage: parent(x) is parent(y)
1329
+ True
1330
+
1331
+ There is some support for non-Sage datatypes as well::
1332
+
1333
+ sage: x, y = cm.canonical_coercion(int(5), 10)
1334
+ sage: type(x), type(y)
1335
+ (<class 'sage.rings.integer.Integer'>, <class 'sage.rings.integer.Integer'>)
1336
+
1337
+ sage: x, y = cm.canonical_coercion(int(5), complex(3))
1338
+ sage: type(x), type(y)
1339
+ (<class 'complex'>, <class 'complex'>)
1340
+
1341
+ sage: class MyClass:
1342
+ ....: def _sage_(self):
1343
+ ....: return 13
1344
+ sage: a, b = cm.canonical_coercion(MyClass(), 1/3)
1345
+ sage: a, b
1346
+ (13, 1/3)
1347
+ sage: type(a)
1348
+ <class 'sage.rings.rational.Rational'>
1349
+
1350
+ We also make an exception for 0, even if `\ZZ` does not map in::
1351
+
1352
+ sage: canonical_coercion(vector([1, 2, 3]), 0) # needs sage.modules
1353
+ ((1, 2, 3), (0, 0, 0))
1354
+ sage: canonical_coercion(GF(5)(0), float(0))
1355
+ (0, 0)
1356
+ """
1357
+ xp = parent(x)
1358
+ yp = parent(y)
1359
+ if xp is yp:
1360
+ return x,y
1361
+
1362
+ cdef Element x_elt, y_elt
1363
+ coercions = self.coercion_maps(xp, yp)
1364
+ if coercions is not None:
1365
+ x_map, y_map = coercions
1366
+ if x_map is not None:
1367
+ x_elt = (<Map>x_map)._call_(x)
1368
+ else:
1369
+ x_elt = x
1370
+ if y_map is not None:
1371
+ y_elt = (<Map>y_map)._call_(y)
1372
+ else:
1373
+ y_elt = y
1374
+ if x_elt is None:
1375
+ raise RuntimeError("BUG in map, returned None %s %s %s" % (x, type(x_map), x_map))
1376
+ elif y_elt is None:
1377
+ raise RuntimeError("BUG in map, returned None %s %s %s" % (y, type(y_map), y_map))
1378
+ if x_elt._parent is y_elt._parent:
1379
+ # We must verify this as otherwise we are prone to
1380
+ # getting into an infinite loop in c, and the above
1381
+ # maps may be written by (imperfect) users.
1382
+ return x_elt,y_elt
1383
+ elif x_elt._parent == y_elt._parent:
1384
+ # TODO: Non-uniqueness of parents strikes again!
1385
+ y_elt = parent(x_elt)(y_elt)
1386
+ if x_elt._parent is y_elt._parent:
1387
+ return x_elt,y_elt
1388
+ self._coercion_error(x, x_map, x_elt, y, y_map, y_elt)
1389
+
1390
+ cdef bint x_numeric = isinstance(x, (int, float, complex))
1391
+ cdef bint y_numeric = isinstance(y, (int, float, complex))
1392
+
1393
+ if not x_numeric and is_numpy_type(type(x)):
1394
+ import numpy
1395
+ x_numeric = isinstance(x, numpy.number)
1396
+ if not y_numeric and is_numpy_type(type(y)):
1397
+ import numpy
1398
+ y_numeric = isinstance(y, numpy.number)
1399
+
1400
+ if x_numeric and y_numeric:
1401
+ ty = type(x + y)
1402
+ return ty(x), ty(y)
1403
+
1404
+ # Now handle the native python + sage object cases
1405
+ # that were not taken care of above.
1406
+ elif x_numeric:
1407
+ try:
1408
+ sage_parent = py_scalar_parent(type(x))
1409
+ if sage_parent is None or sage_parent.has_coerce_map_from(yp):
1410
+ return x, x.__class__(y)
1411
+ else:
1412
+ return self.canonical_coercion(sage_parent(x), y)
1413
+ except (TypeError, ValueError):
1414
+ self._record_exception()
1415
+
1416
+ elif y_numeric:
1417
+ try:
1418
+ sage_parent = py_scalar_parent(type(y))
1419
+ if sage_parent is None or sage_parent.has_coerce_map_from(xp):
1420
+ return y.__class__(x), y
1421
+ else:
1422
+ return self.canonical_coercion(x, sage_parent(y))
1423
+ except (TypeError, ValueError):
1424
+ self._record_exception()
1425
+
1426
+ # See if the non-objects define a _sage_ method.
1427
+ if not isinstance(x, SageObject) or not isinstance(y, SageObject):
1428
+ try:
1429
+ x = x._sage_()
1430
+ y = y._sage_()
1431
+ except AttributeError:
1432
+ self._record_exception()
1433
+ else:
1434
+ return self.canonical_coercion(x, y)
1435
+
1436
+ # Allow coercion of 0 even if no coercion from Z
1437
+ if (x_numeric or is_Integer(x)) and not x and type(yp) is not type:
1438
+ try:
1439
+ return yp(0), y
1440
+ except Exception:
1441
+ self._record_exception()
1442
+
1443
+ if (y_numeric or is_Integer(y)) and not y and type(xp) is not type:
1444
+ try:
1445
+ return x, xp(0)
1446
+ except Exception:
1447
+ self._record_exception()
1448
+
1449
+ raise TypeError("no common canonical parent for objects with parents: '%s' and '%s'" % (xp, yp))
1450
+
1451
+ cpdef coercion_maps(self, R, S):
1452
+ r"""
1453
+ Give two parents `R` and `S`, return a pair of coercion maps
1454
+ `f: R \rightarrow Z` and `g: S \rightarrow Z` , if such a `Z`
1455
+ can be found.
1456
+
1457
+ In the (common) case that `R=Z` or `S=Z` then ``None`` is returned
1458
+ for `f` or `g` respectively rather than constructing (and subsequently
1459
+ calling) the identity morphism.
1460
+
1461
+ If no suitable `f, g` can be found, a single ``None`` is returned.
1462
+ This result is cached.
1463
+
1464
+ .. NOTE::
1465
+
1466
+ By :issue:`14711`, coerce maps should be copied when using them
1467
+ outside of the coercion system, because they may become defunct
1468
+ by garbage collection.
1469
+
1470
+ EXAMPLES::
1471
+
1472
+ sage: cm = sage.structure.element.get_coercion_model()
1473
+ sage: f, g = cm.coercion_maps(ZZ, QQ)
1474
+ sage: print(copy(f))
1475
+ Natural morphism:
1476
+ From: Integer Ring
1477
+ To: Rational Field
1478
+ sage: print(g)
1479
+ None
1480
+
1481
+ sage: ZZx = ZZ['x']
1482
+ sage: f, g = cm.coercion_maps(ZZx, QQ)
1483
+ sage: print(f)
1484
+ (map internal to coercion system -- copy before use)
1485
+ Ring morphism:
1486
+ From: Univariate Polynomial Ring in x over Integer Ring
1487
+ To: Univariate Polynomial Ring in x over Rational Field
1488
+ sage: print(g)
1489
+ (map internal to coercion system -- copy before use)
1490
+ Polynomial base injection morphism:
1491
+ From: Rational Field
1492
+ To: Univariate Polynomial Ring in x over Rational Field
1493
+
1494
+ sage: K = GF(7)
1495
+ sage: cm.coercion_maps(QQ, K) is None
1496
+ True
1497
+
1498
+ Note that to break symmetry, if there is a coercion map in both
1499
+ directions, the parent on the left is used::
1500
+
1501
+ sage: # needs sage.modules
1502
+ sage: V = QQ^3
1503
+ sage: W = V.__class__(QQ, 3)
1504
+ sage: V == W
1505
+ True
1506
+ sage: V is W
1507
+ False
1508
+ sage: cm = sage.structure.element.get_coercion_model()
1509
+ sage: cm.coercion_maps(V, W)
1510
+ (None,
1511
+ (map internal to coercion system -- copy before use)
1512
+ Coercion map:
1513
+ From: Vector space of dimension 3 over Rational Field
1514
+ To: Vector space of dimension 3 over Rational Field)
1515
+ sage: cm.coercion_maps(W, V)
1516
+ (None,
1517
+ (map internal to coercion system -- copy before use)
1518
+ Coercion map:
1519
+ From: Vector space of dimension 3 over Rational Field
1520
+ To: Vector space of dimension 3 over Rational Field)
1521
+ sage: v = V([1,2,3])
1522
+ sage: w = W([1,2,3])
1523
+ sage: parent(v + w) is V
1524
+ True
1525
+ sage: parent(w + v) is W
1526
+ True
1527
+
1528
+ TESTS:
1529
+
1530
+ We check that with :issue:`14058`, parents are still eligible for
1531
+ garbage collection after being involved in binary operations::
1532
+
1533
+ sage: # needs sage.libs.pari
1534
+ sage: import gc
1535
+ sage: T = type(GF(2))
1536
+ sage: gc.collect() # random
1537
+ 852
1538
+ sage: N0 = len(list(o for o in gc.get_objects() if type(o) is T))
1539
+ sage: L = [ZZ(1) + GF(p)(1) for p in prime_range(2, 50)]
1540
+ sage: N1 = len(list(o for o in gc.get_objects() if type(o) is T))
1541
+ sage: N1 > N0
1542
+ True
1543
+ sage: del L
1544
+ sage: gc.collect() # random
1545
+ 3939
1546
+ sage: N2 = len(list(o for o in gc.get_objects() if type(o) is T))
1547
+ sage: N2 - N0
1548
+ 0
1549
+ """
1550
+ try:
1551
+ refs = self._coercion_maps.get(R, S, None)
1552
+ if refs is None:
1553
+ return None
1554
+ R_map_ref, S_map_ref = refs
1555
+ if R_map_ref is None:
1556
+ S_map = <object>PyWeakref_GET_OBJECT(S_map_ref)
1557
+ if S_map is not None:
1558
+ return None, S_map
1559
+ elif S_map_ref is None:
1560
+ R_map = <object>PyWeakref_GET_OBJECT(R_map_ref)
1561
+ if R_map is not None:
1562
+ return R_map, None
1563
+ else:
1564
+ R_map = <object>PyWeakref_GET_OBJECT(R_map_ref)
1565
+ S_map = <object>PyWeakref_GET_OBJECT(S_map_ref)
1566
+ if R_map is not None and S_map is not None:
1567
+ return R_map, S_map
1568
+ except KeyError:
1569
+ pass
1570
+ homs = self.discover_coercion(R, S)
1571
+ if 0:
1572
+ # This breaks too many things that are going to change
1573
+ # in the new coercion model anyways.
1574
+ # COERCE TODO: Enable it then.
1575
+ homs = self.verify_coercion_maps(R, S, homs)
1576
+ else:
1577
+ if homs is not None:
1578
+ x_map, y_map = homs
1579
+ if x_map is not None and not isinstance(x_map, Map):
1580
+ raise RuntimeError("BUG in coercion model: coerce_map_from must return a Map")
1581
+ if y_map is not None and not isinstance(y_map, Map):
1582
+ raise RuntimeError("BUG in coercion model: coerce_map_from must return a Map")
1583
+ if homs is None:
1584
+ refs = None
1585
+ swap = None
1586
+ else:
1587
+ R_map, S_map = homs
1588
+ R_map_ref = None if R_map is None else PyWeakref_NewRef(R_map, None)
1589
+ S_map_ref = None if S_map is None else PyWeakref_NewRef(S_map, None)
1590
+ refs = R_map_ref, S_map_ref
1591
+ if R_map is None and isinstance(S, Parent) and (<Parent>S).has_coerce_map_from(R):
1592
+ swap = None, PyWeakref_NewRef((<Parent>S).coerce_map_from(R), None)
1593
+ else:
1594
+ swap = S_map_ref, R_map_ref
1595
+ self._coercion_maps.set(R, S, None, refs)
1596
+ self._coercion_maps.set(S, R, None, swap)
1597
+ return homs
1598
+
1599
+ cpdef verify_coercion_maps(self, R, S, homs, bint fix=False):
1600
+ """
1601
+ Make sure this is a valid pair of homomorphisms from `R` and `S` to a common parent.
1602
+ This function is used to protect the user against buggy parents.
1603
+
1604
+ EXAMPLES::
1605
+
1606
+ sage: cm = sage.structure.element.get_coercion_model()
1607
+ sage: homs = QQ.coerce_map_from(ZZ), None
1608
+ sage: cm.verify_coercion_maps(ZZ, QQ, homs) == homs
1609
+ True
1610
+ sage: homs = QQ.coerce_map_from(ZZ), RR.coerce_map_from(QQ)
1611
+ sage: cm.verify_coercion_maps(ZZ, QQ, homs) == homs
1612
+ Traceback (most recent call last):
1613
+ ...
1614
+ RuntimeError: ('BUG in coercion model, codomains must be identical',
1615
+ Natural morphism:
1616
+ From: Integer Ring
1617
+ To: Rational Field,
1618
+ Generic map:
1619
+ From: Rational Field
1620
+ To: Real Field with 53 bits of precision)
1621
+ """
1622
+ if homs is None:
1623
+ return None
1624
+ cdef Map R_map, S_map
1625
+ R_map, S_map = homs
1626
+ if isinstance(R, type):
1627
+ R = Set_PythonType(R)
1628
+ elif isinstance(S, type):
1629
+ S = Set_PythonType(S)
1630
+ if R_map is None:
1631
+ R_map = IdentityMorphism(R)
1632
+ elif S_map is None:
1633
+ S_map = IdentityMorphism(S)
1634
+ # Make sure the domains are correct
1635
+ if R_map.domain() is not R:
1636
+ if fix:
1637
+ connecting = R_map.domain()._internal_coerce_map_from(R)
1638
+ if connecting is not None:
1639
+ R_map = R_map * connecting
1640
+ if R_map.domain() is not R:
1641
+ raise RuntimeError("BUG in coercion model, left domain must be original parent", R, R_map)
1642
+ if S_map is not None and S_map.domain() is not S:
1643
+ if fix:
1644
+ connecting = S_map.domain()._internal_coerce_map_from(S)
1645
+ if connecting is not None:
1646
+ S_map = S_map * connecting
1647
+ if S_map.domain() is not S:
1648
+ raise RuntimeError("BUG in coercion model, right domain must be original parent", S, S_map)
1649
+ # Make sure the codomains are correct
1650
+ if R_map.codomain() is not S_map.codomain():
1651
+ if fix:
1652
+ connecting = R_map.codomain()._internal_coerce_map_from(S_map.codomain())
1653
+ if connecting is not None:
1654
+ S_map = connecting * S_map
1655
+ else:
1656
+ connecting = S_map.codomain()._internal_coerce_map_from(R_map.codomain())
1657
+ if connecting is not None:
1658
+ R_map = connecting * R_map
1659
+ if R_map.codomain() is not S_map.codomain():
1660
+ raise RuntimeError("BUG in coercion model, codomains must be identical", R_map, S_map)
1661
+ if isinstance(R_map, IdentityMorphism):
1662
+ R_map = None
1663
+ elif isinstance(S_map, IdentityMorphism):
1664
+ S_map = None
1665
+ return R_map, S_map
1666
+
1667
+ cpdef discover_coercion(self, R, S):
1668
+ """
1669
+ This actually implements the finding of coercion maps as described in
1670
+ the :meth:`coercion_maps` method.
1671
+
1672
+ EXAMPLES::
1673
+
1674
+ sage: cm = sage.structure.element.get_coercion_model()
1675
+
1676
+ If R is S, then two identity morphisms suffice::
1677
+
1678
+ sage: cm.discover_coercion(SR, SR) # needs sage.symbolic
1679
+ (None, None)
1680
+
1681
+ If there is a coercion map either direction, use that::
1682
+
1683
+ sage: cm.discover_coercion(ZZ, QQ)
1684
+ ((map internal to coercion system -- copy before use)
1685
+ Natural morphism:
1686
+ From: Integer Ring
1687
+ To: Rational Field, None)
1688
+ sage: cm.discover_coercion(RR, QQ) # needs sage.rings.real_mpfr
1689
+ (None, (map internal to coercion system -- copy before use)
1690
+ Generic map:
1691
+ From: Rational Field
1692
+ To: Real Field with 53 bits of precision)
1693
+
1694
+ Otherwise, try and compute an appropriate cover::
1695
+
1696
+ sage: ZZxy = ZZ['x,y']
1697
+ sage: cm.discover_coercion(ZZxy, RDF)
1698
+ ((map internal to coercion system -- copy before use)
1699
+ Coercion map:
1700
+ From: Multivariate Polynomial Ring in x, y over Integer Ring
1701
+ To: Multivariate Polynomial Ring in x, y over Real Double Field,
1702
+ (map internal to coercion system -- copy before use)
1703
+ Polynomial base injection morphism:
1704
+ From: Real Double Field
1705
+ To: Multivariate Polynomial Ring in x, y over Real Double Field)
1706
+
1707
+ Sometimes there is a reasonable "cover," but no canonical coercion::
1708
+
1709
+ sage: sage.categories.pushout.pushout(QQ, QQ^3) # needs sage.modules
1710
+ Vector space of dimension 3 over Rational Field
1711
+ sage: print(cm.discover_coercion(QQ, QQ^3)) # needs sage.modules
1712
+ None
1713
+ """
1714
+ if R is S:
1715
+ return None, None
1716
+
1717
+ # See if there is a natural coercion from R to S
1718
+ if isinstance(R, Parent):
1719
+ mor = (<Parent>R)._internal_coerce_map_from(S)
1720
+ if mor is not None:
1721
+ return None, mor
1722
+
1723
+ # See if there is a natural coercion from S to R
1724
+ if isinstance(S, Parent):
1725
+ mor = (<Parent>S)._internal_coerce_map_from(R)
1726
+ if mor is not None:
1727
+ return mor, None
1728
+
1729
+ # Try base extending
1730
+ if isinstance(R, Parent) and isinstance(S, Parent):
1731
+ from sage.categories.pushout import pushout
1732
+ try:
1733
+ Z = pushout(R, S)
1734
+ coerce_R = Z._internal_coerce_map_from(R)
1735
+ coerce_S = Z._internal_coerce_map_from(S)
1736
+ if coerce_R is None:
1737
+ raise TypeError("No coercion from %s to pushout %s" % (R, Z))
1738
+ if coerce_S is None:
1739
+ raise TypeError("No coercion from %s to pushout %s" % (S, Z))
1740
+ return coerce_R, coerce_S
1741
+ except Exception:
1742
+ self._record_exception()
1743
+
1744
+ return None
1745
+
1746
+ cpdef get_action(self, R, S, op=mul, r=None, s=None):
1747
+ """
1748
+ Get the action of R on S or S on R associated to the operation op.
1749
+
1750
+ EXAMPLES::
1751
+
1752
+ sage: cm = sage.structure.element.get_coercion_model()
1753
+ sage: ZZx = ZZ['x']
1754
+ sage: cm.get_action(ZZx, ZZ, operator.mul)
1755
+ Right scalar multiplication by Integer Ring
1756
+ on Univariate Polynomial Ring in x over Integer Ring
1757
+ sage: cm.get_action(ZZx, QQ, operator.mul)
1758
+ Right scalar multiplication by Rational Field
1759
+ on Univariate Polynomial Ring in x over Integer Ring
1760
+ sage: QQx = QQ['x']
1761
+ sage: cm.get_action(QQx, int, operator.mul)
1762
+ Right scalar multiplication by Integer Ring
1763
+ on Univariate Polynomial Ring in x over Rational Field
1764
+ with precomposition on right by Native morphism:
1765
+ From: Set of Python objects of class 'int'
1766
+ To: Integer Ring
1767
+
1768
+ sage: A = cm.get_action(QQx, ZZ, operator.truediv); A
1769
+ Right inverse action by Rational Field
1770
+ on Univariate Polynomial Ring in x over Rational Field
1771
+ with precomposition on right by Natural morphism:
1772
+ From: Integer Ring
1773
+ To: Rational Field
1774
+ sage: x = QQx.gen()
1775
+ sage: A(x+10, 5)
1776
+ 1/5*x + 2
1777
+ """
1778
+ try:
1779
+ return self._action_maps.get(R, S, op)
1780
+ except KeyError:
1781
+ pass
1782
+ action = self.discover_action(R, S, op, r, s)
1783
+ action = self.verify_action(action, R, S, op)
1784
+ self._action_maps.set(R, S, op, action)
1785
+ return action
1786
+
1787
+ cpdef verify_action(self, action, R, S, op, bint fix=True):
1788
+ r"""
1789
+ Verify that ``action`` takes an element of R on the left and S
1790
+ on the right, raising an error if not.
1791
+
1792
+ This is used for consistency checking in the coercion model.
1793
+
1794
+ EXAMPLES::
1795
+
1796
+ sage: R.<x> = ZZ['x']
1797
+ sage: cm = sage.structure.element.get_coercion_model()
1798
+ sage: cm.verify_action(R.get_action(QQ), R, QQ, operator.mul)
1799
+ Right scalar multiplication by Rational Field
1800
+ on Univariate Polynomial Ring in x over Integer Ring
1801
+ sage: cm.verify_action(R.get_action(QQ), RDF, R, operator.mul)
1802
+ Traceback (most recent call last):
1803
+ ...
1804
+ RuntimeError: There is a BUG in the coercion model:
1805
+ Action found for R <built-in function mul> S does not have the correct domains
1806
+ R = Real Double Field
1807
+ S = Univariate Polynomial Ring in x over Integer Ring
1808
+ (should be Univariate Polynomial Ring in x over Integer Ring, Rational Field)
1809
+ action = Right scalar multiplication by Rational Field
1810
+ on Univariate Polynomial Ring in x over Integer Ring
1811
+ (<class 'sage.structure.coerce_actions.RightModuleAction'>)
1812
+ """
1813
+ if action is None:
1814
+ return action
1815
+ cdef bint ok = True
1816
+ try:
1817
+ if action.left_domain() is not R:
1818
+ ok &= isinstance(R, type) and action.left_domain()._type is R
1819
+ if action.right_domain() is not S:
1820
+ ok &= isinstance(S, type) and action.right_domain()._type is S
1821
+ except AttributeError:
1822
+ ok = False
1823
+ if not ok:
1824
+ if isinstance(R, type):
1825
+ R = Set_PythonType(R)
1826
+ if isinstance(S, type):
1827
+ S = Set_PythonType(S)
1828
+
1829
+ # Non-unique parents
1830
+ if fix and action.left_domain() is not R and action.left_domain() == R:
1831
+ action = PrecomposedAction(action, action.left_domain()._internal_coerce_map_from(R), None)
1832
+ if fix and action.right_domain() is not S and action.right_domain() == S:
1833
+ action = PrecomposedAction(action, None, action.right_domain()._internal_coerce_map_from(S))
1834
+
1835
+ if action.left_domain() is not R or action.right_domain() is not S:
1836
+ raise RuntimeError("""There is a BUG in the coercion model:
1837
+ Action found for R %s S does not have the correct domains
1838
+ R = %s
1839
+ S = %s
1840
+ (should be %s, %s)
1841
+ action = %s (%s)
1842
+ """ % (op, R, S, action.left_domain(), action.right_domain(), action, type(action)))
1843
+
1844
+ return action
1845
+
1846
+ cpdef discover_action(self, R, S, op, r=None, s=None):
1847
+ """
1848
+ INPUT:
1849
+
1850
+ - ``R`` -- the left :class:`Parent` (or type)
1851
+ - ``S`` -- the right :class:`Parent` (or type)
1852
+ - ``op`` -- the operand, typically an element of the :mod:`operator` module
1853
+ - ``r`` -- (optional) element of `R`
1854
+ - ``s`` -- (optional) element of `S`
1855
+
1856
+ OUTPUT: an action `A` such that `s` ``op`` `r` is given by `A(s,r)`
1857
+
1858
+ The steps taken are illustrated below.
1859
+
1860
+ EXAMPLES::
1861
+
1862
+ sage: P.<x> = ZZ['x']
1863
+ sage: P.get_action(ZZ)
1864
+ Right scalar multiplication by Integer Ring on
1865
+ Univariate Polynomial Ring in x over Integer Ring
1866
+ sage: ZZ.get_action(P) is None
1867
+ True
1868
+ sage: cm = sage.structure.element.get_coercion_model()
1869
+
1870
+ If `R` or `S` is a :class:`Parent`, ask it for an action by/on `R`::
1871
+
1872
+ sage: cm.discover_action(ZZ, P, operator.mul)
1873
+ Left scalar multiplication by Integer Ring on
1874
+ Univariate Polynomial Ring in x over Integer Ring
1875
+
1876
+ If `R` or `S` a type, recursively call :meth:`get_action`
1877
+ with the Sage versions of `R` and/or `S`::
1878
+
1879
+ sage: cm.discover_action(P, int, operator.mul)
1880
+ Right scalar multiplication by Integer Ring on
1881
+ Univariate Polynomial Ring in x over Integer Ring
1882
+ with precomposition on right by Native morphism:
1883
+ From: Set of Python objects of class 'int'
1884
+ To: Integer Ring
1885
+
1886
+ If ``op`` is division, look for action on ``right`` by inverse::
1887
+
1888
+ sage: cm.discover_action(P, ZZ, operator.truediv)
1889
+ Right inverse action by Rational Field on
1890
+ Univariate Polynomial Ring in x over Integer Ring
1891
+ with precomposition on right by Natural morphism:
1892
+ From: Integer Ring
1893
+ To: Rational Field
1894
+
1895
+ Check that :issue:`17740` is fixed::
1896
+
1897
+ sage: R = GF(5)['x']
1898
+ sage: cm.discover_action(R, ZZ, operator.truediv)
1899
+ Right inverse action by Finite Field of size 5
1900
+ on Univariate Polynomial Ring in x over Finite Field of size 5
1901
+ with precomposition on right by Natural morphism:
1902
+ From: Integer Ring
1903
+ To: Finite Field of size 5
1904
+ sage: cm.bin_op(R.gen(), 7, operator.truediv).parent()
1905
+ Univariate Polynomial Ring in x over Finite Field of size 5
1906
+
1907
+ Check that :issue:`18221` is fixed::
1908
+
1909
+ sage: # needs sage.combinat sage.modules
1910
+ sage: F.<x> = FreeAlgebra(QQ)
1911
+ sage: x / 2
1912
+ 1/2*x
1913
+ sage: cm.discover_action(F, ZZ, operator.truediv)
1914
+ Right inverse action by Rational Field on
1915
+ Free Algebra on 1 generator (x,) over Rational Field
1916
+ with precomposition on right by Natural morphism:
1917
+ From: Integer Ring
1918
+ To: Rational Field
1919
+ """
1920
+ if isinstance(R, Parent):
1921
+ action = (<Parent>R).get_action(S, op, True, r, s)
1922
+ if action is not None:
1923
+ return action
1924
+
1925
+ if isinstance(S, Parent):
1926
+ action = (<Parent>S).get_action(R, op, False, s, r)
1927
+ if action is not None:
1928
+ return action
1929
+
1930
+ if type(R) is type:
1931
+ sageR = py_scalar_parent(R)
1932
+ if sageR is not None:
1933
+ action = self.get_action(sageR, S, op, s=s)
1934
+ if action is not None:
1935
+ return PrecomposedAction(action, sageR._internal_coerce_map_from(R), None)
1936
+
1937
+ if type(S) is type:
1938
+ sageS = py_scalar_parent(S)
1939
+ if sageS is not None:
1940
+ action = self.get_action(R, sageS, op, r=r)
1941
+ if action is not None:
1942
+ return PrecomposedAction(action, None, sageS._internal_coerce_map_from(S))
1943
+
1944
+ if op is truediv:
1945
+ # Division on right is the same acting on right by inverse, if it is so defined.
1946
+ right_mul = None
1947
+ try:
1948
+ right_mul = self.get_action(R, S, mul)
1949
+ except NotImplementedError:
1950
+ self._record_exception()
1951
+
1952
+ if right_mul is not None and not right_mul.is_left():
1953
+ try:
1954
+ action = ~right_mul
1955
+ if action.right_domain() != S:
1956
+ action = PrecomposedAction(action, None,
1957
+ action.right_domain()._internal_coerce_map_from(S))
1958
+ return action
1959
+ except TypeError: # action may not be invertible
1960
+ self._record_exception()
1961
+
1962
+ # It's possible an action is defined on the fraction field itself.
1963
+ try:
1964
+ K = S._pseudo_fraction_field()
1965
+ except AttributeError:
1966
+ pass
1967
+ else:
1968
+ if K is not S:
1969
+ try:
1970
+ right_mul = self.get_action(R, K, mul)
1971
+ except NotImplementedError:
1972
+ self._record_exception()
1973
+
1974
+ if right_mul is not None and not right_mul.is_left():
1975
+ try:
1976
+ return PrecomposedAction(~right_mul, None, K.coerce_map_from(S))
1977
+ except TypeError: # action may not be invertible
1978
+ self._record_exception()
1979
+
1980
+ return None
1981
+
1982
+ cpdef richcmp(self, x, y, int op):
1983
+ """
1984
+ Given two arbitrary objects ``x`` and ``y``, coerce them to
1985
+ a common parent and compare them using rich comparison operator
1986
+ ``op``.
1987
+
1988
+ EXAMPLES::
1989
+
1990
+ sage: from sage.structure.element import get_coercion_model
1991
+ sage: from sage.structure.richcmp import op_LT, op_LE, op_EQ, op_NE, op_GT, op_GE
1992
+ sage: richcmp = get_coercion_model().richcmp
1993
+ sage: richcmp(None, None, op_EQ)
1994
+ True
1995
+ sage: richcmp(None, 1, op_LT)
1996
+ True
1997
+ sage: richcmp("hello", None, op_LE)
1998
+ False
1999
+ sage: richcmp(-1, 1, op_GE)
2000
+ False
2001
+ sage: richcmp(int(1), float(2), op_GE)
2002
+ False
2003
+
2004
+ If there is no coercion, we only support ``==`` and ``!=``::
2005
+
2006
+ sage: x = QQ.one(); y = GF(2).one()
2007
+ sage: richcmp(x, y, op_EQ)
2008
+ False
2009
+ sage: richcmp(x, y, op_NE)
2010
+ True
2011
+ sage: richcmp(x, y, op_GT)
2012
+ Traceback (most recent call last):
2013
+ ...
2014
+ TypeError: unsupported operand parent(s) for >:
2015
+ 'Rational Field' and 'Finite Field of size 2'
2016
+
2017
+ We support non-Sage types with the usual Python convention::
2018
+
2019
+ sage: class AlwaysEqual():
2020
+ ....: def __eq__(self, other):
2021
+ ....: return True
2022
+ sage: x = AlwaysEqual()
2023
+ sage: x == 1
2024
+ True
2025
+ sage: 1 == x
2026
+ True
2027
+ """
2028
+ # Some very special cases
2029
+ if x is None or x is Ellipsis:
2030
+ return rich_to_bool(op, 0 if x is y else -1)
2031
+ if y is None or y is Ellipsis:
2032
+ return rich_to_bool(op, 0 if x is y else 1)
2033
+
2034
+ cdef bint y_is_Element = isinstance(y, Element)
2035
+
2036
+ # Check for manual __richcmp__ override (only on y since
2037
+ # x.__richcmp__ would already have been called)
2038
+ if y_is_Element:
2039
+ if (<Element>y)._parent.get_flag(Parent_richcmp_element_without_coercion):
2040
+ return Py_TYPE(y).tp_richcompare(y, x, revop(op))
2041
+
2042
+ # Coerce to a common parent
2043
+ try:
2044
+ x, y = self.canonical_coercion(x, y)
2045
+ except (TypeError, NotImplementedError):
2046
+ pass
2047
+ else:
2048
+ # The common parent should not be one which explicitly
2049
+ # asked to *not* use coercion for comparisons.
2050
+ assert not (isinstance(x, Element) and
2051
+ (<Element>x)._parent.get_flag(Parent_richcmp_element_without_coercion))
2052
+ return PyObject_RichCompare(x, y, op)
2053
+
2054
+ # Comparing with coercion didn't work, try something else.
2055
+
2056
+ # Try y.__richcmp__(x, revop) where revop is the reversed
2057
+ # operation (<= becomes >=).
2058
+ # This only makes sense when y is not a Sage Element, otherwise
2059
+ # we would end up trying the same coercion again.
2060
+ if not y_is_Element and Py_TYPE(y).tp_richcompare:
2061
+ res = Py_TYPE(y).tp_richcompare(y, x, revop(op))
2062
+ if res is not NotImplemented:
2063
+ return res
2064
+
2065
+ # At this point, we have 2 objects which cannot be coerced to
2066
+ # a common parent. So we assume that they are not equal.
2067
+ if op == Py_EQ:
2068
+ return False
2069
+ if op == Py_NE:
2070
+ return True
2071
+
2072
+ # It does not make sense to compare x and y with an inequality,
2073
+ # so we raise an exception.
2074
+ if op == Py_LT:
2075
+ raise bin_op_exception('<', x, y)
2076
+ elif op == Py_LE:
2077
+ raise bin_op_exception('<=', x, y)
2078
+ elif op == Py_GT:
2079
+ raise bin_op_exception('>', x, y)
2080
+ else:
2081
+ raise bin_op_exception('>=', x, y)
2082
+
2083
+ def _coercion_error(self, x, x_map, x_elt, y, y_map, y_elt):
2084
+ """
2085
+ This function is only called when someone has incorrectly implemented
2086
+ a user-defined part of the coercion system (usually, a morphism).
2087
+
2088
+ EXAMPLES::
2089
+
2090
+ sage: cm = sage.structure.element.get_coercion_model()
2091
+ sage: cm._coercion_error('a', 'f', 'f(a)', 'b', 'g', 'g(b)')
2092
+ Traceback (most recent call last):
2093
+ ...
2094
+ RuntimeError: There is a bug in the coercion code in Sage.
2095
+ Both x (='f(a)') and y (='g(b)') are supposed to have identical parents but they don't.
2096
+ In fact, x has parent '<class 'str'>'
2097
+ whereas y has parent '<class 'str'>'
2098
+ Original elements 'a' (parent <class 'str'>) and 'b' (parent <class 'str'>) and maps
2099
+ <class 'str'> 'f'
2100
+ <class 'str'> 'g'
2101
+ """
2102
+ raise RuntimeError("""There is a bug in the coercion code in Sage.
2103
+ Both x (=%r) and y (=%r) are supposed to have identical parents but they don't.
2104
+ In fact, x has parent '%s'
2105
+ whereas y has parent '%s'
2106
+ Original elements %r (parent %s) and %r (parent %s) and maps
2107
+ %s %r
2108
+ %s %r""" % (x_elt, y_elt, parent(x_elt), parent(y_elt),
2109
+ x, parent(x), y, parent(y),
2110
+ type(x_map), x_map, type(y_map), y_map))
2111
+
2112
+
2113
+ coercion_model = CoercionModel()