passagemath-objects 10.6.46__cp314-cp314t-macosx_13_0_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of passagemath-objects might be problematic. Click here for more details.
- passagemath_objects/.dylibs/libgmp.10.dylib +0 -0
- passagemath_objects/__init__.py +3 -0
- passagemath_objects-10.6.46.dist-info/METADATA +115 -0
- passagemath_objects-10.6.46.dist-info/RECORD +280 -0
- passagemath_objects-10.6.46.dist-info/WHEEL +6 -0
- passagemath_objects-10.6.46.dist-info/top_level.txt +3 -0
- sage/all__sagemath_objects.py +37 -0
- sage/arith/all__sagemath_objects.py +5 -0
- sage/arith/long.pxd +411 -0
- sage/arith/numerical_approx.cpython-314t-darwin.so +0 -0
- sage/arith/numerical_approx.pxd +35 -0
- sage/arith/numerical_approx.pyx +75 -0
- sage/arith/power.cpython-314t-darwin.so +0 -0
- sage/arith/power.pxd +31 -0
- sage/arith/power.pyx +127 -0
- sage/categories/action.cpython-314t-darwin.so +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 +62 -0
- sage/categories/cartesian_product.py +295 -0
- sage/categories/category.py +3401 -0
- sage/categories/category_cy_helper.cpython-314t-darwin.so +0 -0
- sage/categories/category_cy_helper.pxd +8 -0
- sage/categories/category_cy_helper.pyx +322 -0
- sage/categories/category_singleton.cpython-314t-darwin.so +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 +2876 -0
- sage/categories/covariant_functorial_construction.py +703 -0
- sage/categories/facade_sets.py +228 -0
- sage/categories/functor.cpython-314t-darwin.so +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.cpython-314t-darwin.so +0 -0
- sage/categories/map.pxd +34 -0
- sage/categories/map.pyx +2106 -0
- sage/categories/morphism.cpython-314t-darwin.so +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 +3290 -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 +19 -0
- sage/cpython/_py2_random.py +619 -0
- sage/cpython/all.py +3 -0
- sage/cpython/atexit.cpython-314t-darwin.so +0 -0
- sage/cpython/atexit.pyx +269 -0
- sage/cpython/builtin_types.cpython-314t-darwin.so +0 -0
- sage/cpython/builtin_types.pyx +7 -0
- sage/cpython/cython_metaclass.cpython-314t-darwin.so +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.cpython-314t-darwin.so +0 -0
- sage/cpython/debug.pyx +302 -0
- sage/cpython/dict_del_by_value.cpython-314t-darwin.so +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.cpython-314t-darwin.so +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.cpython-314t-darwin.so +0 -0
- sage/cpython/string.pxd +76 -0
- sage/cpython/string.pyx +34 -0
- sage/cpython/string_impl.h +60 -0
- sage/cpython/type.cpython-314t-darwin.so +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.cpython-314t-darwin.so +0 -0
- sage/groups/group.pxd +14 -0
- sage/groups/group.pyx +322 -0
- sage/groups/old.cpython-314t-darwin.so +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.cpython-314t-darwin.so +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.cpython-314t-darwin.so +0 -0
- sage/misc/c3_controlled.pxd +2 -0
- sage/misc/c3_controlled.pyx +1402 -0
- sage/misc/cachefunc.cpython-314t-darwin.so +0 -0
- sage/misc/cachefunc.pxd +43 -0
- sage/misc/cachefunc.pyx +3781 -0
- sage/misc/call.py +188 -0
- sage/misc/classcall_metaclass.cpython-314t-darwin.so +0 -0
- sage/misc/classcall_metaclass.pxd +14 -0
- sage/misc/classcall_metaclass.pyx +599 -0
- sage/misc/constant_function.cpython-314t-darwin.so +0 -0
- sage/misc/constant_function.pyx +130 -0
- sage/misc/decorators.py +747 -0
- sage/misc/fast_methods.cpython-314t-darwin.so +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.cpython-314t-darwin.so +0 -0
- sage/misc/fpickle.pyx +177 -0
- sage/misc/function_mangling.cpython-314t-darwin.so +0 -0
- sage/misc/function_mangling.pxd +11 -0
- sage/misc/function_mangling.pyx +308 -0
- sage/misc/inherit_comparison.cpython-314t-darwin.so +0 -0
- sage/misc/inherit_comparison.pxd +5 -0
- sage/misc/inherit_comparison.pyx +105 -0
- sage/misc/instancedoc.cpython-314t-darwin.so +0 -0
- sage/misc/instancedoc.pyx +331 -0
- sage/misc/lazy_attribute.cpython-314t-darwin.so +0 -0
- sage/misc/lazy_attribute.pyx +607 -0
- sage/misc/lazy_format.py +135 -0
- sage/misc/lazy_import.cpython-314t-darwin.so +0 -0
- sage/misc/lazy_import.pyx +1299 -0
- sage/misc/lazy_import_cache.py +36 -0
- sage/misc/lazy_list.cpython-314t-darwin.so +0 -0
- sage/misc/lazy_list.pxd +19 -0
- sage/misc/lazy_list.pyx +1187 -0
- sage/misc/lazy_string.cpython-314t-darwin.so +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.cpython-314t-darwin.so +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.cpython-314t-darwin.so +0 -0
- sage/misc/nested_class.pxd +3 -0
- sage/misc/nested_class.pyx +394 -0
- sage/misc/persist.cpython-314t-darwin.so +0 -0
- sage/misc/persist.pyx +1251 -0
- sage/misc/prandom.py +418 -0
- sage/misc/randstate.cpython-314t-darwin.so +0 -0
- sage/misc/randstate.pxd +30 -0
- sage/misc/randstate.pyx +1059 -0
- sage/misc/repr.py +203 -0
- sage/misc/reset.cpython-314t-darwin.so +0 -0
- sage/misc/reset.pyx +196 -0
- sage/misc/sage_ostools.cpython-314t-darwin.so +0 -0
- sage/misc/sage_ostools.pyx +323 -0
- sage/misc/sage_timeit.py +275 -0
- sage/misc/sage_timeit_class.cpython-314t-darwin.so +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.cpython-314t-darwin.so +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.cpython-314t-darwin.so +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.cpython-314t-darwin.so +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.cpython-314t-darwin.so +0 -0
- sage/sets/pythonclass.pxd +9 -0
- sage/sets/pythonclass.pyx +247 -0
- sage/structure/__init__.py +4 -0
- sage/structure/all.py +30 -0
- sage/structure/category_object.cpython-314t-darwin.so +0 -0
- sage/structure/category_object.pxd +28 -0
- sage/structure/category_object.pyx +1087 -0
- sage/structure/coerce.cpython-314t-darwin.so +0 -0
- sage/structure/coerce.pxd +44 -0
- sage/structure/coerce.pyx +2107 -0
- sage/structure/coerce_actions.cpython-314t-darwin.so +0 -0
- sage/structure/coerce_actions.pxd +27 -0
- sage/structure/coerce_actions.pyx +988 -0
- sage/structure/coerce_dict.cpython-314t-darwin.so +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.cpython-314t-darwin.so +0 -0
- sage/structure/coerce_maps.pxd +28 -0
- sage/structure/coerce_maps.pyx +718 -0
- sage/structure/debug_options.cpython-314t-darwin.so +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.cpython-314t-darwin.so +0 -0
- sage/structure/element.pxd +272 -0
- sage/structure/element.pyx +4772 -0
- sage/structure/element_wrapper.cpython-314t-darwin.so +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.cpython-314t-darwin.so +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.cpython-314t-darwin.so +0 -0
- sage/structure/list_clone.pxd +65 -0
- sage/structure/list_clone.pyx +1867 -0
- sage/structure/list_clone_demo.cpython-314t-darwin.so +0 -0
- sage/structure/list_clone_demo.pyx +248 -0
- sage/structure/list_clone_timings.py +179 -0
- sage/structure/list_clone_timings_cy.cpython-314t-darwin.so +0 -0
- sage/structure/list_clone_timings_cy.pyx +86 -0
- sage/structure/mutability.cpython-314t-darwin.so +0 -0
- sage/structure/mutability.pxd +21 -0
- sage/structure/mutability.pyx +348 -0
- sage/structure/nonexact.py +69 -0
- sage/structure/parent.cpython-314t-darwin.so +0 -0
- sage/structure/parent.pxd +112 -0
- sage/structure/parent.pyx +3093 -0
- sage/structure/parent_base.cpython-314t-darwin.so +0 -0
- sage/structure/parent_base.pxd +13 -0
- sage/structure/parent_base.pyx +44 -0
- sage/structure/parent_gens.cpython-314t-darwin.so +0 -0
- sage/structure/parent_gens.pxd +22 -0
- sage/structure/parent_gens.pyx +377 -0
- sage/structure/parent_old.cpython-314t-darwin.so +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.cpython-314t-darwin.so +0 -0
- sage/structure/richcmp.pxd +213 -0
- sage/structure/richcmp.pyx +495 -0
- sage/structure/sage_object.cpython-314t-darwin.so +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/misc/randstate.pyx
ADDED
|
@@ -0,0 +1,1059 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-objects
|
|
2
|
+
# sage.doctest: needs sage.groups sage.libs.gap sage.libs.ntl sage.libs.pari
|
|
3
|
+
r"""
|
|
4
|
+
Random Number States
|
|
5
|
+
|
|
6
|
+
AUTHORS:
|
|
7
|
+
|
|
8
|
+
- Carl Witty (2008-03): new file
|
|
9
|
+
|
|
10
|
+
This module manages all the available pseudo-random number generators
|
|
11
|
+
in Sage. (For the rest of the documentation in this module, we will
|
|
12
|
+
drop the "pseudo".)
|
|
13
|
+
|
|
14
|
+
The goal is to allow algorithms using random numbers to be
|
|
15
|
+
reproducible from one run of Sage to the next, and (to the extent
|
|
16
|
+
possible) from one machine to the next (even across different
|
|
17
|
+
operating systems and architectures).
|
|
18
|
+
|
|
19
|
+
There are two parts to the API. First we will describe the
|
|
20
|
+
command line oriented API, for setting random number generator seeds.
|
|
21
|
+
Then we will describe the library API, for people writing Sage
|
|
22
|
+
library code that uses random numbers.
|
|
23
|
+
|
|
24
|
+
Command line oriented API
|
|
25
|
+
=========================
|
|
26
|
+
|
|
27
|
+
We'll start with the simplest usage: setting fixed random number seeds
|
|
28
|
+
and showing that these lead to reproducible results. ::
|
|
29
|
+
|
|
30
|
+
sage: K.<x> = QQ[]
|
|
31
|
+
sage: G = PermutationGroup([[(1,2,3),(4,5)], [(1,2)]])
|
|
32
|
+
sage: rgp = Gp()
|
|
33
|
+
sage: def gap_randstring(n):
|
|
34
|
+
....: current_randstate().set_seed_gap()
|
|
35
|
+
....: return gap(n).SCRRandomString()
|
|
36
|
+
sage: def rtest():
|
|
37
|
+
....: current_randstate().set_seed_gp(rgp)
|
|
38
|
+
....: return (ZZ.random_element(1000), RR.random_element(),
|
|
39
|
+
....: K.random_element(), G.random_element(),
|
|
40
|
+
....: gap_randstring(5),
|
|
41
|
+
....: rgp.random(), ntl.ZZ_random(99999),
|
|
42
|
+
....: random())
|
|
43
|
+
|
|
44
|
+
The above test shows the results of six different random number
|
|
45
|
+
generators, in three different processes. The random elements from
|
|
46
|
+
``ZZ``, ``RR``, and ``K`` all derive from a single GMP-based random number
|
|
47
|
+
generator. The random element from ``G`` comes from a GAP subprocess.
|
|
48
|
+
The random "string" (5-element binary list) is also from a GAP
|
|
49
|
+
subprocess, using the "classical" GAP random generator.
|
|
50
|
+
The random number from ``rgp`` is from a Pari/gp subprocess. NTL's
|
|
51
|
+
``ZZ_random`` uses a separate NTL random number generator in the main
|
|
52
|
+
Sage process. And ``random()`` is from a Python :class:`random.Random`
|
|
53
|
+
object.
|
|
54
|
+
|
|
55
|
+
Here we see that setting the random number seed really does make the
|
|
56
|
+
results of these random number generators reproducible. ::
|
|
57
|
+
|
|
58
|
+
sage: set_random_seed(0)
|
|
59
|
+
sage: print(rtest())
|
|
60
|
+
(303, -0.266166246380421, 1/2*x^2 - 1/95*x - 1/2, (1,3), [ 1, 0, 0, 1, 1 ], 265625921, 5842, 0.9661911734708414)
|
|
61
|
+
sage: set_random_seed(1)
|
|
62
|
+
sage: print(rtest())
|
|
63
|
+
(978, 0.0557699430711638, -3*x^2 - 1/12, (1,2), [ 0, 0, 1, 1, 0 ], 807447831, 29982, 0.8335077654199736)
|
|
64
|
+
sage: set_random_seed(2)
|
|
65
|
+
sage: print(rtest())
|
|
66
|
+
(207, -0.0141049486533456, 4*x^2 + 1/2, (1,2)(4,5), [ 1, 0, 0, 1, 1 ], 1642898426, 41662, 0.19982565117278328)
|
|
67
|
+
sage: set_random_seed(0)
|
|
68
|
+
sage: print(rtest())
|
|
69
|
+
(303, -0.266166246380421, 1/2*x^2 - 1/95*x - 1/2, (1,3), [ 1, 0, 0, 1, 1 ], 265625921, 5842, 0.9661911734708414)
|
|
70
|
+
sage: set_random_seed(1)
|
|
71
|
+
sage: print(rtest())
|
|
72
|
+
(978, 0.0557699430711638, -3*x^2 - 1/12, (1,2), [ 0, 0, 1, 1, 0 ], 807447831, 29982, 0.8335077654199736)
|
|
73
|
+
sage: set_random_seed(2)
|
|
74
|
+
sage: print(rtest())
|
|
75
|
+
(207, -0.0141049486533456, 4*x^2 + 1/2, (1,2)(4,5), [ 1, 0, 0, 1, 1 ], 1642898426, 41662, 0.19982565117278328)
|
|
76
|
+
|
|
77
|
+
Once we've set the random number seed, we can check what seed was used.
|
|
78
|
+
(This is not the current random number state; it does not change when
|
|
79
|
+
random numbers are generated.) ::
|
|
80
|
+
|
|
81
|
+
sage: set_random_seed(12345)
|
|
82
|
+
sage: initial_seed()
|
|
83
|
+
12345
|
|
84
|
+
sage: print(rtest())
|
|
85
|
+
(720, -0.612180244315804, x^2 - x, (1,2,3), [ 1, 0, 0, 0, 1 ], 1911581957, 27093, 0.9205331599518184)
|
|
86
|
+
sage: initial_seed()
|
|
87
|
+
12345
|
|
88
|
+
|
|
89
|
+
If :func:`set_random_seed` is called with no arguments, then a new
|
|
90
|
+
seed is automatically selected. On operating systems that support it,
|
|
91
|
+
the new seed comes from :func:`os.urandom`; this is intended to be
|
|
92
|
+
a truly random (not pseudo-random), cryptographically secure number.
|
|
93
|
+
(Whether it is actually cryptographically secure depends on operating
|
|
94
|
+
system details that are outside the control of Sage.)
|
|
95
|
+
|
|
96
|
+
If :func:`os.urandom` is not supported, then the new seed comes
|
|
97
|
+
from the current time, which is definitely not cryptographically
|
|
98
|
+
secure. ::
|
|
99
|
+
|
|
100
|
+
sage: set_random_seed()
|
|
101
|
+
sage: r = rtest()
|
|
102
|
+
sage: r # random
|
|
103
|
+
(909, -0.407373370020575, 6/7*x^2 + 1, (1,2,3)(4,5), 985329107, 21461, 0.30047071049504859)
|
|
104
|
+
|
|
105
|
+
After setting a new random number seed with :func:`set_random_seed`,
|
|
106
|
+
we can use :func:`initial_seed` to see what seed was automatically
|
|
107
|
+
selected, and call :func:`set_random_seed` to restart the same
|
|
108
|
+
random number sequence. ::
|
|
109
|
+
|
|
110
|
+
sage: s = initial_seed()
|
|
111
|
+
sage: s # random
|
|
112
|
+
336237747258024892084418842839280045662
|
|
113
|
+
sage: set_random_seed(s)
|
|
114
|
+
sage: r2 = rtest()
|
|
115
|
+
sage: r == r2
|
|
116
|
+
True
|
|
117
|
+
|
|
118
|
+
Whenever Sage starts, :func:`set_random_seed` is called just before
|
|
119
|
+
command line interaction starts; so every Sage run starts with a
|
|
120
|
+
different random number seed. This seed can be recovered with
|
|
121
|
+
:func:`initial_seed()` (as long as the user has not set a different
|
|
122
|
+
seed with :func:`set_random_seed`), so that the results of this run
|
|
123
|
+
can be reproduced in another run; or this automatically selected seed
|
|
124
|
+
can be overridden with, for instance, ``set_random_seed(0)``.
|
|
125
|
+
|
|
126
|
+
We can demonstrate this startup behavior by running a new instance of
|
|
127
|
+
Sage as a subprocess. ::
|
|
128
|
+
|
|
129
|
+
sage: subsage = Sage()
|
|
130
|
+
sage: s = ZZ(subsage('initial_seed()'))
|
|
131
|
+
sage: r = ZZ(subsage('ZZ.random_element(2^200)'))
|
|
132
|
+
sage: s # random
|
|
133
|
+
161165040149656168853863459174502758403
|
|
134
|
+
sage: r # random
|
|
135
|
+
1273828861620427462924151488498075119241254209468761367941442
|
|
136
|
+
sage: set_random_seed(s)
|
|
137
|
+
sage: r == ZZ.random_element(2^200)
|
|
138
|
+
True
|
|
139
|
+
|
|
140
|
+
Note that wrappers of all the random number generation methods from
|
|
141
|
+
Python's :mod:`random` module are available at the Sage command
|
|
142
|
+
line, and these wrappers are properly affected by :meth:`set_random_seed`. ::
|
|
143
|
+
|
|
144
|
+
sage: set_random_seed(0)
|
|
145
|
+
sage: random(), getrandbits(20), uniform(5.0, 10.0), normalvariate(0, 1)
|
|
146
|
+
(0.111439293741037, 539332, 8.26785106378383, 1.3893337539828183)
|
|
147
|
+
sage: set_random_seed(1)
|
|
148
|
+
sage: random(), getrandbits(20), uniform(5.0, 10.0), normalvariate(0, 1)
|
|
149
|
+
(0.8294022851874259, 624859, 5.77894484361117, -0.4201366826308758)
|
|
150
|
+
sage: set_random_seed(0)
|
|
151
|
+
sage: random(), getrandbits(20), uniform(5.0, 10.0), normalvariate(0, 1)
|
|
152
|
+
(0.111439293741037, 539332, 8.26785106378383, 1.3893337539828183)
|
|
153
|
+
|
|
154
|
+
That pretty much covers what you need to know for command-line use of
|
|
155
|
+
this module. Now let's move to what authors of Sage library code
|
|
156
|
+
need to know about the module.
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
Library API
|
|
160
|
+
===========
|
|
161
|
+
|
|
162
|
+
First, we'll cover doctesting. Every docstring now has an implicit
|
|
163
|
+
``set_random_seed(0)`` prepended. Any uses of ``# random`` that
|
|
164
|
+
are based on random numbers under the control of this module should be
|
|
165
|
+
removed, and the reproducible answers inserted instead.
|
|
166
|
+
|
|
167
|
+
This practice has two potential drawbacks. First, it increases the work
|
|
168
|
+
of maintaining doctests. For instance, in a long docstring that has
|
|
169
|
+
many doctests that depend on random numbers, a change near the beginning
|
|
170
|
+
(for instance, adding a new doctest) may invalidate all later doctests
|
|
171
|
+
in the docstring. To reduce this downside, you may add calls to
|
|
172
|
+
``set_random_seed(0)`` throughout the docstring (in the extreme case,
|
|
173
|
+
before every doctest).
|
|
174
|
+
|
|
175
|
+
Second, the ``# random`` in the doctest served as a signal to the
|
|
176
|
+
reader of the docstring that the result was unpredictable and that it
|
|
177
|
+
would not be surprising to get a different result when trying out the
|
|
178
|
+
examples in the doctest. If a doctest specifically refers to
|
|
179
|
+
``ZZ.random_element()`` (for instance), this is presumably enough
|
|
180
|
+
of a signal to render this function of ``# random`` unnecessary.
|
|
181
|
+
However, some doctests are not obviously (from the name) random, but
|
|
182
|
+
do depend on random numbers internally, such as the
|
|
183
|
+
:meth:`composition_series <sage.groups.perm_gps.permgroup.PermutationGroup_generic.composition_series>`
|
|
184
|
+
method of a ``PermutationGroup``. In these cases, the convention is to insert
|
|
185
|
+
the following text at the beginning of the ``EXAMPLES`` section. ::
|
|
186
|
+
|
|
187
|
+
These computations use pseudo-random numbers, so we set the
|
|
188
|
+
seed for reproducible testing.
|
|
189
|
+
|
|
190
|
+
sage: set_random_seed(0)
|
|
191
|
+
|
|
192
|
+
Note that this call to ``set_random_seed(0)`` is redundant, since
|
|
193
|
+
``set_random_seed(0)`` is automatically inserted at the beginning
|
|
194
|
+
of every docstring. However, it makes the example reproducible for somebody
|
|
195
|
+
who just types the lines from the doctest and doesn't know about the
|
|
196
|
+
automatic ``set_random_seed(0)``.
|
|
197
|
+
|
|
198
|
+
Next, let's cover setting the random seed from library code. The
|
|
199
|
+
first rule is that library code should never call
|
|
200
|
+
:func:`set_random_seed`. This function is only for command-line
|
|
201
|
+
use. Instead, if the library code wants to use a different random
|
|
202
|
+
seed, it should use ``with seed(s):``. This will use the new seed
|
|
203
|
+
within the scope of the ``with`` statement, but will revert to the previous
|
|
204
|
+
seed once the ``with`` statement is completed. (Or the library can use
|
|
205
|
+
``with seed():`` to get a seed automatically selected using
|
|
206
|
+
:func:`os.urandom()` or the current time, in the same way as described for
|
|
207
|
+
:func:`set_random_seed` above.)
|
|
208
|
+
|
|
209
|
+
Ideally, using ``with seed(s):`` should not affect the outer random
|
|
210
|
+
number sequence at all; we will call this property "isolation." We
|
|
211
|
+
achieve isolation for most, but not all, of the random number generators
|
|
212
|
+
in Sage (we fail for generators, such as NTL, that do not provide an API
|
|
213
|
+
to retrieve the current random number state).
|
|
214
|
+
|
|
215
|
+
We'll demonstrate isolation. First, we show the sequence of random numbers
|
|
216
|
+
that you get without intervening ``with seed``. ::
|
|
217
|
+
|
|
218
|
+
sage: set_random_seed(0)
|
|
219
|
+
sage: r1 = rtest(); print(r1)
|
|
220
|
+
(303, -0.266166246380421, 1/2*x^2 - 1/95*x - 1/2, (1,3), [ 1, 0, 0, 1, 1 ], 265625921, 5842, 0.9661911734708414)
|
|
221
|
+
sage: r2 = rtest(); print(r2)
|
|
222
|
+
(105, 0.642309615982449, -x^2 - x - 6, (1,3)(4,5), [ 1, 0, 0, 0, 1 ], 53231108, 77132, 0.001767155077382232)
|
|
223
|
+
|
|
224
|
+
We get slightly different results with an intervening ``with seed``. ::
|
|
225
|
+
|
|
226
|
+
sage: set_random_seed(0)
|
|
227
|
+
sage: r1 == rtest()
|
|
228
|
+
True
|
|
229
|
+
sage: with seed(1): rtest()
|
|
230
|
+
(978, 0.0557699430711638, -3*x^2 - 1/12, (1,2), [ 0, 0, 1, 1, 0 ], 807447831, 29982, 0.8335077654199736)
|
|
231
|
+
sage: r2m = rtest(); r2m
|
|
232
|
+
(105, 0.642309615982449, -x^2 - x - 6, (1,3)(4,5), [ 1, 0, 0, 0, 1 ], 53231108, 40267, 0.001767155077382232)
|
|
233
|
+
sage: r2m == r2
|
|
234
|
+
False
|
|
235
|
+
|
|
236
|
+
We can see that ``r2`` and ``r2m`` are the same except for the
|
|
237
|
+
call to :func:`ntl.ZZ_random`, which produces different results
|
|
238
|
+
with and without the ``with seed``.
|
|
239
|
+
|
|
240
|
+
However, we do still get a partial form of isolation, even in this
|
|
241
|
+
case, as we see in this example::
|
|
242
|
+
|
|
243
|
+
sage: set_random_seed(0)
|
|
244
|
+
sage: r1 == rtest()
|
|
245
|
+
True
|
|
246
|
+
sage: with seed(1):
|
|
247
|
+
....: print(rtest())
|
|
248
|
+
....: print(rtest())
|
|
249
|
+
(978, 0.0557699430711638, -3*x^2 - 1/12, (1,2), [ 0, 0, 1, 1, 0 ], 807447831, 29982, 0.8335077654199736)
|
|
250
|
+
(138, -0.0404945051288503, 2*x - 24, (1,2,3), [ 1, 1, 0, 1, 1 ], 1010791326, 91360, 0.0033332230808060803)
|
|
251
|
+
sage: r2m == rtest()
|
|
252
|
+
True
|
|
253
|
+
|
|
254
|
+
The NTL results after the ``with seed`` don't depend on how many
|
|
255
|
+
NTL random numbers were generated inside the ``with seed``.
|
|
256
|
+
|
|
257
|
+
sage: set_random_seed(0)
|
|
258
|
+
sage: r1 == rtest()
|
|
259
|
+
True
|
|
260
|
+
sage: with seed(1):
|
|
261
|
+
....: rtest()
|
|
262
|
+
(978, 0.0557699430711638, -3*x^2 - 1/12, (1,2), [ 0, 0, 1, 1, 0 ], 807447831, 29982, 0.8335077654199736)
|
|
263
|
+
sage: r2m == rtest()
|
|
264
|
+
True
|
|
265
|
+
|
|
266
|
+
(In general, the above code is not exactly equivalent to the ``with``
|
|
267
|
+
statement, because if an exception happens in the body, the real
|
|
268
|
+
``with`` statement will pass the exception information as parameters to
|
|
269
|
+
the ``__exit__`` method. However, our ``__exit__`` method
|
|
270
|
+
ignores the exception information anyway, so the above is equivalent in
|
|
271
|
+
our case.)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
Generating random numbers in library code
|
|
275
|
+
=========================================
|
|
276
|
+
|
|
277
|
+
Now we come to the last part of the documentation: actually generating
|
|
278
|
+
random numbers in library code. First, the easy case. If you generate
|
|
279
|
+
random numbers only by calling other Sage library code (such as
|
|
280
|
+
``random_element`` methods on parents), you don't need to do
|
|
281
|
+
anything special; the other code presumably already interacts with
|
|
282
|
+
this module correctly.
|
|
283
|
+
|
|
284
|
+
Otherwise, it depends on what random number generator you want to use.
|
|
285
|
+
|
|
286
|
+
- ``gmp_randstate_t`` -- if you want to use some random number
|
|
287
|
+
generator that takes a ``gmp_randstate_t`` (like ``mpz_urandomm`` or
|
|
288
|
+
``mpfr_urandomb``), then use code like the following::
|
|
289
|
+
|
|
290
|
+
from sage.misc.randstate cimport randstate, current_randstate
|
|
291
|
+
...
|
|
292
|
+
|
|
293
|
+
cdef randstate rstate = current_randstate()
|
|
294
|
+
|
|
295
|
+
Then a ``gmp_randstate_t`` is available as ``rstate.gmp_state``.
|
|
296
|
+
|
|
297
|
+
Fetch the current :class:`randstate` with ``current_randstate()`` in
|
|
298
|
+
every function that wants to use it; don't cache it globally or in a
|
|
299
|
+
class. (Such caching would break ``set_random_seed``).
|
|
300
|
+
|
|
301
|
+
- ``Python`` -- if you want to use the random number generators from
|
|
302
|
+
the :mod:`random` module, you have two choices. The slightly
|
|
303
|
+
easier choice is to import functions from
|
|
304
|
+
:mod:`sage.misc.prandom`; for instance, you can simply replace
|
|
305
|
+
``from random import randrange`` with
|
|
306
|
+
``from sage.misc.prandom import randrange``. However, this is slightly less
|
|
307
|
+
efficient, because the wrappers in :mod:`sage.misc.prandom` look up the
|
|
308
|
+
current :class:`randstate` on each call. If you're generating many
|
|
309
|
+
random numbers in a row, it's faster to instead do ::
|
|
310
|
+
|
|
311
|
+
from sage.misc.randstate import current_randstate ...
|
|
312
|
+
|
|
313
|
+
randrange = current_randstate().python_random().randrange
|
|
314
|
+
|
|
315
|
+
Fetch the current :class:`randstate` with
|
|
316
|
+
:func:`current_randstate()` in every function that wants to use it;
|
|
317
|
+
don't cache the :class:`randstate`, the :class:`Random` object
|
|
318
|
+
returned by ``python_random``, or the bound methods on that
|
|
319
|
+
:class:`Random` object globally or in a class. (Such caching would
|
|
320
|
+
break ``set_random_seed``).
|
|
321
|
+
|
|
322
|
+
- ``GAP`` -- if you are calling code in GAP that uses random numbers,
|
|
323
|
+
call ``set_seed_gap`` at the beginning of your function, like this::
|
|
324
|
+
|
|
325
|
+
from sage.misc.randstate import current_randstate
|
|
326
|
+
...
|
|
327
|
+
|
|
328
|
+
current_randstate().set_seed_gap()
|
|
329
|
+
|
|
330
|
+
Fetch the current :class:`randstate` with
|
|
331
|
+
:func:`current_randstate()` in every function that wants to use it;
|
|
332
|
+
don't cache it globally or in a class. (Such caching would break
|
|
333
|
+
``set_random_seed``).
|
|
334
|
+
|
|
335
|
+
- ``Pari`` -- if you are calling code in the Pari library that uses
|
|
336
|
+
random numbers, call ``set_seed_pari`` at the beginning of your
|
|
337
|
+
function, like this::
|
|
338
|
+
|
|
339
|
+
from sage.misc.randstate import current_randstate
|
|
340
|
+
...
|
|
341
|
+
|
|
342
|
+
current_randstate().set_seed_pari()
|
|
343
|
+
|
|
344
|
+
Fetch the current :class:`randstate` with
|
|
345
|
+
:func:`current_randstate()` in every function that wants to use it;
|
|
346
|
+
don't cache it globally or in a class. (Such caching would break
|
|
347
|
+
``set_random_seed``).
|
|
348
|
+
|
|
349
|
+
- ``Pari/gp`` -- if you are calling code in a Pari/gp subprocess that
|
|
350
|
+
uses random numbers, call ``set_seed_gp`` at the beginning of your
|
|
351
|
+
function, like this::
|
|
352
|
+
|
|
353
|
+
from sage.misc.randstate import current_randstate
|
|
354
|
+
...
|
|
355
|
+
|
|
356
|
+
current_randstate().set_seed_gp()
|
|
357
|
+
|
|
358
|
+
This will set the seed in the gp process in ``sage.interfaces.gp.gp``.
|
|
359
|
+
If you have a different gp process, say in the variable ``my_gp``, then
|
|
360
|
+
call ``set_seed_gp(my_gp)`` instead.
|
|
361
|
+
|
|
362
|
+
Fetch the current :class:`randstate` with :func:`current_randstate()` in
|
|
363
|
+
every function that wants to use it; don't cache it globally or
|
|
364
|
+
in a class. (Such caching would break ``set_random_seed``).
|
|
365
|
+
|
|
366
|
+
- ``NTL`` -- if you are calling code in the NTL library that uses
|
|
367
|
+
random numbers, call ``set_seed_ntl`` at the beginning of your
|
|
368
|
+
function, like this::
|
|
369
|
+
|
|
370
|
+
from sage.misc.randstate import current_randstate ...
|
|
371
|
+
|
|
372
|
+
current_randstate().set_seed_ntl(False)
|
|
373
|
+
|
|
374
|
+
Fetch the current :class:`randstate` with
|
|
375
|
+
:func:`current_randstate()` in every function that wants to use it;
|
|
376
|
+
don't cache it globally or in a class. (Such caching would break
|
|
377
|
+
``set_random_seed``).
|
|
378
|
+
|
|
379
|
+
- ``libc`` -- if you are writing code that calls the libc function
|
|
380
|
+
:func:`random()`: don't! The :func:`random()` function does not
|
|
381
|
+
give reproducible results across different operating systems, so we
|
|
382
|
+
can't make portable doctests for the results. Instead, do::
|
|
383
|
+
|
|
384
|
+
from sage.misc.randstate cimport random
|
|
385
|
+
|
|
386
|
+
The :func:`random` function in :mod:`sage.misc.randstate` gives a
|
|
387
|
+
31-bit random number, but it uses the ``gmp_randstate_t`` in the
|
|
388
|
+
current :class:`randstate`, so it is portable. (This range was
|
|
389
|
+
chosen for two reasons: it matches the range of random() on 32-bit
|
|
390
|
+
and 64-bit Linux, although not Solaris; and it's the largest range
|
|
391
|
+
of nonnegative numbers that fits in a 32-bit signed integer.)
|
|
392
|
+
|
|
393
|
+
However, you may still need to set the libc random number state; for
|
|
394
|
+
instance, if you are wrapping a library that uses :func:`random()`
|
|
395
|
+
internally and you don't want to change the library. In that case,
|
|
396
|
+
call ``set_seed_libc`` at the beginning of your function, like this::
|
|
397
|
+
|
|
398
|
+
from sage.misc.randstate import current_randstate
|
|
399
|
+
...
|
|
400
|
+
|
|
401
|
+
current_randstate().set_seed_libc(False)
|
|
402
|
+
|
|
403
|
+
Fetch the current :class:`randstate` with
|
|
404
|
+
:func:`current_randstate()` in every function that wants to use it;
|
|
405
|
+
don't cache it globally or in a class. (Such caching would break
|
|
406
|
+
``set_random_seed``).
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
Classes and methods
|
|
410
|
+
===================
|
|
411
|
+
"""
|
|
412
|
+
|
|
413
|
+
cdef extern from "stdlib.h":
|
|
414
|
+
# Provide equivalent functions for Windows.
|
|
415
|
+
"""
|
|
416
|
+
#ifdef _WIN32
|
|
417
|
+
#include <stdlib.h>
|
|
418
|
+
static inline void srandom(unsigned int seed)
|
|
419
|
+
{
|
|
420
|
+
srand(seed);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
static inline long int random(void)
|
|
424
|
+
{
|
|
425
|
+
return rand();
|
|
426
|
+
}
|
|
427
|
+
#endif
|
|
428
|
+
"""
|
|
429
|
+
long c_libc_random "random"()
|
|
430
|
+
void c_libc_srandom "srandom"(unsigned int seed)
|
|
431
|
+
|
|
432
|
+
from sage.libs.gmp.all cimport *
|
|
433
|
+
|
|
434
|
+
import binascii
|
|
435
|
+
import os
|
|
436
|
+
import time
|
|
437
|
+
import weakref
|
|
438
|
+
import random as _random
|
|
439
|
+
|
|
440
|
+
use_urandom = False
|
|
441
|
+
# Check whether os.urandom() works.
|
|
442
|
+
try:
|
|
443
|
+
os.urandom(1)
|
|
444
|
+
use_urandom = True
|
|
445
|
+
except NotImplementedError:
|
|
446
|
+
pass
|
|
447
|
+
|
|
448
|
+
# Holds the current randstate object.
|
|
449
|
+
cdef randstate _current_randstate
|
|
450
|
+
|
|
451
|
+
# For each kind of random number generator, keep track of which
|
|
452
|
+
# randstate object was the most recent one to seed it. (Before
|
|
453
|
+
# the generator has been seeded, these will be None.)
|
|
454
|
+
cdef randstate _libc_seed_randstate
|
|
455
|
+
cdef randstate _ntl_seed_randstate
|
|
456
|
+
cdef randstate _gap_seed_randstate
|
|
457
|
+
cdef randstate _pari_seed_randstate
|
|
458
|
+
# For each gp subprocess that has been seeded, keep track of which
|
|
459
|
+
# randstate object was the most recent one to seed it.
|
|
460
|
+
_gp_seed_randstates = weakref.WeakKeyDictionary()
|
|
461
|
+
|
|
462
|
+
cpdef randstate current_randstate():
|
|
463
|
+
r"""
|
|
464
|
+
Return the current random number state.
|
|
465
|
+
|
|
466
|
+
EXAMPLES::
|
|
467
|
+
|
|
468
|
+
sage: set_random_seed(0)
|
|
469
|
+
sage: current_randstate()
|
|
470
|
+
<sage.misc.randstate.randstate object at 0x...>
|
|
471
|
+
sage: current_randstate().python_random().random()
|
|
472
|
+
0.111439293741037
|
|
473
|
+
"""
|
|
474
|
+
return _current_randstate
|
|
475
|
+
|
|
476
|
+
# Keep track of the stack of randstates involved in "with seed(s):".
|
|
477
|
+
randstate_stack = []
|
|
478
|
+
|
|
479
|
+
# Default class to use for randstate.python_random
|
|
480
|
+
DEFAULT_PYTHON_RANDOM = _random.Random
|
|
481
|
+
|
|
482
|
+
# The following components of Sage use random numbers that I have not
|
|
483
|
+
# figured out how to seed: fpLLL, mwrank, mpfi
|
|
484
|
+
# (there are probably others; these are the ones I noticed while trying
|
|
485
|
+
# to remove "# random" from doctests)
|
|
486
|
+
|
|
487
|
+
cdef class randstate:
|
|
488
|
+
r"""
|
|
489
|
+
The :class:`randstate` class. This class keeps track of random number
|
|
490
|
+
states and seeds. Type ``sage.misc.randstate?`` for much more
|
|
491
|
+
information on random numbers in Sage.
|
|
492
|
+
"""
|
|
493
|
+
def __cinit__(self, *args, **opts):
|
|
494
|
+
"""
|
|
495
|
+
Initialise c-data for randstate, in a fail-safe way.
|
|
496
|
+
|
|
497
|
+
TESTS:
|
|
498
|
+
|
|
499
|
+
The following used to segfault (see :issue:`10113`). Now,
|
|
500
|
+
there is a proper type error::
|
|
501
|
+
|
|
502
|
+
sage: seed(1,2) # indirect doctest
|
|
503
|
+
Traceback (most recent call last):
|
|
504
|
+
...
|
|
505
|
+
TypeError: ...__init__() takes at most 1 positional argument (2 given)
|
|
506
|
+
|
|
507
|
+
AUTHOR:
|
|
508
|
+
|
|
509
|
+
- Simon King <simon.king@uni-jena.de>
|
|
510
|
+
"""
|
|
511
|
+
gmp_randinit_default(self.gmp_state)
|
|
512
|
+
|
|
513
|
+
def __init__(self, seed=None):
|
|
514
|
+
r"""
|
|
515
|
+
Initialize a new :class:`randstate` object with the given seed
|
|
516
|
+
(which must be coercible to a Python long).
|
|
517
|
+
|
|
518
|
+
If no seed is given, then a seed is automatically selected
|
|
519
|
+
using :func:`os.urandom` if it is available, or the current
|
|
520
|
+
time otherwise.
|
|
521
|
+
|
|
522
|
+
EXAMPLES::
|
|
523
|
+
|
|
524
|
+
sage: from sage.misc.randstate import randstate
|
|
525
|
+
sage: r = randstate(54321); r
|
|
526
|
+
<sage.misc.randstate.randstate object at 0x...>
|
|
527
|
+
sage: r.seed()
|
|
528
|
+
54321
|
|
529
|
+
sage: r = randstate(); r
|
|
530
|
+
<sage.misc.randstate.randstate object at 0x...>
|
|
531
|
+
sage: r.seed() # random
|
|
532
|
+
305866218880103397618377824640007711767
|
|
533
|
+
|
|
534
|
+
Note that creating a :class:`randstate` with a seed of 0
|
|
535
|
+
is vastly faster than any other seed (over a thousand times
|
|
536
|
+
faster in my test). ::
|
|
537
|
+
|
|
538
|
+
sage: timeit('randstate(0)') # random
|
|
539
|
+
625 loops, best of 3: 1.38 us per loop
|
|
540
|
+
sage: timeit('randstate(1)') # random
|
|
541
|
+
125 loops, best of 3: 3.59 ms per loop
|
|
542
|
+
"""
|
|
543
|
+
cdef mpz_t mpz_seed
|
|
544
|
+
|
|
545
|
+
if seed is None:
|
|
546
|
+
if use_urandom:
|
|
547
|
+
seed = int(binascii.hexlify(os.urandom(16)), 16)
|
|
548
|
+
else:
|
|
549
|
+
seed = int(time.time() * 256)
|
|
550
|
+
else:
|
|
551
|
+
seed = int(seed)
|
|
552
|
+
|
|
553
|
+
# If seed==0, leave it at the default seed used by
|
|
554
|
+
# gmp_randinit_default()
|
|
555
|
+
if seed:
|
|
556
|
+
mpz_init(mpz_seed)
|
|
557
|
+
mpz_set_pylong(mpz_seed, seed)
|
|
558
|
+
gmp_randseed(self.gmp_state, mpz_seed)
|
|
559
|
+
mpz_clear(mpz_seed)
|
|
560
|
+
|
|
561
|
+
self._seed = seed
|
|
562
|
+
|
|
563
|
+
def seed(self):
|
|
564
|
+
r"""
|
|
565
|
+
Return the initial seed of a :class:`randstate` object. (This is not
|
|
566
|
+
the current state; it does not change when you get random
|
|
567
|
+
numbers.)
|
|
568
|
+
|
|
569
|
+
EXAMPLES::
|
|
570
|
+
|
|
571
|
+
sage: set_random_seed(0)
|
|
572
|
+
sage: from sage.misc.randstate import randstate
|
|
573
|
+
sage: r = randstate(314159)
|
|
574
|
+
sage: r.seed()
|
|
575
|
+
314159
|
|
576
|
+
sage: r.python_random().random()
|
|
577
|
+
0.111439293741037
|
|
578
|
+
sage: r.seed()
|
|
579
|
+
314159
|
|
580
|
+
"""
|
|
581
|
+
return self._seed
|
|
582
|
+
|
|
583
|
+
def python_random(self, cls=None, seed=None):
|
|
584
|
+
r"""
|
|
585
|
+
Return a :class:`random.Random` object. The first time it is
|
|
586
|
+
called on a given :class:`randstate`, a new :class:`random.Random`
|
|
587
|
+
is created (seeded from the *current* :class:`randstate`);
|
|
588
|
+
the same object is returned on subsequent calls.
|
|
589
|
+
|
|
590
|
+
It is expected that ``python_random`` will only be
|
|
591
|
+
called on the current :class:`randstate`.
|
|
592
|
+
|
|
593
|
+
INPUT:
|
|
594
|
+
|
|
595
|
+
- ``cls`` -- (optional) a class with the same interface as
|
|
596
|
+
:class:`random.Random` (e.g. a subclass thereof) to use as the
|
|
597
|
+
Python RNG interface. Otherwise the standard :class:`random.Random`
|
|
598
|
+
is used.
|
|
599
|
+
|
|
600
|
+
- ``seed`` -- (optional) an integer to seed the :class:`random.Random`
|
|
601
|
+
instance with upon creation; if not specified it is seeded using
|
|
602
|
+
``ZZ.random_element(1 << 128)``.
|
|
603
|
+
|
|
604
|
+
EXAMPLES::
|
|
605
|
+
|
|
606
|
+
sage: set_random_seed(5)
|
|
607
|
+
sage: rnd = current_randstate().python_random()
|
|
608
|
+
sage: rnd.random()
|
|
609
|
+
0.013558022446944151
|
|
610
|
+
sage: rnd.randrange(1000)
|
|
611
|
+
544
|
|
612
|
+
"""
|
|
613
|
+
|
|
614
|
+
if cls is None:
|
|
615
|
+
cls = DEFAULT_PYTHON_RANDOM
|
|
616
|
+
|
|
617
|
+
if type(self._python_random) is cls:
|
|
618
|
+
return self._python_random
|
|
619
|
+
|
|
620
|
+
from sage.rings.integer_ring import ZZ
|
|
621
|
+
rand = cls()
|
|
622
|
+
if seed is None:
|
|
623
|
+
rand.seed(int(ZZ.random_element(1<<128)))
|
|
624
|
+
else:
|
|
625
|
+
rand.seed(int(seed))
|
|
626
|
+
self._python_random = rand
|
|
627
|
+
return rand
|
|
628
|
+
|
|
629
|
+
cpdef ZZ_seed(self):
|
|
630
|
+
r"""
|
|
631
|
+
When called on the current :class:`randstate`, returns a 128-bit
|
|
632
|
+
:mod:`Integer <sage.rings.integer_ring>` suitable for seeding another
|
|
633
|
+
random number generator.
|
|
634
|
+
|
|
635
|
+
EXAMPLES::
|
|
636
|
+
|
|
637
|
+
sage: set_random_seed(1414)
|
|
638
|
+
sage: current_randstate().ZZ_seed()
|
|
639
|
+
48314508034782595865062786044921182484
|
|
640
|
+
"""
|
|
641
|
+
from sage.rings.integer_ring import ZZ
|
|
642
|
+
return ZZ.random_element(1<<128)
|
|
643
|
+
|
|
644
|
+
cpdef long_seed(self):
|
|
645
|
+
r"""
|
|
646
|
+
When called on the current :class:`randstate`, returns a 128-bit
|
|
647
|
+
Python long suitable for seeding another random number generator.
|
|
648
|
+
|
|
649
|
+
EXAMPLES::
|
|
650
|
+
|
|
651
|
+
sage: set_random_seed(1618)
|
|
652
|
+
sage: current_randstate().long_seed()
|
|
653
|
+
256056279774514099508607350947089272595
|
|
654
|
+
"""
|
|
655
|
+
from sage.rings.integer_ring import ZZ
|
|
656
|
+
return int(ZZ.random_element(1<<128))
|
|
657
|
+
|
|
658
|
+
cpdef set_seed_libc(self, bint force):
|
|
659
|
+
r"""
|
|
660
|
+
Check to see if ``self`` was the most recent :class:`randstate`
|
|
661
|
+
to seed the libc random number generator. If not, seeds the
|
|
662
|
+
libc random number generator. (Do not use the libc random
|
|
663
|
+
number generator if you have a choice; its randomness is poor,
|
|
664
|
+
and the random number sequences it produces are not portable
|
|
665
|
+
across operating systems.)
|
|
666
|
+
|
|
667
|
+
If the argument ``force`` is ``True``, seeds the generator
|
|
668
|
+
unconditionally.
|
|
669
|
+
|
|
670
|
+
EXAMPLES::
|
|
671
|
+
|
|
672
|
+
sage: from sage.misc.randstate import _doctest_libc_random
|
|
673
|
+
sage: set_random_seed(0xBAD)
|
|
674
|
+
sage: current_randstate().set_seed_libc(False)
|
|
675
|
+
sage: _doctest_libc_random() # random
|
|
676
|
+
1070075918
|
|
677
|
+
"""
|
|
678
|
+
global _libc_seed_randstate
|
|
679
|
+
if force or _libc_seed_randstate is not self:
|
|
680
|
+
c_libc_srandom(gmp_urandomb_ui(self.gmp_state, sizeof(int)*8))
|
|
681
|
+
_libc_seed_randstate = self
|
|
682
|
+
|
|
683
|
+
cpdef set_seed_ntl(self, bint force):
|
|
684
|
+
r"""
|
|
685
|
+
Check to see if ``self`` was the most recent :class:`randstate`
|
|
686
|
+
to seed the NTL random number generator. If not, seeds
|
|
687
|
+
the generator. If the argument ``force`` is ``True``,
|
|
688
|
+
seeds the generator unconditionally.
|
|
689
|
+
|
|
690
|
+
EXAMPLES::
|
|
691
|
+
|
|
692
|
+
sage: set_random_seed(2008)
|
|
693
|
+
|
|
694
|
+
This call is actually redundant; :func:`ntl.ZZ_random` will
|
|
695
|
+
seed the generator itself. However, we put the call in
|
|
696
|
+
to make the coverage tester happy. ::
|
|
697
|
+
|
|
698
|
+
sage: current_randstate().set_seed_ntl(False)
|
|
699
|
+
sage: ntl.ZZ_random(10^40)
|
|
700
|
+
1495283511775355459459209288047895196007
|
|
701
|
+
"""
|
|
702
|
+
global _ntl_seed_randstate
|
|
703
|
+
if force or _ntl_seed_randstate is not self:
|
|
704
|
+
import sage.libs.ntl.ntl_ZZ as ntl_ZZ
|
|
705
|
+
from sage.rings.integer_ring import ZZ
|
|
706
|
+
ntl_ZZ.ntl_setSeed(ZZ.random_element(1<<128))
|
|
707
|
+
_ntl_seed_randstate = self
|
|
708
|
+
|
|
709
|
+
def set_seed_gap(self):
|
|
710
|
+
r"""
|
|
711
|
+
Check to see if ``self`` was the most recent :class:`randstate`
|
|
712
|
+
to seed the GAP random number generator. If not, seeds
|
|
713
|
+
the generator.
|
|
714
|
+
|
|
715
|
+
EXAMPLES::
|
|
716
|
+
|
|
717
|
+
sage: set_random_seed(99900000999)
|
|
718
|
+
sage: current_randstate().set_seed_gap()
|
|
719
|
+
sage: gap.Random(1, 10^50)
|
|
720
|
+
1496738263332555434474532297768680634540939580077
|
|
721
|
+
sage: gap(35).SCRRandomString()
|
|
722
|
+
[ 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1,
|
|
723
|
+
1, 0, 0, 1, 1, 1, 1, 1, 0, 1 ]
|
|
724
|
+
"""
|
|
725
|
+
global _gap_seed_randstate
|
|
726
|
+
if _gap_seed_randstate is not self:
|
|
727
|
+
from sage.interfaces.gap import gap
|
|
728
|
+
|
|
729
|
+
if self._gap_saved_seed is not None:
|
|
730
|
+
mersenne_seed, classic_seed = self._gap_saved_seed
|
|
731
|
+
else:
|
|
732
|
+
from sage.rings.integer_ring import ZZ
|
|
733
|
+
seed = ZZ.random_element(1<<128)
|
|
734
|
+
classic_seed = seed
|
|
735
|
+
mersenne_seed = seed
|
|
736
|
+
|
|
737
|
+
prev_mersenne_seed = gap.Reset(gap.GlobalMersenneTwister, mersenne_seed)
|
|
738
|
+
prev_classic_seed = gap.Reset(gap.GlobalRandomSource, classic_seed)
|
|
739
|
+
|
|
740
|
+
if _gap_seed_randstate is not None:
|
|
741
|
+
_gap_seed_randstate._gap_saved_seed = \
|
|
742
|
+
prev_mersenne_seed, prev_classic_seed
|
|
743
|
+
|
|
744
|
+
_gap_seed_randstate = self
|
|
745
|
+
|
|
746
|
+
def set_seed_gp(self, gp=None):
|
|
747
|
+
r"""
|
|
748
|
+
Check to see if ``self`` was the most recent :class:`randstate`
|
|
749
|
+
to seed the random number generator in the given instance
|
|
750
|
+
of gp. (If no instance is given, uses the one in
|
|
751
|
+
:class:`gp <sage.interfaces.gp.Gp>`.) If not, seeds the generator.
|
|
752
|
+
|
|
753
|
+
EXAMPLES::
|
|
754
|
+
|
|
755
|
+
sage: set_random_seed(987654321)
|
|
756
|
+
sage: current_randstate().set_seed_gp()
|
|
757
|
+
sage: gp.random()
|
|
758
|
+
23289294
|
|
759
|
+
"""
|
|
760
|
+
if gp is None:
|
|
761
|
+
import sage.interfaces.gp
|
|
762
|
+
gp = sage.interfaces.gp.gp
|
|
763
|
+
|
|
764
|
+
cdef randstate prev
|
|
765
|
+
|
|
766
|
+
try:
|
|
767
|
+
prev = _gp_seed_randstates[gp]
|
|
768
|
+
except KeyError:
|
|
769
|
+
prev = None
|
|
770
|
+
|
|
771
|
+
if prev is not self:
|
|
772
|
+
if self._gp_saved_seeds is not None and gp in self._gp_saved_seeds:
|
|
773
|
+
seed = self._gp_saved_seeds[gp]
|
|
774
|
+
else:
|
|
775
|
+
seed = self.c_random()
|
|
776
|
+
|
|
777
|
+
prev_seed = gp.getrand()
|
|
778
|
+
gp.setrand(seed)
|
|
779
|
+
|
|
780
|
+
if prev is not None:
|
|
781
|
+
if prev._gp_saved_seeds is None:
|
|
782
|
+
prev._gp_saved_seeds = weakref.WeakKeyDictionary()
|
|
783
|
+
prev._gp_saved_seeds[gp] = prev_seed
|
|
784
|
+
|
|
785
|
+
_gp_seed_randstates[gp] = self
|
|
786
|
+
|
|
787
|
+
def set_seed_pari(self):
|
|
788
|
+
r"""
|
|
789
|
+
Check to see if ``self`` was the most recent :class:`randstate` to
|
|
790
|
+
seed the Pari random number generator. If not, seeds the
|
|
791
|
+
generator.
|
|
792
|
+
|
|
793
|
+
.. NOTE::
|
|
794
|
+
|
|
795
|
+
Since pari 2.4.3, pari's random number generator has
|
|
796
|
+
changed a lot. the seed output by getrand() is now a
|
|
797
|
+
vector of integers.
|
|
798
|
+
|
|
799
|
+
EXAMPLES::
|
|
800
|
+
|
|
801
|
+
sage: set_random_seed(5551212)
|
|
802
|
+
sage: current_randstate().set_seed_pari()
|
|
803
|
+
sage: pari.getrand().type()
|
|
804
|
+
't_INT'
|
|
805
|
+
"""
|
|
806
|
+
global _pari_seed_randstate
|
|
807
|
+
if _pari_seed_randstate is not self:
|
|
808
|
+
from sage.libs.pari import pari
|
|
809
|
+
|
|
810
|
+
if self._pari_saved_seed is not None:
|
|
811
|
+
seed = self._pari_saved_seed
|
|
812
|
+
else:
|
|
813
|
+
seed = self.c_random()
|
|
814
|
+
|
|
815
|
+
prev_seed = pari.getrand()
|
|
816
|
+
pari.setrand(seed)
|
|
817
|
+
|
|
818
|
+
if _pari_seed_randstate is not None:
|
|
819
|
+
_pari_seed_randstate._pari_saved_seed = prev_seed
|
|
820
|
+
|
|
821
|
+
_pari_seed_randstate = self
|
|
822
|
+
|
|
823
|
+
cpdef int c_random(self) noexcept:
|
|
824
|
+
r"""
|
|
825
|
+
Return a 31-bit random number. Intended for internal
|
|
826
|
+
use only; instead of calling ``current_randstate().c_random()``,
|
|
827
|
+
it is equivalent (but probably faster) to call the
|
|
828
|
+
:meth:`random <sage.misc.randstate.random>` method of this
|
|
829
|
+
:class:`randstate` class.
|
|
830
|
+
|
|
831
|
+
EXAMPLES::
|
|
832
|
+
|
|
833
|
+
sage: set_random_seed(1207)
|
|
834
|
+
sage: current_randstate().c_random()
|
|
835
|
+
2008037228
|
|
836
|
+
|
|
837
|
+
We verify the equivalence mentioned above. ::
|
|
838
|
+
|
|
839
|
+
sage: from sage.misc.randstate import random
|
|
840
|
+
sage: set_random_seed(1207)
|
|
841
|
+
sage: random()
|
|
842
|
+
2008037228
|
|
843
|
+
"""
|
|
844
|
+
return gmp_urandomb_ui(self.gmp_state, 31)
|
|
845
|
+
|
|
846
|
+
cpdef double c_rand_double(self) noexcept:
|
|
847
|
+
r"""
|
|
848
|
+
Return a random floating-point number between 0 and 1.
|
|
849
|
+
|
|
850
|
+
EXAMPLES::
|
|
851
|
+
|
|
852
|
+
sage: set_random_seed(2718281828)
|
|
853
|
+
sage: current_randstate().c_rand_double()
|
|
854
|
+
0.22437207488974298
|
|
855
|
+
"""
|
|
856
|
+
cdef double a = gmp_urandomb_ui(self.gmp_state, 25) * (1.0 / 33554432.0) # divide by 2^25
|
|
857
|
+
cdef double b = gmp_urandomb_ui(self.gmp_state, 28) * (1.0 / 9007199254740992.0) # divide by 2^53
|
|
858
|
+
return a+b
|
|
859
|
+
|
|
860
|
+
def __dealloc__(self):
|
|
861
|
+
r"""
|
|
862
|
+
Free up the memory from the ``gmp_randstate_t`` in a
|
|
863
|
+
:class:`randstate`.
|
|
864
|
+
|
|
865
|
+
EXAMPLES::
|
|
866
|
+
|
|
867
|
+
sage: from sage.misc.randstate import randstate
|
|
868
|
+
sage: foo = randstate()
|
|
869
|
+
sage: foo = None
|
|
870
|
+
"""
|
|
871
|
+
gmp_randclear(self.gmp_state)
|
|
872
|
+
|
|
873
|
+
def __enter__(self):
|
|
874
|
+
r"""
|
|
875
|
+
Use a :class:`randstate` object as a ``with`` statement context
|
|
876
|
+
manager; switches this :class:`randstate` to be the current
|
|
877
|
+
:class:`randstate`, to be switched back on exit from the ``with``
|
|
878
|
+
statement.
|
|
879
|
+
|
|
880
|
+
For this purpose, we usually use the ``seed`` alias for
|
|
881
|
+
:class:`randstate`.
|
|
882
|
+
|
|
883
|
+
EXAMPLES::
|
|
884
|
+
|
|
885
|
+
sage: from sage.misc.randstate import randstate
|
|
886
|
+
sage: seed is randstate
|
|
887
|
+
True
|
|
888
|
+
sage: set_random_seed(-12345)
|
|
889
|
+
sage: ZZ.random_element(10^30)
|
|
890
|
+
197130468050826967386035500824
|
|
891
|
+
sage: ZZ.random_element(10^30)
|
|
892
|
+
601704412330400807050962541983
|
|
893
|
+
sage: set_random_seed(-12345)
|
|
894
|
+
sage: ZZ.random_element(10^30)
|
|
895
|
+
197130468050826967386035500824
|
|
896
|
+
sage: with seed(12345):
|
|
897
|
+
....: ZZ.random_element(10^30)
|
|
898
|
+
197130468050826967386035500824
|
|
899
|
+
sage: ZZ.random_element(10^30)
|
|
900
|
+
601704412330400807050962541983
|
|
901
|
+
"""
|
|
902
|
+
global _current_randstate
|
|
903
|
+
randstate_stack.append(_current_randstate)
|
|
904
|
+
_current_randstate = self
|
|
905
|
+
return self
|
|
906
|
+
|
|
907
|
+
def __exit__(self, ty, value, traceback):
|
|
908
|
+
r"""
|
|
909
|
+
Use a :class:`randstate` object as a ``with`` statement context
|
|
910
|
+
manager; restores the previous :class:`randstate` as the current
|
|
911
|
+
:class:`randstate`.
|
|
912
|
+
|
|
913
|
+
For this purpose, we usually use the ``seed`` alias for
|
|
914
|
+
:class:`randstate`.
|
|
915
|
+
|
|
916
|
+
EXAMPLES::
|
|
917
|
+
|
|
918
|
+
sage: from sage.misc.randstate import randstate
|
|
919
|
+
sage: seed is randstate
|
|
920
|
+
True
|
|
921
|
+
sage: set_random_seed(-12345)
|
|
922
|
+
sage: ZZ.random_element(10^30)
|
|
923
|
+
197130468050826967386035500824
|
|
924
|
+
sage: ZZ.random_element(10^30)
|
|
925
|
+
601704412330400807050962541983
|
|
926
|
+
sage: set_random_seed(-12345)
|
|
927
|
+
sage: ZZ.random_element(10^30)
|
|
928
|
+
197130468050826967386035500824
|
|
929
|
+
sage: with seed(12345):
|
|
930
|
+
....: ZZ.random_element(10^30)
|
|
931
|
+
197130468050826967386035500824
|
|
932
|
+
sage: ZZ.random_element(10^30)
|
|
933
|
+
601704412330400807050962541983
|
|
934
|
+
"""
|
|
935
|
+
global _current_randstate
|
|
936
|
+
_current_randstate = randstate_stack.pop()
|
|
937
|
+
return False
|
|
938
|
+
|
|
939
|
+
|
|
940
|
+
cpdef set_random_seed(seed=None):
|
|
941
|
+
r"""
|
|
942
|
+
Set the current random number seed from the given ``seed``
|
|
943
|
+
(which must be coercible to a Python long).
|
|
944
|
+
|
|
945
|
+
If no seed is given, then a seed is automatically selected
|
|
946
|
+
using :func:`os.urandom` if it is available, or the current
|
|
947
|
+
time otherwise.
|
|
948
|
+
|
|
949
|
+
Type ``sage.misc.randstate?`` for much more
|
|
950
|
+
information on random numbers in Sage.
|
|
951
|
+
|
|
952
|
+
This function is only intended for command line use. Never call
|
|
953
|
+
this from library code; instead, use ``with seed(s):``.
|
|
954
|
+
|
|
955
|
+
Note that setting the random number seed to 0 is much faster than
|
|
956
|
+
using any other number.
|
|
957
|
+
|
|
958
|
+
EXAMPLES::
|
|
959
|
+
|
|
960
|
+
sage: set_random_seed(5)
|
|
961
|
+
sage: initial_seed()
|
|
962
|
+
5
|
|
963
|
+
"""
|
|
964
|
+
global _current_randstate
|
|
965
|
+
_current_randstate = randstate(seed)
|
|
966
|
+
|
|
967
|
+
set_random_seed()
|
|
968
|
+
|
|
969
|
+
# Create an alias for randstate to be used in context managers
|
|
970
|
+
seed = randstate
|
|
971
|
+
|
|
972
|
+
cpdef int random() noexcept:
|
|
973
|
+
r"""
|
|
974
|
+
Return a 31-bit random number. Intended as a drop-in replacement for
|
|
975
|
+
the libc :func:`random()` function.
|
|
976
|
+
|
|
977
|
+
EXAMPLES::
|
|
978
|
+
|
|
979
|
+
sage: set_random_seed(31)
|
|
980
|
+
sage: from sage.misc.randstate import random
|
|
981
|
+
sage: random()
|
|
982
|
+
32990711
|
|
983
|
+
"""
|
|
984
|
+
return gmp_urandomb_ui(_current_randstate.gmp_state, 31)
|
|
985
|
+
|
|
986
|
+
|
|
987
|
+
def initial_seed():
|
|
988
|
+
r"""
|
|
989
|
+
Return the initial seed used to create the current :class:`randstate`.
|
|
990
|
+
|
|
991
|
+
EXAMPLES::
|
|
992
|
+
|
|
993
|
+
sage: set_random_seed(42)
|
|
994
|
+
sage: initial_seed()
|
|
995
|
+
42
|
|
996
|
+
|
|
997
|
+
If you set a random seed (by failing to specify the seed), this is how
|
|
998
|
+
you retrieve the seed actually chosen by Sage. This can also be
|
|
999
|
+
used to retrieve the seed chosen for a new Sage run (if the user
|
|
1000
|
+
has not used ``set_random_seed()``). ::
|
|
1001
|
+
|
|
1002
|
+
sage: set_random_seed()
|
|
1003
|
+
sage: initial_seed() # random
|
|
1004
|
+
121030915255244661507561642968348336774
|
|
1005
|
+
"""
|
|
1006
|
+
return _current_randstate._seed
|
|
1007
|
+
|
|
1008
|
+
|
|
1009
|
+
def benchmark_libc():
|
|
1010
|
+
r"""
|
|
1011
|
+
This function was used to test whether moving from libc to GMP's
|
|
1012
|
+
Mersenne Twister for random numbers would be a significant slowdown.
|
|
1013
|
+
|
|
1014
|
+
EXAMPLES::
|
|
1015
|
+
|
|
1016
|
+
sage: from sage.misc.randstate import benchmark_libc, benchmark_mt
|
|
1017
|
+
sage: timeit('benchmark_libc()') # random
|
|
1018
|
+
125 loops, best of 3: 1.95 ms per loop
|
|
1019
|
+
sage: timeit('benchmark_mt()') # random
|
|
1020
|
+
125 loops, best of 3: 2.12 ms per loop
|
|
1021
|
+
"""
|
|
1022
|
+
for _ in range(100000):
|
|
1023
|
+
c_libc_random()
|
|
1024
|
+
|
|
1025
|
+
|
|
1026
|
+
def benchmark_mt():
|
|
1027
|
+
r"""
|
|
1028
|
+
This function was used to test whether moving from libc to GMP's
|
|
1029
|
+
Mersenne Twister for random numbers would be a significant slowdown.
|
|
1030
|
+
|
|
1031
|
+
EXAMPLES::
|
|
1032
|
+
|
|
1033
|
+
sage: from sage.misc.randstate import benchmark_libc, benchmark_mt
|
|
1034
|
+
sage: timeit('benchmark_libc()') # random
|
|
1035
|
+
125 loops, best of 3: 1.95 ms per loop
|
|
1036
|
+
sage: timeit('benchmark_mt()') # random
|
|
1037
|
+
125 loops, best of 3: 2.11 ms per loop
|
|
1038
|
+
"""
|
|
1039
|
+
cdef int i
|
|
1040
|
+
cdef randstate rstate = _current_randstate
|
|
1041
|
+
for i from 0 <= i < 100000:
|
|
1042
|
+
gmp_urandomb_ui(rstate.gmp_state, 32)
|
|
1043
|
+
|
|
1044
|
+
|
|
1045
|
+
cpdef int _doctest_libc_random() noexcept:
|
|
1046
|
+
r"""
|
|
1047
|
+
Return the result of :func:`random()` from libc.
|
|
1048
|
+
|
|
1049
|
+
Only for use in doctests; this should not actually be used in Sage,
|
|
1050
|
+
since the resulting random number stream is not portable across
|
|
1051
|
+
operating systems.
|
|
1052
|
+
|
|
1053
|
+
EXAMPLES::
|
|
1054
|
+
|
|
1055
|
+
sage: from sage.misc.randstate import _doctest_libc_random
|
|
1056
|
+
sage: _doctest_libc_random() # random
|
|
1057
|
+
910236436
|
|
1058
|
+
"""
|
|
1059
|
+
return c_libc_random()
|