passagemath-objects 10.6.41__cp312-cp312-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.
- passagemath_objects/__init__.py +3 -0
- passagemath_objects-10.6.41.dist-info/DELVEWHEEL +2 -0
- passagemath_objects-10.6.41.dist-info/METADATA +115 -0
- passagemath_objects-10.6.41.dist-info/RECORD +281 -0
- passagemath_objects-10.6.41.dist-info/WHEEL +5 -0
- passagemath_objects-10.6.41.dist-info/top_level.txt +3 -0
- passagemath_objects.libs/libgmp-10-79b4110c7ea2b760f16cfef97e8a8a34.dll +0 -0
- sage/all__sagemath_objects.py +46 -0
- sage/arith/all__sagemath_objects.py +5 -0
- sage/arith/long.pxd +411 -0
- sage/arith/numerical_approx.cp312-win_amd64.pyd +0 -0
- sage/arith/numerical_approx.pxd +35 -0
- sage/arith/numerical_approx.pyx +75 -0
- sage/arith/power.cp312-win_amd64.pyd +0 -0
- sage/arith/power.pxd +31 -0
- sage/arith/power.pyx +127 -0
- sage/categories/action.cp312-win_amd64.pyd +0 -0
- sage/categories/action.pxd +29 -0
- sage/categories/action.pyx +641 -0
- sage/categories/algebra_functor.py +745 -0
- sage/categories/all__sagemath_objects.py +33 -0
- sage/categories/basic.py +71 -0
- sage/categories/cartesian_product.py +295 -0
- sage/categories/category.py +3401 -0
- sage/categories/category_cy_helper.cp312-win_amd64.pyd +0 -0
- sage/categories/category_cy_helper.pxd +8 -0
- sage/categories/category_cy_helper.pyx +322 -0
- sage/categories/category_singleton.cp312-win_amd64.pyd +0 -0
- sage/categories/category_singleton.pxd +3 -0
- sage/categories/category_singleton.pyx +342 -0
- sage/categories/category_types.py +637 -0
- sage/categories/category_with_axiom.py +2885 -0
- sage/categories/covariant_functorial_construction.py +703 -0
- sage/categories/facade_sets.py +228 -0
- sage/categories/functor.cp312-win_amd64.pyd +0 -0
- sage/categories/functor.pxd +7 -0
- sage/categories/functor.pyx +691 -0
- sage/categories/homset.py +1338 -0
- sage/categories/homsets.py +364 -0
- sage/categories/isomorphic_objects.py +73 -0
- sage/categories/map.cp312-win_amd64.pyd +0 -0
- sage/categories/map.pxd +34 -0
- sage/categories/map.pyx +2112 -0
- sage/categories/morphism.cp312-win_amd64.pyd +0 -0
- sage/categories/morphism.pxd +14 -0
- sage/categories/morphism.pyx +895 -0
- sage/categories/objects.py +167 -0
- sage/categories/primer.py +1696 -0
- sage/categories/pushout.py +4834 -0
- sage/categories/quotients.py +64 -0
- sage/categories/realizations.py +200 -0
- sage/categories/sets_cat.py +3228 -0
- sage/categories/sets_with_partial_maps.py +52 -0
- sage/categories/subobjects.py +64 -0
- sage/categories/subquotients.py +21 -0
- sage/categories/with_realizations.py +311 -0
- sage/cpython/__init__.py +28 -0
- sage/cpython/_py2_random.py +619 -0
- sage/cpython/all.py +3 -0
- sage/cpython/atexit.cp312-win_amd64.pyd +0 -0
- sage/cpython/atexit.pyx +269 -0
- sage/cpython/builtin_types.cp312-win_amd64.pyd +0 -0
- sage/cpython/builtin_types.pyx +7 -0
- sage/cpython/cython_metaclass.cp312-win_amd64.pyd +0 -0
- sage/cpython/cython_metaclass.h +117 -0
- sage/cpython/cython_metaclass.pxd +3 -0
- sage/cpython/cython_metaclass.pyx +130 -0
- sage/cpython/debug.cp312-win_amd64.pyd +0 -0
- sage/cpython/debug.pyx +302 -0
- sage/cpython/dict_del_by_value.cp312-win_amd64.pyd +0 -0
- sage/cpython/dict_del_by_value.pxd +9 -0
- sage/cpython/dict_del_by_value.pyx +191 -0
- sage/cpython/dict_internal.h +245 -0
- sage/cpython/getattr.cp312-win_amd64.pyd +0 -0
- sage/cpython/getattr.pxd +9 -0
- sage/cpython/getattr.pyx +439 -0
- sage/cpython/pycore_long.h +97 -0
- sage/cpython/pycore_long.pxd +10 -0
- sage/cpython/python_debug.h +44 -0
- sage/cpython/python_debug.pxd +47 -0
- sage/cpython/pyx_visit.h +13 -0
- sage/cpython/string.cp312-win_amd64.pyd +0 -0
- sage/cpython/string.pxd +76 -0
- sage/cpython/string.pyx +34 -0
- sage/cpython/string_impl.h +60 -0
- sage/cpython/type.cp312-win_amd64.pyd +0 -0
- sage/cpython/type.pxd +2 -0
- sage/cpython/type.pyx +40 -0
- sage/cpython/wrapperdescr.pxd +67 -0
- sage/ext/all__sagemath_objects.py +3 -0
- sage/ext/ccobject.h +64 -0
- sage/ext/cplusplus.pxd +17 -0
- sage/ext/mod_int.h +30 -0
- sage/ext/mod_int.pxd +24 -0
- sage/ext/stdsage.pxd +39 -0
- sage/groups/all__sagemath_objects.py +1 -0
- sage/groups/group.cp312-win_amd64.pyd +0 -0
- sage/groups/group.pxd +14 -0
- sage/groups/group.pyx +322 -0
- sage/groups/old.cp312-win_amd64.pyd +0 -0
- sage/groups/old.pxd +14 -0
- sage/groups/old.pyx +219 -0
- sage/libs/all__sagemath_objects.py +3 -0
- sage/libs/gmp/__init__.py +1 -0
- sage/libs/gmp/all.pxd +6 -0
- sage/libs/gmp/binop.pxd +23 -0
- sage/libs/gmp/misc.pxd +8 -0
- sage/libs/gmp/mpf.pxd +88 -0
- sage/libs/gmp/mpn.pxd +57 -0
- sage/libs/gmp/mpq.pxd +57 -0
- sage/libs/gmp/mpz.pxd +202 -0
- sage/libs/gmp/pylong.cp312-win_amd64.pyd +0 -0
- sage/libs/gmp/pylong.pxd +12 -0
- sage/libs/gmp/pylong.pyx +150 -0
- sage/libs/gmp/random.pxd +25 -0
- sage/libs/gmp/randomize.pxd +59 -0
- sage/libs/gmp/types.pxd +53 -0
- sage/libs/gmpxx.pxd +19 -0
- sage/misc/abstract_method.py +276 -0
- sage/misc/all__sagemath_objects.py +43 -0
- sage/misc/bindable_class.py +253 -0
- sage/misc/c3_controlled.cp312-win_amd64.pyd +0 -0
- sage/misc/c3_controlled.pxd +2 -0
- sage/misc/c3_controlled.pyx +1402 -0
- sage/misc/cachefunc.cp312-win_amd64.pyd +0 -0
- sage/misc/cachefunc.pxd +43 -0
- sage/misc/cachefunc.pyx +3781 -0
- sage/misc/call.py +188 -0
- sage/misc/classcall_metaclass.cp312-win_amd64.pyd +0 -0
- sage/misc/classcall_metaclass.pxd +14 -0
- sage/misc/classcall_metaclass.pyx +599 -0
- sage/misc/constant_function.cp312-win_amd64.pyd +0 -0
- sage/misc/constant_function.pyx +130 -0
- sage/misc/decorators.py +747 -0
- sage/misc/fast_methods.cp312-win_amd64.pyd +0 -0
- sage/misc/fast_methods.pxd +20 -0
- sage/misc/fast_methods.pyx +351 -0
- sage/misc/flatten.py +90 -0
- sage/misc/fpickle.cp312-win_amd64.pyd +0 -0
- sage/misc/fpickle.pyx +177 -0
- sage/misc/function_mangling.cp312-win_amd64.pyd +0 -0
- sage/misc/function_mangling.pxd +11 -0
- sage/misc/function_mangling.pyx +308 -0
- sage/misc/inherit_comparison.cp312-win_amd64.pyd +0 -0
- sage/misc/inherit_comparison.pxd +5 -0
- sage/misc/inherit_comparison.pyx +105 -0
- sage/misc/instancedoc.cp312-win_amd64.pyd +0 -0
- sage/misc/instancedoc.pyx +331 -0
- sage/misc/lazy_attribute.cp312-win_amd64.pyd +0 -0
- sage/misc/lazy_attribute.pyx +607 -0
- sage/misc/lazy_format.py +135 -0
- sage/misc/lazy_import.cp312-win_amd64.pyd +0 -0
- sage/misc/lazy_import.pyx +1299 -0
- sage/misc/lazy_import_cache.py +36 -0
- sage/misc/lazy_list.cp312-win_amd64.pyd +0 -0
- sage/misc/lazy_list.pxd +19 -0
- sage/misc/lazy_list.pyx +1187 -0
- sage/misc/lazy_string.cp312-win_amd64.pyd +0 -0
- sage/misc/lazy_string.pxd +7 -0
- sage/misc/lazy_string.pyx +546 -0
- sage/misc/misc.py +1066 -0
- sage/misc/misc_c.cp312-win_amd64.pyd +0 -0
- sage/misc/misc_c.pxd +3 -0
- sage/misc/misc_c.pyx +766 -0
- sage/misc/namespace_package.py +37 -0
- sage/misc/nested_class.cp312-win_amd64.pyd +0 -0
- sage/misc/nested_class.pxd +3 -0
- sage/misc/nested_class.pyx +394 -0
- sage/misc/persist.cp312-win_amd64.pyd +0 -0
- sage/misc/persist.pyx +1251 -0
- sage/misc/prandom.py +418 -0
- sage/misc/randstate.cp312-win_amd64.pyd +0 -0
- sage/misc/randstate.pxd +30 -0
- sage/misc/randstate.pyx +1059 -0
- sage/misc/repr.py +203 -0
- sage/misc/reset.cp312-win_amd64.pyd +0 -0
- sage/misc/reset.pyx +196 -0
- sage/misc/sage_ostools.cp312-win_amd64.pyd +0 -0
- sage/misc/sage_ostools.pyx +323 -0
- sage/misc/sage_timeit.py +276 -0
- sage/misc/sage_timeit_class.cp312-win_amd64.pyd +0 -0
- sage/misc/sage_timeit_class.pyx +120 -0
- sage/misc/sage_unittest.py +637 -0
- sage/misc/sageinspect.py +2768 -0
- sage/misc/session.cp312-win_amd64.pyd +0 -0
- sage/misc/session.pyx +392 -0
- sage/misc/superseded.py +557 -0
- sage/misc/test_nested_class.py +228 -0
- sage/misc/timing.py +264 -0
- sage/misc/unknown.py +222 -0
- sage/misc/verbose.py +253 -0
- sage/misc/weak_dict.cp312-win_amd64.pyd +0 -0
- sage/misc/weak_dict.pxd +15 -0
- sage/misc/weak_dict.pyx +1231 -0
- sage/modules/all__sagemath_objects.py +1 -0
- sage/modules/module.cp312-win_amd64.pyd +0 -0
- sage/modules/module.pxd +5 -0
- sage/modules/module.pyx +329 -0
- sage/rings/all__sagemath_objects.py +3 -0
- sage/rings/integer_fake.h +22 -0
- sage/rings/integer_fake.pxd +55 -0
- sage/sets/all__sagemath_objects.py +3 -0
- sage/sets/pythonclass.cp312-win_amd64.pyd +0 -0
- sage/sets/pythonclass.pxd +9 -0
- sage/sets/pythonclass.pyx +247 -0
- sage/structure/__init__.py +13 -0
- sage/structure/all.py +30 -0
- sage/structure/category_object.cp312-win_amd64.pyd +0 -0
- sage/structure/category_object.pxd +28 -0
- sage/structure/category_object.pyx +1087 -0
- sage/structure/coerce.cp312-win_amd64.pyd +0 -0
- sage/structure/coerce.pxd +44 -0
- sage/structure/coerce.pyx +2107 -0
- sage/structure/coerce_actions.cp312-win_amd64.pyd +0 -0
- sage/structure/coerce_actions.pxd +27 -0
- sage/structure/coerce_actions.pyx +988 -0
- sage/structure/coerce_dict.cp312-win_amd64.pyd +0 -0
- sage/structure/coerce_dict.pxd +51 -0
- sage/structure/coerce_dict.pyx +1557 -0
- sage/structure/coerce_exceptions.py +23 -0
- sage/structure/coerce_maps.cp312-win_amd64.pyd +0 -0
- sage/structure/coerce_maps.pxd +28 -0
- sage/structure/coerce_maps.pyx +718 -0
- sage/structure/debug_options.cp312-win_amd64.pyd +0 -0
- sage/structure/debug_options.pxd +6 -0
- sage/structure/debug_options.pyx +54 -0
- sage/structure/dynamic_class.py +541 -0
- sage/structure/element.cp312-win_amd64.pyd +0 -0
- sage/structure/element.pxd +272 -0
- sage/structure/element.pyx +4772 -0
- sage/structure/element_wrapper.cp312-win_amd64.pyd +0 -0
- sage/structure/element_wrapper.pxd +12 -0
- sage/structure/element_wrapper.pyx +582 -0
- sage/structure/factorization.py +1422 -0
- sage/structure/factorization_integer.py +105 -0
- sage/structure/factory.cp312-win_amd64.pyd +0 -0
- sage/structure/factory.pyx +786 -0
- sage/structure/formal_sum.py +489 -0
- sage/structure/gens_py.py +73 -0
- sage/structure/global_options.py +1743 -0
- sage/structure/indexed_generators.py +863 -0
- sage/structure/list_clone.cp312-win_amd64.pyd +0 -0
- sage/structure/list_clone.pxd +65 -0
- sage/structure/list_clone.pyx +1867 -0
- sage/structure/list_clone_demo.cp312-win_amd64.pyd +0 -0
- sage/structure/list_clone_demo.pyx +248 -0
- sage/structure/list_clone_timings.py +179 -0
- sage/structure/list_clone_timings_cy.cp312-win_amd64.pyd +0 -0
- sage/structure/list_clone_timings_cy.pyx +86 -0
- sage/structure/mutability.cp312-win_amd64.pyd +0 -0
- sage/structure/mutability.pxd +21 -0
- sage/structure/mutability.pyx +348 -0
- sage/structure/nonexact.py +69 -0
- sage/structure/parent.cp312-win_amd64.pyd +0 -0
- sage/structure/parent.pxd +112 -0
- sage/structure/parent.pyx +3093 -0
- sage/structure/parent_base.cp312-win_amd64.pyd +0 -0
- sage/structure/parent_base.pxd +13 -0
- sage/structure/parent_base.pyx +44 -0
- sage/structure/parent_gens.cp312-win_amd64.pyd +0 -0
- sage/structure/parent_gens.pxd +22 -0
- sage/structure/parent_gens.pyx +377 -0
- sage/structure/parent_old.cp312-win_amd64.pyd +0 -0
- sage/structure/parent_old.pxd +25 -0
- sage/structure/parent_old.pyx +294 -0
- sage/structure/proof/__init__.py +1 -0
- sage/structure/proof/all.py +243 -0
- sage/structure/proof/proof.py +300 -0
- sage/structure/richcmp.cp312-win_amd64.pyd +0 -0
- sage/structure/richcmp.pxd +213 -0
- sage/structure/richcmp.pyx +495 -0
- sage/structure/sage_object.cp312-win_amd64.pyd +0 -0
- sage/structure/sage_object.pxd +3 -0
- sage/structure/sage_object.pyx +988 -0
- sage/structure/sage_object_test.py +19 -0
- sage/structure/sequence.py +937 -0
- sage/structure/set_factories.py +1178 -0
- sage/structure/set_factories_example.py +527 -0
- sage/structure/support_view.py +179 -0
- sage/structure/test_factory.py +56 -0
- sage/structure/unique_representation.py +1359 -0
|
@@ -0,0 +1,718 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-objects
|
|
2
|
+
"""
|
|
3
|
+
Coerce maps
|
|
4
|
+
"""
|
|
5
|
+
import types
|
|
6
|
+
|
|
7
|
+
from sage.structure.parent cimport Parent
|
|
8
|
+
from sage.structure.element cimport Element
|
|
9
|
+
from sage.sets.pythonclass cimport Set_PythonType
|
|
10
|
+
|
|
11
|
+
cdef object BuiltinMethodType = type(repr)
|
|
12
|
+
|
|
13
|
+
# COERCE TODO: remove or integrate better (as this bit is only checked on an error)
|
|
14
|
+
cdef bint print_warnings = 0
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
cdef class DefaultConvertMap(Map):
|
|
18
|
+
"""
|
|
19
|
+
This morphism simply calls the codomain's element_constructor method,
|
|
20
|
+
passing in the codomain as the first argument.
|
|
21
|
+
|
|
22
|
+
EXAMPLES::
|
|
23
|
+
|
|
24
|
+
sage: QQ[['x']].coerce_map_from(QQ)
|
|
25
|
+
Coercion map:
|
|
26
|
+
From: Rational Field
|
|
27
|
+
To: Power Series Ring in x over Rational Field
|
|
28
|
+
"""
|
|
29
|
+
def __init__(self, domain, codomain, category=None):
|
|
30
|
+
"""
|
|
31
|
+
TESTS:
|
|
32
|
+
|
|
33
|
+
Maps of this type are morphisms in the category of sets with
|
|
34
|
+
partial maps (see :issue:`15618`)::
|
|
35
|
+
|
|
36
|
+
sage: f = GF(11).convert_map_from(GF(7)); f # needs sage.rings.finite_rings
|
|
37
|
+
Conversion map:
|
|
38
|
+
From: Finite Field of size 7
|
|
39
|
+
To: Finite Field of size 11
|
|
40
|
+
sage: f.parent() # needs sage.rings.finite_rings
|
|
41
|
+
Set of Morphisms
|
|
42
|
+
from Finite Field of size 7
|
|
43
|
+
to Finite Field of size 11
|
|
44
|
+
in Category of sets with partial maps
|
|
45
|
+
|
|
46
|
+
Test that :issue:`23211` is resolved::
|
|
47
|
+
|
|
48
|
+
sage: f._is_coercion # needs sage.rings.finite_rings
|
|
49
|
+
False
|
|
50
|
+
sage: QQ[['x']].coerce_map_from(QQ)._is_coercion
|
|
51
|
+
True
|
|
52
|
+
|
|
53
|
+
This class is deprecated when used directly::
|
|
54
|
+
|
|
55
|
+
sage: from sage.structure.coerce_maps import DefaultConvertMap
|
|
56
|
+
sage: DefaultConvertMap(ZZ, ZZ)
|
|
57
|
+
doctest:...: DeprecationWarning: DefaultConvertMap is deprecated, use DefaultConvertMap_unique instead.
|
|
58
|
+
This probably means that _element_constructor_ should be a method and not some other kind of callable
|
|
59
|
+
See https://github.com/sagemath/sage/issues/26879 for details.
|
|
60
|
+
Conversion map:
|
|
61
|
+
From: Integer Ring
|
|
62
|
+
To: Integer Ring
|
|
63
|
+
"""
|
|
64
|
+
# The base class DefaultConvertMap is deprecated, only the
|
|
65
|
+
# derived class DefaultConvertMap_unique should be used.
|
|
66
|
+
# When removing this deprecation, this class should be merged
|
|
67
|
+
# into DefaultConvertMap_unique.
|
|
68
|
+
if not isinstance(self, DefaultConvertMap_unique):
|
|
69
|
+
from sage.misc.superseded import deprecation_cython as deprecation
|
|
70
|
+
deprecation(26879, "DefaultConvertMap is deprecated, use DefaultConvertMap_unique instead. This probably means that _element_constructor_ should be a method and not some other kind of callable")
|
|
71
|
+
|
|
72
|
+
if not isinstance(domain, Parent):
|
|
73
|
+
domain = Set_PythonType(domain)
|
|
74
|
+
if category is None:
|
|
75
|
+
from sage.categories.sets_with_partial_maps import SetsWithPartialMaps
|
|
76
|
+
category = SetsWithPartialMaps()
|
|
77
|
+
parent = domain.Hom(codomain, category=category)
|
|
78
|
+
Map.__init__(self, parent)
|
|
79
|
+
self._coerce_cost = 100
|
|
80
|
+
if (<Parent>codomain)._element_constructor is None:
|
|
81
|
+
raise RuntimeError("BUG in coercion model, no element constructor for {}".format(type(codomain)))
|
|
82
|
+
|
|
83
|
+
def _repr_type(self):
|
|
84
|
+
r"""
|
|
85
|
+
Return a printable type for this morphism.
|
|
86
|
+
|
|
87
|
+
EXAMPLES::
|
|
88
|
+
|
|
89
|
+
sage: f = GF(11).convert_map_from(GF(7)) # needs sage.rings.finite_rings
|
|
90
|
+
sage: f._repr_type() # needs sage.rings.finite_rings
|
|
91
|
+
'Conversion'
|
|
92
|
+
"""
|
|
93
|
+
return self._repr_type_str or ("Coercion" if self._is_coercion else "Conversion")
|
|
94
|
+
|
|
95
|
+
cpdef Element _call_(self, x):
|
|
96
|
+
"""
|
|
97
|
+
Create an element of the codomain from a single element of the domain.
|
|
98
|
+
|
|
99
|
+
EXAMPLES::
|
|
100
|
+
|
|
101
|
+
sage: f = QQ[['x']].coerce_map_from(QQ)
|
|
102
|
+
sage: f(2/3).parent()
|
|
103
|
+
Power Series Ring in x over Rational Field
|
|
104
|
+
"""
|
|
105
|
+
cdef Parent C = self._codomain
|
|
106
|
+
try:
|
|
107
|
+
return C._element_constructor(C, x)
|
|
108
|
+
except Exception:
|
|
109
|
+
if print_warnings:
|
|
110
|
+
print(type(C), C)
|
|
111
|
+
print(type(C._element_constructor), C._element_constructor)
|
|
112
|
+
raise
|
|
113
|
+
|
|
114
|
+
cpdef Element _call_with_args(self, x, args=(), kwds={}):
|
|
115
|
+
"""
|
|
116
|
+
Create an element of the codomain from an element of the domain, with extra arguments.
|
|
117
|
+
|
|
118
|
+
EXAMPLES::
|
|
119
|
+
|
|
120
|
+
sage: f = QQ[['x']].coerce_map_from(QQ)
|
|
121
|
+
sage: f(2/3, 4)
|
|
122
|
+
2/3 + O(x^4)
|
|
123
|
+
"""
|
|
124
|
+
cdef Parent C = self._codomain
|
|
125
|
+
try:
|
|
126
|
+
if len(args) == 0:
|
|
127
|
+
if len(kwds) == 0:
|
|
128
|
+
# This line is apparently never used in any tests (hivert, 2009-04-28)
|
|
129
|
+
return C._element_constructor(C, x)
|
|
130
|
+
else:
|
|
131
|
+
return C._element_constructor(C, x, **kwds)
|
|
132
|
+
else:
|
|
133
|
+
if len(kwds) == 0:
|
|
134
|
+
return C._element_constructor(C, x, *args)
|
|
135
|
+
else:
|
|
136
|
+
return C._element_constructor(C, x, *args, **kwds)
|
|
137
|
+
except Exception:
|
|
138
|
+
if print_warnings:
|
|
139
|
+
print(type(C), C)
|
|
140
|
+
print(type(C._element_constructor), C._element_constructor)
|
|
141
|
+
raise
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
cdef class DefaultConvertMap_unique(DefaultConvertMap):
|
|
145
|
+
"""
|
|
146
|
+
This morphism simply defers action to the codomain's
|
|
147
|
+
element_constructor method, WITHOUT passing in the codomain as the
|
|
148
|
+
first argument.
|
|
149
|
+
|
|
150
|
+
This is used for creating elements that don't take a parent as the
|
|
151
|
+
first argument to their __init__ method, for example, Integers,
|
|
152
|
+
Rationals, Algebraic Reals... all have a unique parent. It is also
|
|
153
|
+
used when the element_constructor is a bound method (whose self
|
|
154
|
+
argument is assumed to be bound to the codomain).
|
|
155
|
+
"""
|
|
156
|
+
cpdef Element _call_(self, x):
|
|
157
|
+
cdef Parent C = self._codomain
|
|
158
|
+
try:
|
|
159
|
+
return C._element_constructor(x)
|
|
160
|
+
except Exception:
|
|
161
|
+
if print_warnings:
|
|
162
|
+
print(type(C), C)
|
|
163
|
+
print(type(C._element_constructor), C._element_constructor)
|
|
164
|
+
raise
|
|
165
|
+
|
|
166
|
+
cpdef Element _call_with_args(self, x, args=(), kwds={}):
|
|
167
|
+
cdef Parent C = self._codomain
|
|
168
|
+
try:
|
|
169
|
+
if len(args) == 0:
|
|
170
|
+
if len(kwds) == 0:
|
|
171
|
+
return C._element_constructor(x)
|
|
172
|
+
else:
|
|
173
|
+
return C._element_constructor(x, **kwds)
|
|
174
|
+
else:
|
|
175
|
+
if len(kwds) == 0:
|
|
176
|
+
return C._element_constructor(x, *args)
|
|
177
|
+
else:
|
|
178
|
+
return C._element_constructor(x, *args, **kwds)
|
|
179
|
+
except Exception:
|
|
180
|
+
if print_warnings:
|
|
181
|
+
print(type(C), C)
|
|
182
|
+
print(type(C._element_constructor), C._element_constructor)
|
|
183
|
+
raise
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
cdef class NamedConvertMap(Map):
|
|
187
|
+
"""
|
|
188
|
+
This is used for creating elements via the _xxx_ methods.
|
|
189
|
+
|
|
190
|
+
For example, many elements implement an _integer_ method to
|
|
191
|
+
convert to ZZ, or a _rational_ method to convert to QQ.
|
|
192
|
+
"""
|
|
193
|
+
|
|
194
|
+
def __init__(self, domain, codomain, method_name):
|
|
195
|
+
"""
|
|
196
|
+
EXAMPLES::
|
|
197
|
+
|
|
198
|
+
sage: # needs sage.symbolic
|
|
199
|
+
sage: from sage.structure.coerce_maps import NamedConvertMap
|
|
200
|
+
sage: var('t')
|
|
201
|
+
t
|
|
202
|
+
sage: mor = NamedConvertMap(SR, QQ['t'], '_polynomial_')
|
|
203
|
+
sage: mor(t^2/4 + 1)
|
|
204
|
+
1/4*t^2 + 1
|
|
205
|
+
sage: mor = NamedConvertMap(SR, GF(7)[['t']], '_polynomial_')
|
|
206
|
+
sage: mor(t^2/4 + 1)
|
|
207
|
+
1 + 2*t^2
|
|
208
|
+
"""
|
|
209
|
+
if isinstance(domain, type):
|
|
210
|
+
domain = Set_PythonType(domain)
|
|
211
|
+
Map.__init__(self, domain, codomain)
|
|
212
|
+
self._coerce_cost = 400
|
|
213
|
+
self.method_name = method_name
|
|
214
|
+
self._repr_type_str = "Conversion via %s method" % self.method_name
|
|
215
|
+
|
|
216
|
+
cdef dict _extra_slots(self):
|
|
217
|
+
"""
|
|
218
|
+
Helper for copying and pickling.
|
|
219
|
+
|
|
220
|
+
EXAMPLES::
|
|
221
|
+
|
|
222
|
+
sage: # needs sage.symbolic
|
|
223
|
+
sage: from sage.structure.coerce_maps import NamedConvertMap
|
|
224
|
+
sage: var('t')
|
|
225
|
+
t
|
|
226
|
+
sage: phi = NamedConvertMap(SR, QQ['t'], '_polynomial_')
|
|
227
|
+
sage: psi = copy(phi) # indirect doctest
|
|
228
|
+
sage: psi
|
|
229
|
+
Conversion via _polynomial_ method map:
|
|
230
|
+
From: Symbolic Ring
|
|
231
|
+
To: Univariate Polynomial Ring in t over Rational Field
|
|
232
|
+
sage: phi == psi # not implemented
|
|
233
|
+
True
|
|
234
|
+
sage: psi(t^2/4 + 1)
|
|
235
|
+
1/4*t^2 + 1
|
|
236
|
+
sage: psi(t^2/4 + 1) == phi(t^2/4 + 1)
|
|
237
|
+
True
|
|
238
|
+
"""
|
|
239
|
+
slots = Map._extra_slots(self)
|
|
240
|
+
slots['method_name'] = self.method_name
|
|
241
|
+
return slots
|
|
242
|
+
|
|
243
|
+
cdef _update_slots(self, dict _slots):
|
|
244
|
+
"""
|
|
245
|
+
Helper for copying and pickling.
|
|
246
|
+
|
|
247
|
+
EXAMPLES::
|
|
248
|
+
|
|
249
|
+
sage: # needs sage.symbolic
|
|
250
|
+
sage: from sage.structure.coerce_maps import NamedConvertMap
|
|
251
|
+
sage: var('t')
|
|
252
|
+
t
|
|
253
|
+
sage: phi = NamedConvertMap(SR, QQ['t'], '_polynomial_')
|
|
254
|
+
sage: psi = copy(phi) # indirect doctest
|
|
255
|
+
sage: psi
|
|
256
|
+
Conversion via _polynomial_ method map:
|
|
257
|
+
From: Symbolic Ring
|
|
258
|
+
To: Univariate Polynomial Ring in t over Rational Field
|
|
259
|
+
sage: phi == psi # not implemented
|
|
260
|
+
True
|
|
261
|
+
sage: psi(t^2/4 + 1)
|
|
262
|
+
1/4*t^2 + 1
|
|
263
|
+
sage: psi(t^2/4 + 1) == phi(t^2/4 + 1)
|
|
264
|
+
True
|
|
265
|
+
"""
|
|
266
|
+
self.method_name = _slots['method_name']
|
|
267
|
+
Map._update_slots(self, _slots)
|
|
268
|
+
|
|
269
|
+
cpdef Element _call_(self, x):
|
|
270
|
+
"""
|
|
271
|
+
EXAMPLES::
|
|
272
|
+
|
|
273
|
+
sage: from sage.structure.coerce_maps import NamedConvertMap
|
|
274
|
+
sage: f = NamedConvertMap(GF(5), QQ, '_integer_'); f
|
|
275
|
+
Conversion via _integer_ method map:
|
|
276
|
+
From: Finite Field of size 5
|
|
277
|
+
To: Rational Field
|
|
278
|
+
sage: f(19)
|
|
279
|
+
4
|
|
280
|
+
sage: f(19).parent()
|
|
281
|
+
Rational Field
|
|
282
|
+
"""
|
|
283
|
+
cdef Parent C = self._codomain
|
|
284
|
+
try:
|
|
285
|
+
method = getattr(x, self.method_name)
|
|
286
|
+
except AttributeError:
|
|
287
|
+
if print_warnings:
|
|
288
|
+
print(type(x), x)
|
|
289
|
+
print(type(C), C)
|
|
290
|
+
print(self.method_name)
|
|
291
|
+
raise TypeError(f"cannot coerce {x} to {C}")
|
|
292
|
+
cdef Map m
|
|
293
|
+
cdef Element e = method(C)
|
|
294
|
+
if e is None:
|
|
295
|
+
raise RuntimeError("BUG in coercion model: {} method of {} returned None".format(self.method_name, type(x)))
|
|
296
|
+
if e._parent is not C:
|
|
297
|
+
m = C._internal_convert_map_from(e._parent)
|
|
298
|
+
if m is None or m is self:
|
|
299
|
+
raise TypeError
|
|
300
|
+
e = m._call_(e)
|
|
301
|
+
return e
|
|
302
|
+
|
|
303
|
+
cpdef Element _call_with_args(self, x, args=(), kwds={}):
|
|
304
|
+
"""
|
|
305
|
+
EXAMPLES::
|
|
306
|
+
|
|
307
|
+
sage: from sage.structure.coerce_maps import NamedConvertMap
|
|
308
|
+
sage: f = NamedConvertMap(SR, ZZ['x'], '_polynomial_') # needs sage.symbolic
|
|
309
|
+
sage: f(x^2 + 1, check=True) # needs sage.symbolic
|
|
310
|
+
x^2 + 1
|
|
311
|
+
"""
|
|
312
|
+
cdef Parent C = self._codomain
|
|
313
|
+
return C._element_constructor(self._call_(x), *args, **kwds)
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
# Perhaps this could be a method, extracting (<PyMethodDescrObject *>(<object>Parent).coerce_map_from).d_method.ml_meth and/or PyCFunction_GET_FUNCTION(method)
|
|
317
|
+
# and constructing a CCallableConvertMap_class if it is bound to the codomain.
|
|
318
|
+
|
|
319
|
+
cdef class CallableConvertMap(Map):
|
|
320
|
+
def __init__(self, domain, codomain, func, parent_as_first_arg=None):
|
|
321
|
+
r"""
|
|
322
|
+
This lets one easily create maps from any callable object.
|
|
323
|
+
|
|
324
|
+
This is especially useful to create maps from bound methods.
|
|
325
|
+
|
|
326
|
+
EXAMPLES::
|
|
327
|
+
|
|
328
|
+
sage: from sage.structure.coerce_maps import CallableConvertMap
|
|
329
|
+
sage: def foo(P, x): return x/2
|
|
330
|
+
sage: f = CallableConvertMap(ZZ, QQ, foo)
|
|
331
|
+
sage: f(3)
|
|
332
|
+
3/2
|
|
333
|
+
sage: f
|
|
334
|
+
Conversion via foo map:
|
|
335
|
+
From: Integer Ring
|
|
336
|
+
To: Rational Field
|
|
337
|
+
|
|
338
|
+
Create a homomorphism from `\RR` to `\RR^+` viewed as additive groups.
|
|
339
|
+
|
|
340
|
+
::
|
|
341
|
+
|
|
342
|
+
sage: # needs sage.symbolic
|
|
343
|
+
sage: f = CallableConvertMap(RR, RR, exp, parent_as_first_arg=False)
|
|
344
|
+
sage: f(0)
|
|
345
|
+
1.00000000000000
|
|
346
|
+
sage: f(1)
|
|
347
|
+
2.71828182845905
|
|
348
|
+
sage: f(-3)
|
|
349
|
+
0.0497870683678639
|
|
350
|
+
"""
|
|
351
|
+
if isinstance(domain, type):
|
|
352
|
+
domain = Set_PythonType(domain)
|
|
353
|
+
Map.__init__(self, domain, codomain)
|
|
354
|
+
self._coerce_cost = 100
|
|
355
|
+
self._func = func
|
|
356
|
+
if parent_as_first_arg is None:
|
|
357
|
+
if isinstance(func, types.MethodType):
|
|
358
|
+
# can't easily access self
|
|
359
|
+
parent_as_first_arg = False
|
|
360
|
+
elif isinstance(func, BuiltinMethodType):
|
|
361
|
+
parent_as_first_arg = codomain is func.__self__
|
|
362
|
+
else:
|
|
363
|
+
parent_as_first_arg = True
|
|
364
|
+
self._parent_as_first_arg = parent_as_first_arg
|
|
365
|
+
try:
|
|
366
|
+
self._repr_type_str = "Conversion via %s" % self._func.__name__
|
|
367
|
+
except AttributeError:
|
|
368
|
+
self._repr_type_str = "Conversion via %s" % self._func
|
|
369
|
+
|
|
370
|
+
cdef dict _extra_slots(self):
|
|
371
|
+
"""
|
|
372
|
+
Helper for copying and pickling.
|
|
373
|
+
|
|
374
|
+
EXAMPLES::
|
|
375
|
+
|
|
376
|
+
sage: from sage.structure.coerce_maps import CallableConvertMap
|
|
377
|
+
sage: def foo(P, x): return x^2
|
|
378
|
+
sage: f = CallableConvertMap(ZZ, ZZ, foo)
|
|
379
|
+
sage: g = copy(f) # indirect doctest
|
|
380
|
+
sage: f == g # not implemented (todo: implement comparison)
|
|
381
|
+
True
|
|
382
|
+
sage: f(3) == g(3)
|
|
383
|
+
True
|
|
384
|
+
"""
|
|
385
|
+
slots = Map._extra_slots(self)
|
|
386
|
+
slots['_func'] = self._func
|
|
387
|
+
slots['_parent_as_first_arg'] = self._parent_as_first_arg
|
|
388
|
+
return slots
|
|
389
|
+
|
|
390
|
+
cdef _update_slots(self, dict _slots):
|
|
391
|
+
"""
|
|
392
|
+
Helper for copying and pickling.
|
|
393
|
+
|
|
394
|
+
EXAMPLES::
|
|
395
|
+
|
|
396
|
+
sage: from sage.structure.coerce_maps import CallableConvertMap
|
|
397
|
+
sage: def foo(P, x): return x^2
|
|
398
|
+
sage: f = CallableConvertMap(ZZ, ZZ, foo)
|
|
399
|
+
sage: g = copy(f) # indirect doctest
|
|
400
|
+
sage: f == g # not implemented (todo: implement comparison)
|
|
401
|
+
True
|
|
402
|
+
sage: f(3) == g(3)
|
|
403
|
+
True
|
|
404
|
+
"""
|
|
405
|
+
self._func = _slots['_func']
|
|
406
|
+
self._parent_as_first_arg = _slots['_parent_as_first_arg']
|
|
407
|
+
Map._update_slots(self, _slots)
|
|
408
|
+
|
|
409
|
+
cpdef Element _call_(self, x):
|
|
410
|
+
"""
|
|
411
|
+
Because self._func may be anything we do a little bit of sanity
|
|
412
|
+
checking (the return value must be an element with the correct parent).
|
|
413
|
+
|
|
414
|
+
TESTS::
|
|
415
|
+
|
|
416
|
+
sage: from sage.structure.coerce_maps import CallableConvertMap
|
|
417
|
+
sage: def foo(P, x): return x
|
|
418
|
+
sage: f = CallableConvertMap(ZZ, ZZ, foo)
|
|
419
|
+
sage: f(0)
|
|
420
|
+
0
|
|
421
|
+
sage: f = CallableConvertMap(ZZ, QQ, foo)
|
|
422
|
+
sage: f(0)
|
|
423
|
+
Traceback (most recent call last):
|
|
424
|
+
...
|
|
425
|
+
RuntimeError: BUG in coercion model: <function foo at ...> returned element with wrong parent (expected Rational Field got Integer Ring)
|
|
426
|
+
sage: def foo(P, x): return None
|
|
427
|
+
sage: f = CallableConvertMap(ZZ, QQ, foo)
|
|
428
|
+
sage: f(0)
|
|
429
|
+
Traceback (most recent call last):
|
|
430
|
+
...
|
|
431
|
+
RuntimeError: BUG in coercion model: <function foo at ...> returned None
|
|
432
|
+
"""
|
|
433
|
+
cdef Element y
|
|
434
|
+
cdef Parent C = self._codomain
|
|
435
|
+
try:
|
|
436
|
+
if self._parent_as_first_arg:
|
|
437
|
+
y = self._func(C, x)
|
|
438
|
+
else:
|
|
439
|
+
y = self._func(x)
|
|
440
|
+
except Exception:
|
|
441
|
+
if print_warnings:
|
|
442
|
+
print(self._func)
|
|
443
|
+
print(C)
|
|
444
|
+
raise
|
|
445
|
+
if y is None:
|
|
446
|
+
raise RuntimeError("BUG in coercion model: {} returned None".format(self._func))
|
|
447
|
+
elif y._parent is not C:
|
|
448
|
+
raise RuntimeError("BUG in coercion model: {} returned element with wrong parent (expected {} got {})".format(self._func, C, y._parent))
|
|
449
|
+
return y
|
|
450
|
+
|
|
451
|
+
cpdef Element _call_with_args(self, x, args=(), kwds={}):
|
|
452
|
+
"""
|
|
453
|
+
TESTS::
|
|
454
|
+
|
|
455
|
+
sage: from sage.structure.coerce_maps import CallableConvertMap
|
|
456
|
+
sage: def foo(P, x, y): return x or y
|
|
457
|
+
sage: f = CallableConvertMap(ZZ, ZZ, foo)
|
|
458
|
+
sage: f(0, 3)
|
|
459
|
+
3
|
|
460
|
+
sage: f = CallableConvertMap(ZZ, QQ, foo)
|
|
461
|
+
sage: f(0, 3)
|
|
462
|
+
Traceback (most recent call last):
|
|
463
|
+
...
|
|
464
|
+
RuntimeError: BUG in coercion model: <function foo at ...> returned element with wrong parent (expected Rational Field got Integer Ring)
|
|
465
|
+
sage: f(None, None)
|
|
466
|
+
Traceback (most recent call last):
|
|
467
|
+
...
|
|
468
|
+
RuntimeError: BUG in coercion model: <function foo at ...> returned None
|
|
469
|
+
"""
|
|
470
|
+
cdef Element y
|
|
471
|
+
try:
|
|
472
|
+
if self._parent_as_first_arg:
|
|
473
|
+
y = self._func(self._codomain, x, *args, **kwds)
|
|
474
|
+
else:
|
|
475
|
+
y = self._func(x, *args, **kwds)
|
|
476
|
+
except Exception:
|
|
477
|
+
if print_warnings:
|
|
478
|
+
print(self._func)
|
|
479
|
+
print(self._codomain)
|
|
480
|
+
raise
|
|
481
|
+
if y is None:
|
|
482
|
+
raise RuntimeError("BUG in coercion model: %s returned None" % (self._func))
|
|
483
|
+
elif y._parent is not self._codomain:
|
|
484
|
+
raise RuntimeError("BUG in coercion model: %s returned element with wrong parent (expected %s got %s)" % (self._func, self._codomain, y._parent))
|
|
485
|
+
return y
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
cdef class CCallableConvertMap_class(Map):
|
|
489
|
+
cdef Element (*_func)(Parent, object)
|
|
490
|
+
cdef public _name
|
|
491
|
+
|
|
492
|
+
def __init__(self, domain, codomain, name):
|
|
493
|
+
if isinstance(domain, type):
|
|
494
|
+
domain = Set_PythonType(domain)
|
|
495
|
+
Map.__init__(self, domain, codomain)
|
|
496
|
+
self._coerce_cost = 10
|
|
497
|
+
self._name = name
|
|
498
|
+
|
|
499
|
+
cpdef Element _call_(self, x):
|
|
500
|
+
"""
|
|
501
|
+
TESTS::
|
|
502
|
+
|
|
503
|
+
sage: from sage.structure.coerce_maps import test_CCallableConvertMap
|
|
504
|
+
sage: f = test_CCallableConvertMap(QQ, 'test')
|
|
505
|
+
sage: f(1/3)
|
|
506
|
+
-8/27
|
|
507
|
+
"""
|
|
508
|
+
return self._func(self._codomain, x)
|
|
509
|
+
|
|
510
|
+
def _repr_type(self):
|
|
511
|
+
"""
|
|
512
|
+
EXAMPLES::
|
|
513
|
+
|
|
514
|
+
sage: from sage.structure.coerce_maps import test_CCallableConvertMap
|
|
515
|
+
sage: test_CCallableConvertMap(ZZ, 'any name')
|
|
516
|
+
Conversion via c call 'any name' map:
|
|
517
|
+
From: Integer Ring
|
|
518
|
+
To: Integer Ring
|
|
519
|
+
sage: test_CCallableConvertMap(ZZ, None)
|
|
520
|
+
Conversion via c call at 0x... map:
|
|
521
|
+
From: Integer Ring
|
|
522
|
+
To: Integer Ring
|
|
523
|
+
"""
|
|
524
|
+
if self._name is None:
|
|
525
|
+
return "Conversion via c call at 0x%x" % <long>self._func
|
|
526
|
+
else:
|
|
527
|
+
return "Conversion via c call '%s'" % self._name
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
cdef Map CCallableConvertMap(domain, codomain, void* func, name):
|
|
531
|
+
"""
|
|
532
|
+
Use this to create a map from domain to codomain by calling func
|
|
533
|
+
(which must be a function pointer taking a Parent and object, and
|
|
534
|
+
returning an Element in the given Parent).
|
|
535
|
+
|
|
536
|
+
This is the c analogue of CallableConvertMap.
|
|
537
|
+
"""
|
|
538
|
+
# Cython doesn't yet accept function pointers as arguments,
|
|
539
|
+
# change this when it does.
|
|
540
|
+
cdef CCallableConvertMap_class map = CCallableConvertMap_class(domain, codomain, name)
|
|
541
|
+
map._func = <Element (*)(Parent, object)>func
|
|
542
|
+
return map
|
|
543
|
+
|
|
544
|
+
cpdef Element _ccall_test_function(codomain, x):
|
|
545
|
+
"""
|
|
546
|
+
For testing CCallableConvertMap_class. Returns x*x*x-x in the codomain.
|
|
547
|
+
|
|
548
|
+
TESTS::
|
|
549
|
+
|
|
550
|
+
sage: from sage.structure.coerce_maps import _ccall_test_function
|
|
551
|
+
sage: _ccall_test_function(ZZ, 1)
|
|
552
|
+
0
|
|
553
|
+
sage: _ccall_test_function(ZZ, 2)
|
|
554
|
+
6
|
|
555
|
+
sage: _ccall_test_function(ZZ, -3)
|
|
556
|
+
-24
|
|
557
|
+
"""
|
|
558
|
+
return codomain(x*x*x-x)
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
def test_CCallableConvertMap(domain, name=None):
|
|
562
|
+
"""
|
|
563
|
+
For testing CCallableConvertMap_class.
|
|
564
|
+
|
|
565
|
+
TESTS::
|
|
566
|
+
|
|
567
|
+
sage: from sage.structure.coerce_maps import test_CCallableConvertMap
|
|
568
|
+
sage: f = test_CCallableConvertMap(ZZ, 'test'); f
|
|
569
|
+
Conversion via c call 'test' map:
|
|
570
|
+
From: Integer Ring
|
|
571
|
+
To: Integer Ring
|
|
572
|
+
sage: f(3)
|
|
573
|
+
24
|
|
574
|
+
sage: f(9)
|
|
575
|
+
720
|
|
576
|
+
"""
|
|
577
|
+
return CCallableConvertMap(domain, domain, <void*>&_ccall_test_function, name)
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
cdef class ListMorphism(Map):
|
|
581
|
+
|
|
582
|
+
cdef Map _real_morphism
|
|
583
|
+
|
|
584
|
+
def __init__(self, domain, Map real_morphism):
|
|
585
|
+
if not isinstance(domain, Parent):
|
|
586
|
+
domain = Set_PythonType(domain)
|
|
587
|
+
Map.__init__(self, domain, real_morphism.codomain())
|
|
588
|
+
self._coerce_cost = real_morphism._coerce_cost + 3
|
|
589
|
+
self._real_morphism = real_morphism
|
|
590
|
+
self._repr_type_str = "List"
|
|
591
|
+
|
|
592
|
+
cdef dict _extra_slots(self):
|
|
593
|
+
slots = Map._extra_slots(self)
|
|
594
|
+
slots['_real_morphism'] = self._real_morphism
|
|
595
|
+
return slots
|
|
596
|
+
|
|
597
|
+
cdef _update_slots(self, dict _slots):
|
|
598
|
+
self._real_morphism = _slots['_real_morphism']
|
|
599
|
+
Map._update_slots(self, _slots)
|
|
600
|
+
|
|
601
|
+
cpdef Element _call_(self, x):
|
|
602
|
+
try:
|
|
603
|
+
x = x._data
|
|
604
|
+
except AttributeError:
|
|
605
|
+
x = list(x)
|
|
606
|
+
return self._real_morphism._call_(x)
|
|
607
|
+
|
|
608
|
+
cpdef Element _call_with_args(self, x, args=(), kwds={}):
|
|
609
|
+
try:
|
|
610
|
+
x = x._data
|
|
611
|
+
except AttributeError:
|
|
612
|
+
x = list(x)
|
|
613
|
+
return self._real_morphism._call_with_args(x, args, kwds)
|
|
614
|
+
|
|
615
|
+
|
|
616
|
+
cdef class TryMap(Map):
|
|
617
|
+
def __init__(self, Map morphism_preferred, Map morphism_backup, error_types=None):
|
|
618
|
+
"""
|
|
619
|
+
TESTS::
|
|
620
|
+
|
|
621
|
+
sage: sage.structure.coerce_maps.TryMap(RDF.coerce_map_from(QQ), RDF.coerce_map_from(ZZ))
|
|
622
|
+
Traceback (most recent call last):
|
|
623
|
+
...
|
|
624
|
+
TypeError: incorrectly matching parent
|
|
625
|
+
"""
|
|
626
|
+
if (morphism_preferred.domain() is not morphism_backup.domain()
|
|
627
|
+
or morphism_preferred.codomain() is not morphism_backup.codomain()):
|
|
628
|
+
raise TypeError("incorrectly matching parent")
|
|
629
|
+
Map.__init__(self, morphism_preferred.parent())
|
|
630
|
+
self._map_p = morphism_preferred
|
|
631
|
+
self._map_b = morphism_backup
|
|
632
|
+
if error_types is None:
|
|
633
|
+
self._error_types = (ValueError, TypeError, AttributeError)
|
|
634
|
+
else:
|
|
635
|
+
self._error_types = error_types
|
|
636
|
+
|
|
637
|
+
cdef dict _extra_slots(self):
|
|
638
|
+
"""
|
|
639
|
+
Helper for copying and pickling.
|
|
640
|
+
|
|
641
|
+
EXAMPLES::
|
|
642
|
+
|
|
643
|
+
sage: map1 = sage.structure.coerce_maps.CallableConvertMap(ZZ, QQ, lambda parent, x: 1/x)
|
|
644
|
+
sage: map2 = QQ.coerce_map_from(ZZ)
|
|
645
|
+
sage: map = sage.structure.coerce_maps.TryMap(map1, map2, error_types=(ZeroDivisionError,))
|
|
646
|
+
sage: cmap = copy(map) # indirect doctest
|
|
647
|
+
sage: cmap == map # not implemented (todo: implement comparison)
|
|
648
|
+
True
|
|
649
|
+
sage: map(3) == cmap(3)
|
|
650
|
+
True
|
|
651
|
+
sage: map(0) == cmap(0)
|
|
652
|
+
True
|
|
653
|
+
"""
|
|
654
|
+
slots = Map._extra_slots(self)
|
|
655
|
+
slots['_map_p'] = self._map_p
|
|
656
|
+
slots['_map_b'] = self._map_b
|
|
657
|
+
slots['_error_types'] = self._error_types
|
|
658
|
+
return slots
|
|
659
|
+
|
|
660
|
+
cdef _update_slots(self, dict _slots):
|
|
661
|
+
"""
|
|
662
|
+
Helper for copying and pickling.
|
|
663
|
+
|
|
664
|
+
EXAMPLES::
|
|
665
|
+
|
|
666
|
+
sage: map1 = sage.structure.coerce_maps.CallableConvertMap(ZZ, QQ, lambda parent, x: 1/x)
|
|
667
|
+
sage: map2 = QQ.coerce_map_from(ZZ)
|
|
668
|
+
sage: map = sage.structure.coerce_maps.TryMap(map1, map2, error_types=(ZeroDivisionError,))
|
|
669
|
+
sage: cmap = copy(map) # indirect doctest
|
|
670
|
+
sage: cmap == map # not implemented (todo: implement comparison)
|
|
671
|
+
True
|
|
672
|
+
sage: map(3) == cmap(3)
|
|
673
|
+
True
|
|
674
|
+
sage: map(0) == cmap(0)
|
|
675
|
+
True
|
|
676
|
+
"""
|
|
677
|
+
self._map_p = _slots['_map_p']
|
|
678
|
+
self._map_b = _slots['_map_b']
|
|
679
|
+
self._error_types = _slots['_error_types']
|
|
680
|
+
Map._update_slots(self, _slots)
|
|
681
|
+
|
|
682
|
+
cpdef Element _call_(self, x):
|
|
683
|
+
"""
|
|
684
|
+
EXAMPLES::
|
|
685
|
+
|
|
686
|
+
sage: map1 = sage.structure.coerce_maps.CallableConvertMap(ZZ, QQ, lambda parent, x: 1/x)
|
|
687
|
+
sage: map2 = QQ.coerce_map_from(ZZ)
|
|
688
|
+
sage: map = sage.structure.coerce_maps.TryMap(map1, map2, error_types=(ZeroDivisionError,))
|
|
689
|
+
sage: map(3)
|
|
690
|
+
1/3
|
|
691
|
+
sage: map(-7)
|
|
692
|
+
-1/7
|
|
693
|
+
sage: map(0)
|
|
694
|
+
0
|
|
695
|
+
"""
|
|
696
|
+
try:
|
|
697
|
+
return self._map_p._call_(x)
|
|
698
|
+
except self._error_types:
|
|
699
|
+
return self._map_b._call_(x)
|
|
700
|
+
|
|
701
|
+
cpdef Element _call_with_args(self, x, args=(), kwds={}):
|
|
702
|
+
"""
|
|
703
|
+
EXAMPLES::
|
|
704
|
+
|
|
705
|
+
sage: map1 = sage.structure.coerce_maps.CallableConvertMap(ZZ, QQ, lambda parent, x, y: y/x)
|
|
706
|
+
sage: map2 = sage.structure.coerce_maps.CallableConvertMap(ZZ, QQ, lambda parent, x, y: 23/1)
|
|
707
|
+
sage: map = sage.structure.coerce_maps.TryMap(map1, map2, error_types=(ZeroDivisionError,))
|
|
708
|
+
sage: map._call_with_args(3, (2,))
|
|
709
|
+
2/3
|
|
710
|
+
sage: map._call_with_args(-7, (5,))
|
|
711
|
+
-5/7
|
|
712
|
+
sage: map._call_with_args(0, (1,))
|
|
713
|
+
23
|
|
714
|
+
"""
|
|
715
|
+
try:
|
|
716
|
+
return self._map_p._call_with_args(x, args, kwds)
|
|
717
|
+
except self._error_types:
|
|
718
|
+
return self._map_b._call_with_args(x, args, kwds)
|