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
sage/arith/long.pxd
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-objects
|
|
2
|
+
# sage.doctest: needs sage.misc.cython
|
|
3
|
+
r"""
|
|
4
|
+
Fast conversion of Python objects to C long
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# ****************************************************************************
|
|
8
|
+
# Copyright (C) 2015 Vincent Delecroix <20100.delecroix@gmail.com>
|
|
9
|
+
# Copyright (C) 2017 Jeroen Demeyer <J.Demeyer@UGent.be>
|
|
10
|
+
#
|
|
11
|
+
# This program is free software: you can redistribute it and/or modify
|
|
12
|
+
# it under the terms of the GNU General Public License as published by
|
|
13
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
14
|
+
# (at your option) any later version.
|
|
15
|
+
# https://www.gnu.org/licenses/
|
|
16
|
+
# ****************************************************************************
|
|
17
|
+
|
|
18
|
+
from libc.limits cimport LONG_MIN, LONG_MAX
|
|
19
|
+
|
|
20
|
+
from cpython.object cimport Py_SIZE
|
|
21
|
+
from cpython.number cimport PyNumber_Index, PyIndex_Check
|
|
22
|
+
from cpython.longintrepr cimport py_long, PyLong_SHIFT, digit
|
|
23
|
+
from sage.cpython.pycore_long cimport (
|
|
24
|
+
ob_digit, _PyLong_IsNegative, _PyLong_DigitCount)
|
|
25
|
+
|
|
26
|
+
from sage.libs.gmp.mpz cimport mpz_fits_slong_p, mpz_get_si
|
|
27
|
+
from sage.rings.integer_fake cimport is_Integer, Integer_AS_MPZ
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
cdef inline long pyobject_to_long(x) except? LONG_MIN:
|
|
31
|
+
r"""
|
|
32
|
+
Given a Python object ``x`` cast it quickly to a C long.
|
|
33
|
+
|
|
34
|
+
A :exc:`TypeError` is raised if the input cannot be converted to
|
|
35
|
+
an integer or
|
|
36
|
+
an :exc:`OverflowError` is raised if it does not fit into a C long.
|
|
37
|
+
|
|
38
|
+
TESTS:
|
|
39
|
+
|
|
40
|
+
We test indirectly that ``Integer.__pow__`` works::
|
|
41
|
+
|
|
42
|
+
sage: a = 10
|
|
43
|
+
sage: a^10
|
|
44
|
+
10000000000
|
|
45
|
+
sage: a^(10r)
|
|
46
|
+
10000000000
|
|
47
|
+
sage: a^(10l)
|
|
48
|
+
10000000000
|
|
49
|
+
sage: a^(10/1)
|
|
50
|
+
10000000000
|
|
51
|
+
sage: a^(2**258)
|
|
52
|
+
Traceback (most recent call last):
|
|
53
|
+
...
|
|
54
|
+
OverflowError: exponent must be at most 2147483647 # 32-bit
|
|
55
|
+
OverflowError: exponent must be at most 9223372036854775807 # 64-bit
|
|
56
|
+
|
|
57
|
+
See :issue:`22319`::
|
|
58
|
+
|
|
59
|
+
sage: a^pari(10)
|
|
60
|
+
10000000000
|
|
61
|
+
"""
|
|
62
|
+
cdef long value
|
|
63
|
+
cdef int err
|
|
64
|
+
if integer_check_long_py(x, &value, &err):
|
|
65
|
+
if err:
|
|
66
|
+
raise OverflowError("Python int too large to convert to C long")
|
|
67
|
+
return value
|
|
68
|
+
if is_Integer(x):
|
|
69
|
+
z = Integer_AS_MPZ(x)
|
|
70
|
+
if mpz_fits_slong_p(z):
|
|
71
|
+
return mpz_get_si(z)
|
|
72
|
+
else:
|
|
73
|
+
raise OverflowError("Sage Integer too large to convert to C long")
|
|
74
|
+
|
|
75
|
+
return PyNumber_Index(x)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
# Error values for integer_check_long()
|
|
79
|
+
cdef enum:
|
|
80
|
+
ERR_TYPE = 1
|
|
81
|
+
ERR_INDEX = 2
|
|
82
|
+
ERR_OVERFLOW = 3
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
cdef inline bint integer_check_long(x, long* value, int* err) except -1:
|
|
86
|
+
"""
|
|
87
|
+
Return whether ``x`` is some integer type. This is true for the
|
|
88
|
+
Python type ``int``, for Sage Integers and for types
|
|
89
|
+
implementing ``__index__``.
|
|
90
|
+
|
|
91
|
+
If possible, compute the value of this integer as C long and store
|
|
92
|
+
it in ``*value``.
|
|
93
|
+
|
|
94
|
+
Errors are returned as an error indicator ``*err`` (without raising
|
|
95
|
+
any Python exception).
|
|
96
|
+
|
|
97
|
+
Possible errors when returning ``True``:
|
|
98
|
+
|
|
99
|
+
- ``0`` -- ``x`` was successfully converted to a C long and its value
|
|
100
|
+
is stored in ``*value``
|
|
101
|
+
|
|
102
|
+
- ``ERR_OVERFLOW`` -- ``x`` is an integer type but too large to store
|
|
103
|
+
in a C long
|
|
104
|
+
|
|
105
|
+
Possible errors when returning ``False``:
|
|
106
|
+
|
|
107
|
+
- ``ERR_TYPE`` -- ``x`` is not an integer type of any kind
|
|
108
|
+
|
|
109
|
+
- ``ERR_INDEX`` -- ``x`` implements ``__index__`` but a :exc:`TypeError`
|
|
110
|
+
was raised calling ``__index__()``
|
|
111
|
+
|
|
112
|
+
- Other exceptions in ``__index__`` are simply propagated. This is
|
|
113
|
+
the only way this function can raise an exception.
|
|
114
|
+
|
|
115
|
+
EXAMPLES:
|
|
116
|
+
|
|
117
|
+
We create a pure Python wrapper of this function::
|
|
118
|
+
|
|
119
|
+
sage: cython('''
|
|
120
|
+
....: from sage.arith.long cimport *
|
|
121
|
+
....: from sage.rings.integer cimport smallInteger
|
|
122
|
+
....: def check_long(x):
|
|
123
|
+
....: cdef long value
|
|
124
|
+
....: cdef int err
|
|
125
|
+
....: cdef bint c = integer_check_long(x, &value, &err)
|
|
126
|
+
....: if c:
|
|
127
|
+
....: if err == 0:
|
|
128
|
+
....: return value
|
|
129
|
+
....: elif err == ERR_OVERFLOW:
|
|
130
|
+
....: raise OverflowError(f"integer_check_long: overflow ({x})")
|
|
131
|
+
....: elif err == ERR_TYPE:
|
|
132
|
+
....: raise TypeError("integer_check_long: wrong type")
|
|
133
|
+
....: elif err == ERR_INDEX:
|
|
134
|
+
....: raise TypeError("integer_check_long: bad __index__")
|
|
135
|
+
....: assert False
|
|
136
|
+
....: from libc.limits cimport LONG_MIN, LONG_MAX
|
|
137
|
+
....: def long_min():
|
|
138
|
+
....: return smallInteger(LONG_MIN)
|
|
139
|
+
....: def long_max():
|
|
140
|
+
....: return smallInteger(LONG_MAX)
|
|
141
|
+
....: ''')
|
|
142
|
+
sage: L = [1, 12345, 10^9, 2^30, long_max()//9, long_max()//3, long_max()]
|
|
143
|
+
sage: L += [-x for x in L] + [0, long_min()]
|
|
144
|
+
sage: for v in L:
|
|
145
|
+
....: for t in (Integer, int, QQ):
|
|
146
|
+
....: assert check_long(t(v)) == v
|
|
147
|
+
sage: check_long(2^100)
|
|
148
|
+
Traceback (most recent call last):
|
|
149
|
+
...
|
|
150
|
+
OverflowError: integer_check_long: overflow (...)
|
|
151
|
+
sage: check_long(long_max() + 1)
|
|
152
|
+
Traceback (most recent call last):
|
|
153
|
+
...
|
|
154
|
+
OverflowError: integer_check_long: overflow (...)
|
|
155
|
+
sage: check_long(long_min() - 1)
|
|
156
|
+
Traceback (most recent call last):
|
|
157
|
+
...
|
|
158
|
+
OverflowError: integer_check_long: overflow (...)
|
|
159
|
+
sage: check_long("hello")
|
|
160
|
+
Traceback (most recent call last):
|
|
161
|
+
...
|
|
162
|
+
TypeError: integer_check_long: wrong type
|
|
163
|
+
sage: check_long(2/3)
|
|
164
|
+
Traceback (most recent call last):
|
|
165
|
+
...
|
|
166
|
+
TypeError: integer_check_long: bad __index__
|
|
167
|
+
|
|
168
|
+
Repeat the overflow tests with python integers:
|
|
169
|
+
|
|
170
|
+
sage: check_long(int(2^100))
|
|
171
|
+
Traceback (most recent call last):
|
|
172
|
+
...
|
|
173
|
+
OverflowError: integer_check_long: overflow (...)
|
|
174
|
+
sage: check_long(int(long_max() + 1))
|
|
175
|
+
Traceback (most recent call last):
|
|
176
|
+
...
|
|
177
|
+
OverflowError: integer_check_long: overflow (...)
|
|
178
|
+
sage: check_long(int(long_min() - 1))
|
|
179
|
+
Traceback (most recent call last):
|
|
180
|
+
...
|
|
181
|
+
OverflowError: integer_check_long: overflow (...)
|
|
182
|
+
|
|
183
|
+
And again with rationals:
|
|
184
|
+
|
|
185
|
+
sage: check_long(QQ(2^100))
|
|
186
|
+
Traceback (most recent call last):
|
|
187
|
+
...
|
|
188
|
+
OverflowError: integer_check_long: overflow (...)
|
|
189
|
+
sage: check_long(QQ(long_max() + 1))
|
|
190
|
+
Traceback (most recent call last):
|
|
191
|
+
...
|
|
192
|
+
OverflowError: integer_check_long: overflow (...)
|
|
193
|
+
sage: check_long(QQ(long_min() - 1))
|
|
194
|
+
Traceback (most recent call last):
|
|
195
|
+
...
|
|
196
|
+
OverflowError: integer_check_long: overflow (...)
|
|
197
|
+
"""
|
|
198
|
+
cdef int c = integer_check_long_py(x, value, err)
|
|
199
|
+
if c:
|
|
200
|
+
return c
|
|
201
|
+
if is_Integer(x):
|
|
202
|
+
z = Integer_AS_MPZ(x)
|
|
203
|
+
if mpz_fits_slong_p(z):
|
|
204
|
+
value[0] = mpz_get_si(z)
|
|
205
|
+
err[0] = 0
|
|
206
|
+
else:
|
|
207
|
+
err[0] = ERR_OVERFLOW
|
|
208
|
+
return 1
|
|
209
|
+
elif PyIndex_Check(x):
|
|
210
|
+
err[0] = ERR_INDEX
|
|
211
|
+
try:
|
|
212
|
+
x = PyNumber_Index(x)
|
|
213
|
+
except TypeError:
|
|
214
|
+
return 0
|
|
215
|
+
return integer_check_long_py(x, value, err)
|
|
216
|
+
else:
|
|
217
|
+
err[0] = ERR_TYPE
|
|
218
|
+
return 0
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
cdef inline long dig(const digit* D, int n) noexcept:
|
|
222
|
+
# Convenient helper function for integer_check_long_py()
|
|
223
|
+
return (<long>D[n]) << (n * PyLong_SHIFT)
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
cdef inline bint integer_check_long_py(x, long* value, int* err) noexcept:
|
|
227
|
+
"""
|
|
228
|
+
Return whether ``x`` is a Python object of type ``int``.
|
|
229
|
+
|
|
230
|
+
If possible, compute the value of this integer as C long and store
|
|
231
|
+
it in ``*value``.
|
|
232
|
+
|
|
233
|
+
Errors are returned as an error indicator ``*err`` (without raising
|
|
234
|
+
any Python exception).
|
|
235
|
+
|
|
236
|
+
Possible errors when returning ``True``:
|
|
237
|
+
|
|
238
|
+
- ``0`` -- ``x`` was successfully converted to a C long and its value
|
|
239
|
+
is stored in ``*value``
|
|
240
|
+
|
|
241
|
+
- ``ERR_OVERFLOW`` -- ``x`` is a Python object of type ``int`` but
|
|
242
|
+
too large to store in a C long
|
|
243
|
+
|
|
244
|
+
Possible errors when returning ``False``:
|
|
245
|
+
|
|
246
|
+
- ``ERR_TYPE`` -- ``x`` is not a Python object of type ``int``
|
|
247
|
+
|
|
248
|
+
EXAMPLES:
|
|
249
|
+
|
|
250
|
+
We create a pure Python wrapper of this function::
|
|
251
|
+
|
|
252
|
+
sage: cython('''
|
|
253
|
+
....: from sage.arith.long cimport *
|
|
254
|
+
....: def check_long_py(x):
|
|
255
|
+
....: cdef long value
|
|
256
|
+
....: cdef int err
|
|
257
|
+
....: cdef bint c = integer_check_long_py(x, &value, &err)
|
|
258
|
+
....: if c:
|
|
259
|
+
....: if err == 0:
|
|
260
|
+
....: return value
|
|
261
|
+
....: elif err == ERR_OVERFLOW:
|
|
262
|
+
....: return f"Overflow ({x})"
|
|
263
|
+
....: elif err == ERR_TYPE:
|
|
264
|
+
....: return f"Bad type ({x})"
|
|
265
|
+
....: return f"This should never happen ({x})"
|
|
266
|
+
....: from libc.limits cimport LONG_MIN, LONG_MAX
|
|
267
|
+
....: def long_min():
|
|
268
|
+
....: return LONG_MIN
|
|
269
|
+
....: def long_max():
|
|
270
|
+
....: return LONG_MAX
|
|
271
|
+
....: ''')
|
|
272
|
+
sage: L = [1, 12345, 10^9, 2^30, long_max()//9, long_max()//3, long_max()]
|
|
273
|
+
sage: L += [-x for x in L] + [0, long_min()]
|
|
274
|
+
sage: for v in L:
|
|
275
|
+
....: assert check_long_py(int(v)) == v
|
|
276
|
+
sage: check_long_py(int(2^60))
|
|
277
|
+
1152921504606846976 # 64-bit
|
|
278
|
+
'Overflow (...)' # 32-bit
|
|
279
|
+
sage: check_long_py(int(2^61))
|
|
280
|
+
2305843009213693952 # 64-bit
|
|
281
|
+
'Overflow (...)' # 32-bit
|
|
282
|
+
sage: check_long_py(int(2^62))
|
|
283
|
+
4611686018427387904 # 64-bit
|
|
284
|
+
'Overflow (...)' # 32-bit
|
|
285
|
+
sage: check_long_py(int(2^63))
|
|
286
|
+
'Overflow (...)'
|
|
287
|
+
sage: check_long_py(int(2^100))
|
|
288
|
+
'Overflow (...)'
|
|
289
|
+
sage: check_long_py(int(long_max() + 1))
|
|
290
|
+
'Overflow (...)'
|
|
291
|
+
sage: check_long_py(int(long_min() - 1))
|
|
292
|
+
'Overflow (...)'
|
|
293
|
+
sage: check_long_py(389)
|
|
294
|
+
'Bad type (...)'
|
|
295
|
+
sage: check_long_py("hello")
|
|
296
|
+
'Bad type (...)'
|
|
297
|
+
sage: check_long_py(2/3)
|
|
298
|
+
'Bad type (...)'
|
|
299
|
+
"""
|
|
300
|
+
if not isinstance(x, int):
|
|
301
|
+
err[0] = ERR_TYPE
|
|
302
|
+
return 0
|
|
303
|
+
|
|
304
|
+
# x is a Python "int" (aka PyLongObject or py_long in cython)
|
|
305
|
+
cdef const digit* D = ob_digit(x)
|
|
306
|
+
cdef Py_ssize_t size = _PyLong_DigitCount(x)
|
|
307
|
+
|
|
308
|
+
if _PyLong_IsNegative(x):
|
|
309
|
+
size = -size
|
|
310
|
+
|
|
311
|
+
# We assume PyLong_SHIFT <= BITS_IN_LONG <= 3 * PyLong_SHIFT.
|
|
312
|
+
# This is true in all the default configurations:
|
|
313
|
+
# - BITS_IN_LONG = 63, PyLong_SHIFT = 30
|
|
314
|
+
# - BITS_IN_LONG = 31, PyLong_SHIFT = 15 (python <= 3.10)
|
|
315
|
+
# - BITS_IN_LONG = 31, PyLong_SHIFT = 30 (new in python 3.11)
|
|
316
|
+
# cf. https://github.com/sagemath/sage/issues/33842#comment:130
|
|
317
|
+
#
|
|
318
|
+
# This way, we know that 1 digit certainly fits in a C long
|
|
319
|
+
# and 4 or more digits never fit.
|
|
320
|
+
# For 2 or 3 digits, we need an explicit overflow check.
|
|
321
|
+
cdef int BITS_IN_LONG = 8 * sizeof(long) - 1
|
|
322
|
+
if not (PyLong_SHIFT <= BITS_IN_LONG <= 3 * PyLong_SHIFT):
|
|
323
|
+
raise AssertionError(
|
|
324
|
+
f"PyLong_SHIFT = {PyLong_SHIFT}, "
|
|
325
|
+
f"BITS_IN_LONG = {BITS_IN_LONG}")
|
|
326
|
+
|
|
327
|
+
cdef long lead
|
|
328
|
+
cdef long lead_2_overflow = (<long>1) << (BITS_IN_LONG - PyLong_SHIFT)
|
|
329
|
+
cdef long lead_3_overflow
|
|
330
|
+
if BITS_IN_LONG < 2 * PyLong_SHIFT:
|
|
331
|
+
# in this case 3 digit is always overflow
|
|
332
|
+
lead_3_overflow = 0
|
|
333
|
+
else:
|
|
334
|
+
lead_3_overflow = (<long>1) << (BITS_IN_LONG - 2 * PyLong_SHIFT)
|
|
335
|
+
if size == 0:
|
|
336
|
+
value[0] = 0
|
|
337
|
+
err[0] = 0
|
|
338
|
+
elif size == 1:
|
|
339
|
+
value[0] = dig(D, 0)
|
|
340
|
+
err[0] = 0
|
|
341
|
+
elif size == -1:
|
|
342
|
+
value[0] = -dig(D, 0)
|
|
343
|
+
err[0] = 0
|
|
344
|
+
elif size == 2:
|
|
345
|
+
if BITS_IN_LONG < 2 * PyLong_SHIFT and D[1] >= lead_2_overflow:
|
|
346
|
+
err[0] = ERR_OVERFLOW
|
|
347
|
+
return 1
|
|
348
|
+
value[0] = dig(D, 0) + dig(D, 1)
|
|
349
|
+
err[0] = 0
|
|
350
|
+
elif size == -2:
|
|
351
|
+
if BITS_IN_LONG < 2 * PyLong_SHIFT and D[1] >= lead_2_overflow:
|
|
352
|
+
if D[0] == 0 and D[1] == lead_2_overflow:
|
|
353
|
+
# Special case for LONG_MIN
|
|
354
|
+
value[0] = (<long>-1) << BITS_IN_LONG
|
|
355
|
+
err[0] = 0
|
|
356
|
+
else:
|
|
357
|
+
err[0] = ERR_OVERFLOW
|
|
358
|
+
return 1
|
|
359
|
+
value[0] = -(dig(D, 0) + dig(D, 1))
|
|
360
|
+
err[0] = 0
|
|
361
|
+
elif size == 3:
|
|
362
|
+
lead = D[2]
|
|
363
|
+
if lead < lead_3_overflow:
|
|
364
|
+
value[0] = dig(D, 0) + dig(D, 1) + dig(D, 2)
|
|
365
|
+
err[0] = 0
|
|
366
|
+
else:
|
|
367
|
+
err[0] = ERR_OVERFLOW
|
|
368
|
+
elif size == -3:
|
|
369
|
+
lead = D[2]
|
|
370
|
+
if lead < lead_3_overflow:
|
|
371
|
+
value[0] = -(dig(D, 0) + dig(D, 1) + dig(D, 2))
|
|
372
|
+
err[0] = 0
|
|
373
|
+
elif D[0] == 0 and D[1] == 0 and lead == lead_3_overflow:
|
|
374
|
+
# Special case for LONG_MIN
|
|
375
|
+
value[0] = (<long>-1) << BITS_IN_LONG
|
|
376
|
+
err[0] = 0
|
|
377
|
+
else:
|
|
378
|
+
err[0] = ERR_OVERFLOW
|
|
379
|
+
else:
|
|
380
|
+
# 4 digits or more: guaranteed overflow
|
|
381
|
+
err[0] = ERR_OVERFLOW
|
|
382
|
+
return 1
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
cdef inline bint is_small_python_int(obj) noexcept:
|
|
386
|
+
"""
|
|
387
|
+
Test whether Python object is a small Python integer.
|
|
388
|
+
|
|
389
|
+
Meaning that it can be converted to a C long. In Python 2,
|
|
390
|
+
this is equivalent to it being the ``int`` Python type. In Python
|
|
391
|
+
3, the ``int`` Python type has unlimited precision so we need to
|
|
392
|
+
check its range.
|
|
393
|
+
|
|
394
|
+
EXAMPLES::
|
|
395
|
+
|
|
396
|
+
sage: cython('''
|
|
397
|
+
....: from sage.arith.long cimport is_small_python_int
|
|
398
|
+
....: def is_small_wrapper(x):
|
|
399
|
+
....: return is_small_python_int(x)
|
|
400
|
+
....: ''')
|
|
401
|
+
sage: is_small_wrapper(int(3))
|
|
402
|
+
True
|
|
403
|
+
sage: is_small_wrapper(ZZ(3)) # not a Python int
|
|
404
|
+
False
|
|
405
|
+
sage: import sys
|
|
406
|
+
sage: is_small_wrapper(int(sys.maxsize)) # does fit into C long
|
|
407
|
+
True
|
|
408
|
+
sage: is_small_wrapper(int(sys.maxsize + 1)) # does not fit into C long
|
|
409
|
+
False
|
|
410
|
+
"""
|
|
411
|
+
return (type(obj) is int) and (LONG_MIN <= obj <= LONG_MAX)
|
|
Binary file
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-objects
|
|
2
|
+
# sage.doctest: needs sage.rings.real_mpfr
|
|
3
|
+
|
|
4
|
+
cpdef inline long digits_to_bits(d) except -1:
|
|
5
|
+
"""
|
|
6
|
+
EXAMPLES::
|
|
7
|
+
|
|
8
|
+
sage: from sage.arith.numerical_approx import digits_to_bits
|
|
9
|
+
sage: digits_to_bits(None)
|
|
10
|
+
53
|
|
11
|
+
sage: digits_to_bits(15)
|
|
12
|
+
54
|
|
13
|
+
sage: digits_to_bits(-1)
|
|
14
|
+
Traceback (most recent call last):
|
|
15
|
+
...
|
|
16
|
+
ValueError: number of digits must be positive
|
|
17
|
+
|
|
18
|
+
TESTS::
|
|
19
|
+
|
|
20
|
+
sage: digits_to_bits("10")
|
|
21
|
+
Traceback (most recent call last):
|
|
22
|
+
...
|
|
23
|
+
TypeError: must be real number, not str
|
|
24
|
+
"""
|
|
25
|
+
if d is None:
|
|
26
|
+
return 53
|
|
27
|
+
cdef double x = d
|
|
28
|
+
if x <= 0:
|
|
29
|
+
raise ValueError("number of digits must be positive")
|
|
30
|
+
|
|
31
|
+
# Add 1 because of the way how we display real numbers by default
|
|
32
|
+
x += 1
|
|
33
|
+
cdef double LOG_TEN_TWO = 3.321928094887362
|
|
34
|
+
# Add 1 to round up
|
|
35
|
+
return <long>(x * LOG_TEN_TWO) + 1
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-objects
|
|
2
|
+
# sage.doctest: needs sage.rings.real_mpfr
|
|
3
|
+
r"""
|
|
4
|
+
Generic numerical approximation function
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# ****************************************************************************
|
|
8
|
+
# Copyright (C) 2016 Jeroen Demeyer <jdemeyer@cage.ugent.be>
|
|
9
|
+
#
|
|
10
|
+
# This program is free software: you can redistribute it and/or modify
|
|
11
|
+
# it under the terms of the GNU General Public License as published by
|
|
12
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
13
|
+
# (at your option) any later version.
|
|
14
|
+
# https://www.gnu.org/licenses/
|
|
15
|
+
# ****************************************************************************
|
|
16
|
+
|
|
17
|
+
from sage.structure.parent cimport Parent
|
|
18
|
+
from sage.structure.element cimport parent
|
|
19
|
+
cdef Parent CDF
|
|
20
|
+
from sage.rings.real_mpfr import RealField
|
|
21
|
+
from sage.rings.complex_mpfr import ComplexField
|
|
22
|
+
from sage.rings.complex_double import CDF
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def numerical_approx_generic(x, prec):
|
|
26
|
+
"""
|
|
27
|
+
Generic implementation of ``numerical_approx`` using coercion or
|
|
28
|
+
conversion to a real or complex field.
|
|
29
|
+
|
|
30
|
+
EXAMPLES::
|
|
31
|
+
|
|
32
|
+
sage: from sage.arith.numerical_approx import numerical_approx_generic
|
|
33
|
+
sage: numerical_approx_generic(pi, 20) # needs sage.symbolic
|
|
34
|
+
3.1416
|
|
35
|
+
sage: numerical_approx_generic(int(42), 20)
|
|
36
|
+
42.000
|
|
37
|
+
sage: numerical_approx_generic(float(4.2), 20)
|
|
38
|
+
4.2000
|
|
39
|
+
"""
|
|
40
|
+
P = parent(x)
|
|
41
|
+
|
|
42
|
+
cdef Parent RR = RealField(prec)
|
|
43
|
+
cmap = RR.coerce_map_from(P)
|
|
44
|
+
if cmap is not None:
|
|
45
|
+
return cmap(x)
|
|
46
|
+
|
|
47
|
+
cdef Parent CC = ComplexField(prec)
|
|
48
|
+
cmap = CC.coerce_map_from(P)
|
|
49
|
+
if cmap is not None:
|
|
50
|
+
return cmap(x)
|
|
51
|
+
|
|
52
|
+
# Coercion didn't work: there are 3 possibilities:
|
|
53
|
+
# (1) There is a coercion possible to a lower precision
|
|
54
|
+
# (2) There is a conversion but no coercion
|
|
55
|
+
# (3) The type doesn't convert at all
|
|
56
|
+
|
|
57
|
+
# Figure out input precision to check for case (1)
|
|
58
|
+
try:
|
|
59
|
+
inprec = x.prec()
|
|
60
|
+
except AttributeError:
|
|
61
|
+
if prec > 53 and CDF.has_coerce_map_from(P):
|
|
62
|
+
# If we can coerce to CDF, assume input precision was 53 bits
|
|
63
|
+
inprec = 53
|
|
64
|
+
else:
|
|
65
|
+
# Otherwise, assume precision wasn't the issue
|
|
66
|
+
inprec = prec
|
|
67
|
+
|
|
68
|
+
if prec > inprec:
|
|
69
|
+
raise TypeError("cannot approximate to a precision of %s bits, use at most %s bits" % (prec, inprec))
|
|
70
|
+
|
|
71
|
+
# The issue is not precision, try conversion instead
|
|
72
|
+
try:
|
|
73
|
+
return RR(x)
|
|
74
|
+
except (TypeError, ValueError):
|
|
75
|
+
return CC(x)
|
|
Binary file
|
sage/arith/power.pxd
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-objects
|
|
2
|
+
from cpython.number cimport PyNumber_TrueDivide
|
|
3
|
+
from sage.structure.element cimport Element
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
ctypedef fused ulong_or_object:
|
|
7
|
+
unsigned long
|
|
8
|
+
object
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
cpdef generic_power(a, n)
|
|
12
|
+
cdef generic_power_long(a, long n)
|
|
13
|
+
cdef generic_power_pos(a, ulong_or_object n) # n > 0
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
cdef inline invert(a):
|
|
17
|
+
"""
|
|
18
|
+
Return ``a^(-1)``.
|
|
19
|
+
"""
|
|
20
|
+
if isinstance(a, Element):
|
|
21
|
+
return ~a
|
|
22
|
+
return PyNumber_TrueDivide(type(a)(1), a)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
cdef inline one(a):
|
|
26
|
+
"""
|
|
27
|
+
Return ``a^0``.
|
|
28
|
+
"""
|
|
29
|
+
if isinstance(a, Element):
|
|
30
|
+
return (<Element>a)._parent.one()
|
|
31
|
+
return type(a)(1)
|
sage/arith/power.pyx
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-objects
|
|
2
|
+
"""
|
|
3
|
+
Generic implementation of powering
|
|
4
|
+
|
|
5
|
+
This implements powering of arbitrary objects using a
|
|
6
|
+
square-and-multiply algorithm.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# ****************************************************************************
|
|
10
|
+
# Copyright (C) 2017 Jeroen Demeyer <J.Demeyer@UGent.be>
|
|
11
|
+
#
|
|
12
|
+
# This program is free software: you can redistribute it and/or modify
|
|
13
|
+
# it under the terms of the GNU General Public License as published by
|
|
14
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
15
|
+
# (at your option) any later version.
|
|
16
|
+
# https://www.gnu.org/licenses/
|
|
17
|
+
# ****************************************************************************
|
|
18
|
+
|
|
19
|
+
from cysignals.signals cimport sig_check
|
|
20
|
+
|
|
21
|
+
from sage.arith.long cimport integer_check_long
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
cpdef generic_power(a, n):
|
|
25
|
+
"""
|
|
26
|
+
Return `a^n`.
|
|
27
|
+
|
|
28
|
+
If `n` is negative, return `(1/a)^{-n}`.
|
|
29
|
+
|
|
30
|
+
INPUT:
|
|
31
|
+
|
|
32
|
+
- ``a`` -- any object supporting multiplication
|
|
33
|
+
(and division if n < 0)
|
|
34
|
+
|
|
35
|
+
- ``n`` -- any integer (in the duck typing sense)
|
|
36
|
+
|
|
37
|
+
EXAMPLES::
|
|
38
|
+
|
|
39
|
+
sage: from sage.arith.power import generic_power
|
|
40
|
+
sage: generic_power(int(12), int(0))
|
|
41
|
+
1
|
|
42
|
+
sage: generic_power(int(0), int(100))
|
|
43
|
+
0
|
|
44
|
+
sage: generic_power(Integer(10), Integer(0))
|
|
45
|
+
1
|
|
46
|
+
sage: generic_power(Integer(0), Integer(23))
|
|
47
|
+
0
|
|
48
|
+
sage: sum([generic_power(2,i) for i in range(17)]) #test all 4-bit combinations
|
|
49
|
+
131071
|
|
50
|
+
sage: F = Zmod(5)
|
|
51
|
+
sage: a = generic_power(F(2), 5); a
|
|
52
|
+
2
|
|
53
|
+
sage: a.parent() is F
|
|
54
|
+
True
|
|
55
|
+
sage: a = generic_power(F(1), 2)
|
|
56
|
+
sage: a.parent() is F
|
|
57
|
+
True
|
|
58
|
+
|
|
59
|
+
sage: generic_power(int(5), 0)
|
|
60
|
+
1
|
|
61
|
+
sage: generic_power(2, 5/4)
|
|
62
|
+
Traceback (most recent call last):
|
|
63
|
+
...
|
|
64
|
+
NotImplementedError: non-integral exponents not supported
|
|
65
|
+
|
|
66
|
+
::
|
|
67
|
+
|
|
68
|
+
sage: class SymbolicMul(str):
|
|
69
|
+
....: def __mul__(self, other):
|
|
70
|
+
....: s = "({}*{})".format(self, other)
|
|
71
|
+
....: return type(self)(s)
|
|
72
|
+
sage: x = SymbolicMul("x")
|
|
73
|
+
sage: print(generic_power(x, 7))
|
|
74
|
+
(((x*x)*(x*x))*((x*x)*x))
|
|
75
|
+
"""
|
|
76
|
+
if not n:
|
|
77
|
+
return one(a)
|
|
78
|
+
|
|
79
|
+
cdef long value = 0
|
|
80
|
+
cdef int err
|
|
81
|
+
if not integer_check_long(n, &value, &err):
|
|
82
|
+
raise NotImplementedError("non-integral exponents not supported")
|
|
83
|
+
if not err:
|
|
84
|
+
return generic_power_long(a, value)
|
|
85
|
+
|
|
86
|
+
if n < 0:
|
|
87
|
+
n = -n
|
|
88
|
+
a = invert(a)
|
|
89
|
+
return generic_power_pos(a, n)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
cdef generic_power_long(a, long n):
|
|
93
|
+
"""
|
|
94
|
+
As ``generic_power`` but where ``n`` is a C long.
|
|
95
|
+
"""
|
|
96
|
+
if not n:
|
|
97
|
+
return one(a)
|
|
98
|
+
|
|
99
|
+
cdef unsigned long u = <unsigned long>n
|
|
100
|
+
if n < 0:
|
|
101
|
+
u = -u
|
|
102
|
+
a = invert(a)
|
|
103
|
+
return generic_power_pos(a, u)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
cdef generic_power_pos(a, ulong_or_object n):
|
|
107
|
+
"""
|
|
108
|
+
Return `a^n` where `n > 0`.
|
|
109
|
+
"""
|
|
110
|
+
# Find least significant set bit as starting point
|
|
111
|
+
apow = a
|
|
112
|
+
while not (n & 1):
|
|
113
|
+
sig_check()
|
|
114
|
+
apow *= apow
|
|
115
|
+
n >>= 1
|
|
116
|
+
|
|
117
|
+
# Now multiply together the correct factors a^(2^i)
|
|
118
|
+
res = apow
|
|
119
|
+
n >>= 1
|
|
120
|
+
while n:
|
|
121
|
+
sig_check()
|
|
122
|
+
apow *= apow
|
|
123
|
+
if n & 1:
|
|
124
|
+
res = apow * res
|
|
125
|
+
n >>= 1
|
|
126
|
+
|
|
127
|
+
return res
|
|
Binary file
|