Skip to content

Commit ff3ccd2

Browse files
committed
#265-create Python 3.14 code
Completed. Still to be tested.
1 parent e387eb0 commit ff3ccd2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+16759
-64
lines changed

Python3.14/.coveragerc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[run]
2+
omit = unit_tests/* \
3+
test*.py
4+
5+
[report]
6+
fail_under = 100
7+
precision = 0

Python3.14/PyRandLib/__init__.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
"""
2+
This file is part of library PyRandLib.
3+
It is provided under MIT License.
4+
Please see files README.md and LICENSE.
5+
6+
Copyright (c) 2016-2025 Philippe Schmouker, ph (dot) schmouker (at) gmail.com
7+
"""
8+
9+
from .basecwg import BaseCWG
10+
from .baselcg import BaseLCG
11+
from .baselfib64 import BaseLFib64
12+
from .basemelg import BaseMELG
13+
from .basemrg import BaseMRG
14+
from .baserandom import BaseRandom
15+
from .basesquares import BaseSquares
16+
from .basewell import BaseWELL
17+
from .basexoroshiro import BaseXoroshiro
18+
from .cwg64 import Cwg64
19+
from .cwg128_64 import Cwg128_64
20+
from .cwg128 import Cwg128
21+
from .fastrand32 import FastRand32
22+
from .fastrand63 import FastRand63
23+
from .lfib78 import LFib78
24+
from .lfib116 import LFib116
25+
from .lfib668 import LFib668
26+
from .lfib1340 import LFib1340
27+
from .melg607 import Melg607
28+
from .melg19937 import Melg19937
29+
from .melg44497 import Melg44497
30+
from .mrg287 import Mrg287
31+
from .mrg1457 import Mrg1457
32+
from .mrg49507 import Mrg49507
33+
from .pcg64_32 import Pcg64_32
34+
from .pcg128_64 import Pcg128_64
35+
from .pcg1024_32 import Pcg1024_32
36+
from .squares32 import Squares32
37+
from .squares64 import Squares64
38+
from .well512a import Well512a
39+
from .well1024a import Well1024a
40+
from .well19937c import Well19937c
41+
from .well44497b import Well44497b
42+
from .xoroshiro256 import Xoroshiro256
43+
from .xoroshiro512 import Xoroshiro512
44+
from .xoroshiro1024 import Xoroshiro1024
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""
2+
Copyright (c) 2021-2025 Philippe Schmouker, ph (dot) schmouker (at) gmail.com
3+
4+
Permission is hereby granted, free of charge, to any person obtaining a copy
5+
of this software and associated documentation files (the "Software"), to deal
6+
in the Software without restriction, including without limitation the rights
7+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
copies of the Software, and to permit persons to whom the Software is
9+
furnished to do so, subject to the following conditions:
10+
11+
The above copyright notice and this permission notice shall be included in all
12+
copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
SOFTWARE.
21+
"""
22+
23+
#=============================================================================
24+
type Numerical = int | float
25+
type StatesList = tuple[int] | list[int]
26+
type StatesListAndExt = tuple[StatesList, int]
27+
type StateType = StatesList | StatesListAndExt
28+
type SeedStateType = Numerical | StateType
29+
30+
31+
#===== end of PyRandLib.annotation_types ===============================

Python3.14/PyRandLib/basecwg.py

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
"""
2+
Copyright (c) 2025 Philippe Schmouker, ph (dot) schmouker (at) gmail.com
3+
4+
Permission is hereby granted, free of charge, to any person obtaining a copy
5+
of this software and associated documentation files (the "Software"), to deal
6+
in the Software without restriction, including without limitation the rights
7+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
copies of the Software, and to permit persons to whom the Software is
9+
furnished to do so, subject to the following conditions:
10+
11+
The above copyright notice and this permission notice shall be included in all
12+
copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
SOFTWARE.
21+
"""
22+
23+
#=============================================================================
24+
from typing import override
25+
26+
from .baserandom import BaseRandom
27+
from .annotation_types import SeedStateType, StatesListAndExt
28+
29+
30+
#=============================================================================
31+
class BaseCWG( BaseRandom ):
32+
"""Definition of the base class for all Collatz-Weyl pseudo-random Generators.
33+
34+
This module is part of library PyRandLib.
35+
36+
Copyright (c) 2025 Philippe Schmouker
37+
38+
CWG models are chaotic generators that are combined with Weyl sequences to
39+
eliminate the risk of short cycles. They have a large period, a uniform
40+
distribution, and the ability to generate multiple independent streams by
41+
changing their internal parameters (Weyl increment). CWGs owe their
42+
exceptional quality to the arithmetical dynamics of noninvertible,
43+
generalized, Collatz mappings based on the wellknown Collatz conjecture.
44+
There is no jump function, but each odd number of the Weyl increment
45+
initiates a new unique period, which enables quick initialization of
46+
independent streams (this text is extracted from [8], see README.md).
47+
48+
The internal implementation of the CWG algorithm varies according to its
49+
implemented version. See implementation classes to get their formal
50+
description.
51+
52+
See Cwg64 for a minimum 2^70 (i.e. about 1.18e+21) period CW-Generator
53+
with low computation time, medium period, 64- bits output values and very
54+
good randomness characteristics.
55+
56+
See Cwg128_64 for a minimum 2^71 (i.e. about 2.36e+21) period CW-Generator
57+
with very low computation time, medium period, 64-bits output values and
58+
very good randomness characteristics.
59+
60+
See Cwg128 for a minimum 2^135 (i.e. about 4.36e+40) period CW-generator
61+
with very low computation time, medium period, 64- bits output values and
62+
very good randomness characteristics.
63+
64+
Furthermore this class is callable:
65+
rand = BaseCWG() # Caution: this is just used as illustrative. This base class cannot be instantiated
66+
print( rand() ) # prints a pseudo-random value within [0.0, 1.0)
67+
print( rand(a) ) # prints a pseudo-random value within [0, a) or [0.0, a) depending on the type of a
68+
print( rand(a, n) ) # prints a list of n pseudo-random values each within [0, a)
69+
70+
Reminder:
71+
We give you here below a copy of the table of tests for the CWGs that have
72+
been implemented in PyRandLib, as presented in paper [8] - see file README.md.
73+
74+
| PyRandLib class | [8] generator name | Memory Usage | Period | time-32bits | time-64 bits | SmallCrush fails | Crush fails | BigCrush fails |
75+
| --------------- | ------------------ | ------------- | -------- | ----------- | ------------ | ---------------- | ----------- | -------------- |
76+
| Cwg64 | CWG64 | 8 x 4-bytes | >= 2^70 | n.a. | n.a. | 0 | 0 | 0 |
77+
| Cwg128_64 | CWG128_64 | 10 x 4-bytes | >= 2^71 | n.a. | n.a. | 0 | 0 | 0 |
78+
| Cwg128 | CWG128 | 16 x 4-bytes | >= 2^135 | n.a. | n.a. | 0 | 0 | 0 |
79+
80+
* _small crush_ is a small set of simple tests that quickly tests some of
81+
the expected characteristics for a pretty good PRNG;
82+
* _crush_ is a bigger set of tests that test more deeply expected random
83+
characteristics;
84+
* _big crush_ is the ultimate set of difficult tests that any GOOD PRNG
85+
should definitively pass.
86+
"""
87+
88+
#-------------------------------------------------------------------------
89+
def __init__(self, _seedState: SeedStateType = None, /) -> None: # type: ignore
90+
"""Constructor.
91+
92+
Should _seedState be None then the local time is used as a seed (with
93+
its shuffled value).
94+
Notice: method setstate() is not implemented in base class BaseRandom.
95+
So, it must be implemented in classes inheriting BaseCWG and it must
96+
initialize attribute self._state.
97+
"""
98+
super().__init__( _seedState ) # this internally calls 'setstate()' which
99+
# MUST be implemented in inheriting classes
100+
101+
102+
#-------------------------------------------------------------------------
103+
@override
104+
def getstate(self) -> StatesListAndExt:
105+
"""Returns an object capturing the current internal state of the generator.
106+
107+
This object can be passed to setstate() to restore the state.
108+
For CWG, this state is defined by a list of control values
109+
(a, weyl, s and an internal state value - or a list of 4 coeffs),
110+
which are used in methods 'next() and 'setstate() of every in-
111+
heriting class.
112+
113+
All inheriting classes MUST IMPLEMENT this method.
114+
"""
115+
return (self._a, self._weyl, self._s, self._state) # type: ignore
116+
117+
118+
#===== end of module basecwg.py ========================================

Python3.14/PyRandLib/baselcg.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
"""
2+
Copyright (c) 2016-2025 Philippe Schmouker, ph (dot) schmouker (at) gmail.com
3+
4+
Permission is hereby granted, free of charge, to any person obtaining a copy
5+
of this software and associated documentation files (the "Software"), to deal
6+
in the Software without restriction, including without limitation the rights
7+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
copies of the Software, and to permit persons to whom the Software is
9+
furnished to do so, subject to the following conditions:
10+
11+
The above copyright notice and this permission notice shall be included in all
12+
copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
SOFTWARE.
21+
"""
22+
23+
#=============================================================================
24+
from typing import override
25+
26+
from .baserandom import BaseRandom
27+
from .annotation_types import Numerical
28+
29+
30+
#=============================================================================
31+
class BaseLCG( BaseRandom ):
32+
"""Definition of the base class for all LCG pseudo-random generators.
33+
34+
This module is part of library PyRandLib.
35+
36+
Copyright (c) 2016-2025 Philippe Schmouker
37+
38+
LCG models evaluate pseudo-random numbers suites x(i) as a simple mathem-
39+
atical function of
40+
41+
x(i-1): x(i) = (a*x(i-1) + c) mod m
42+
43+
Results are nevertheless considered to be poor as stated in the evaluation
44+
done by Pierre L'Ecuyer and Richard Simard (Universite de Montreal) in
45+
'TestU01: A C Library for Empirical Testing of Random Number Generators -
46+
ACM Transactions on Mathematical Software, vol.33 n.4, pp.22-40, August
47+
2007'. It is not recommended to use such pseudo-random numbers generators
48+
for serious simulation applications.
49+
50+
See FastRand32 for a 2^32 (i.e. 4.3e+9) period LC-Generator with very low
51+
computation time but shorter period and worse randomness characteristics
52+
than for FastRand63.
53+
54+
See FastRand63 for a 2^63 (i.e. about 9.2e+18) period LC-Generator with
55+
low computation time also, longer period and quite better randomness
56+
characteristics than for FastRand32.
57+
58+
Furthermore this class is callable:
59+
rand = BaseLCG() # Caution: this is just used as illustrative. This base class cannot be instantiated
60+
print( rand() ) # prints a pseudo-random value within [0.0, 1.0)
61+
print( rand(a) ) # prints a pseudo-random value within [0, a) or [0.0, a) depending on the type of a
62+
print( rand(a, n) ) # prints a list of n pseudo-random values each within [0, a)
63+
64+
Reminder:
65+
We give you here below a copy of the table of tests for the LCGs that have
66+
been implemented in PyRandLib, as provided in paper "TestU01, ..." - see
67+
file README.md.
68+
69+
| PyRandLib class | TU01 generator name | Memory Usage | Period | time-32bits | time-64 bits | SmallCrush fails | Crush fails | BigCrush fails |
70+
| --------------- | ---------------------------------- | --------------- | ------- | ----------- | ------------ | ---------------- | ----------- | -------------- |
71+
| FastRand32 | LCG(2^32, 69069, 1) | 1 x 4-bytes | 2^32 | 3.20 | 0.67 | 11 | 106 | *too many* |
72+
| FastRand63 | LCG(2^63, 9219741426499971445, 1) | 2 x 4-bytes | 2^63 | 4.20 | 0.75 | 0 | 5 | 7 |
73+
74+
* _small crush_ is a small set of simple tests that quickly tests some of
75+
the expected characteristics for a pretty good PRNG;
76+
* _crush_ is a bigger set of tests that test more deeply expected random
77+
characteristics;
78+
* _big crush_ is the ultimate set of difficult tests that any GOOD PRNG
79+
should definitively pass.
80+
"""
81+
82+
#-------------------------------------------------------------------------
83+
def __init__(self, _seedState: Numerical = None, /) -> None: # type: ignore
84+
"""Constructor.
85+
86+
Should _seedState be None then the local time is used as a seed (with
87+
its shuffled value).
88+
Notice: method setstate() is not implemented in base class BaseRandom.
89+
So, it must be implemented in classes inheriting BaseLCG and it must
90+
initialize attribute self._state.
91+
"""
92+
super().__init__( _seedState ) # this internally calls 'setstate()' which
93+
# MUST be implemented in inheriting classes
94+
95+
96+
#-------------------------------------------------------------------------
97+
@override
98+
def getstate(self) -> int: # type: ignore
99+
"""Returns an object capturing the current internal state of the generator.
100+
101+
This object can be passed to setstate() to restore the state.
102+
For LCG, the state is defined with a single integer, 'self._state',
103+
which has to be used in methods 'next() and 'setstate() of every
104+
inheriting class.
105+
"""
106+
return self._state # type: ignore
107+
108+
109+
#===== end of module baselcg.py ========================================

0 commit comments

Comments
 (0)