Skip to content

Commit fe3b4ff

Browse files
authored
Merge pull request #150 from schmouk/dev
Dev --> Master / Prepare Release 2.0.0
2 parents 6f96014 + ecaf4cb commit fe3b4ff

File tree

342 files changed

+53163
-365
lines changed

Some content is hidden

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

342 files changed

+53163
-365
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2016-2022 Philippe Schmouker, schmouk (at) gmail.com.
3+
Copyright (c) 2016-2025 Philippe Schmouker, schmouk (at) gmail.com.
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

PyRandLib-org/__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, schmouk (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

PyRandLib-org/annotation_types.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""
2+
Copyright (c) 2021-2025 Philippe Schmouker, schmouk (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 List, Tuple, Union
25+
26+
Numerical = Union[ int, float ]
27+
StatesList = Union[ Tuple[int], List[int] ]
28+
StatesListAndExt = Tuple[ StatesList, int ]
29+
StateType = Union[ StatesList, StatesListAndExt ]
30+
SeedStateType = Union[ Numerical, StateType ]
31+
32+
33+
#===== end of PyRandLib.annotation_types ===============================
34+
35+
# type: ignore (this comment line is just to avoid boring pylance related error checking)

PyRandLib-org/basecwg.py

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
"""
2+
Copyright (c) 2025 Philippe Schmouker, schmouk (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 .baserandom import BaseRandom
25+
from .annotation_types import SeedStateType, StatesListAndExt
26+
27+
28+
#=============================================================================
29+
class BaseCWG( BaseRandom ):
30+
"""Definition of the base class for all Collatz-Weyl pseudo-random Generators.
31+
32+
This module is part of library PyRandLib.
33+
34+
Copyright (c) 2025 Philippe Schmouker
35+
36+
CWG models are chaotic generators that are combined with Weyl sequences to
37+
eliminate the risk of short cycles. They have a large period, a uniform
38+
distribution, and the ability to generate multiple independent streams by
39+
changing their internal parameters (Weyl increment). CWGs owe their
40+
exceptional quality to the arithmetical dynamics of noninvertible,
41+
generalized, Collatz mappings based on the wellknown Collatz conjecture.
42+
There is no jump function, but each odd number of the Weyl increment
43+
initiates a new unique period, which enables quick initialization of
44+
independent streams (this text is extracted from [8], see README.md).
45+
46+
The internal implementation of the CWG algorithm varies according to its
47+
implemented version. See implementation classes to get their formal
48+
description.
49+
50+
See Cwg64 for a minimum 2^70 (i.e. about 1.18e+21) period CW-Generator
51+
with low computation time, medium period, 64- bits output values and very
52+
good randomness characteristics.
53+
See Cwg128_64 for a minimum 2^71 (i.e. about 2.36e+21) period CW-Generator
54+
with very low computation time, medium period, 64-bits output values and
55+
very good randomness characteristics.
56+
See Cwg128 for a minimum 2^135 (i.e. about 4.36e+40) period CW-generator
57+
with very low computation time, medium period, 64- bits output values and
58+
very good randomness characteristics.
59+
60+
Furthermore this class is callable:
61+
rand = BaseCWG() # Caution: this is just used as illustrative. This base class cannot be instantiated
62+
print( rand() ) # prints a pseudo-random value within [0.0, 1.0)
63+
print( rand(a) ) # prints a pseudo-random value within [0, a) or [0.0, a) depending on the type of a
64+
print( rand(a, n) ) # prints a list of n pseudo-random values each within [0, a)
65+
66+
Reminder:
67+
We give you here below a copy of the table of tests for the CWGs that have
68+
been implemented in PyRandLib, as presented in paper [8] - see file README.md.
69+
70+
| PyRandLib class | [8] generator name | Memory Usage | Period | time-32bits | time-64 bits | SmallCrush fails | Crush fails | BigCrush fails |
71+
| --------------- | ------------------ | ------------- | -------- | ----------- | ------------ | ---------------- | ----------- | -------------- |
72+
| Cwg64 | CWG64 | 8 x 4-bytes | >= 2^70 | n.a. | n.a. | 0 | 0 | 0 |
73+
| Cwg128_64 | CWG128_64 | 10 x 4-bytes | >= 2^71 | n.a. | n.a. | 0 | 0 | 0 |_
74+
| Cwg128 | CWG128 | 16 x 4-bytes | >= 2^135 | n.a. | n.a. | 0 | 0 | 0 |
75+
76+
* _small crush_ is a small set of simple tests that quickly tests some of
77+
the expected characteristics for a pretty good PRNG;
78+
* _crush_ is a bigger set of tests that test more deeply expected random
79+
characteristics;
80+
* _big crush_ is the ultimate set of difficult tests that any GOOD PRNG
81+
should definitively pass.
82+
"""
83+
84+
#-------------------------------------------------------------------------
85+
def __init__(self, _seedState: SeedStateType = None) -> None:
86+
"""Constructor.
87+
88+
Should _seedState be None then the local time is used as a seed (with
89+
its shuffled value).
90+
Notice: method setstate() is not implemented in base class BaseRandom.
91+
So, it must be implemented in classes inheriting BaseLCG and it must
92+
initialize attribute self._state.
93+
"""
94+
super().__init__( _seedState ) # this internally calls 'setstate()' which
95+
# MUST be implemented in inheriting classes
96+
97+
98+
#-------------------------------------------------------------------------
99+
def getstate(self) -> StatesListAndExt:
100+
"""Returns an object capturing the current internal state of the generator.
101+
102+
This object can be passed to setstate() to restore the state.
103+
For CWG, this state is defined by a list of control values
104+
(a, weyl and s - or a list of 4 coeffs) and an internal state
105+
value, which are used in methods 'next() and 'setstate() of
106+
every inheriting class.
107+
108+
All inheriting classes MUST IMPLEMENT this method.
109+
"""
110+
return (self._a, self._weyl, self._s, self._state)
111+
112+
113+
#===== end of module basecwg.py ========================================

PyRandLib-org/baselcg.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
"""
2+
Copyright (c) 2016-2025 Philippe Schmouker, schmouk (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 .baserandom import BaseRandom
25+
from .annotation_types import Numerical
26+
27+
28+
#=============================================================================
29+
class BaseLCG( BaseRandom ):
30+
"""Definition of the base class for all LCG pseudo-random generators.
31+
32+
This module is part of library PyRandLib.
33+
34+
Copyright (c) 2016-2025 Philippe Schmouker
35+
36+
LCG models evaluate pseudo-random numbers suites x(i) as a simple mathem-
37+
atical function of
38+
39+
x(i-1): x(i) = (a*x(i-1) + c) mod m
40+
41+
Results are nevertheless considered to be poor as stated in the evaluation
42+
done by Pierre L'Ecuyer and Richard Simard (Universite de Montreal) in
43+
'TestU01: A C Library for Empirical Testing of Random Number Generators -
44+
ACM Transactions on Mathematical Software, vol.33 n.4, pp.22-40, August
45+
2007'. It is not recommended to use such pseudo-random numbers generators
46+
for serious simulation applications.
47+
48+
See FastRand32 for a 2^32 (i.e. 4.3e+9) period LC-Generator with very low
49+
computation time but shorter period and worse randomness characteristics
50+
than for FastRand63.
51+
See FastRand63 for a 2^63 (i.e. about 9.2e+18) period LC-Generator with
52+
low computation time also, longer period and quite better randomness
53+
characteristics than for FastRand32.
54+
55+
Furthermore this class is callable:
56+
rand = BaseLCG() # Caution: this is just used as illustrative. This base class cannot be instantiated
57+
print( rand() ) # prints a pseudo-random value within [0.0, 1.0)
58+
print( rand(a) ) # prints a pseudo-random value within [0, a) or [0.0, a) depending on the type of a
59+
print( rand(a, n) ) # prints a list of n pseudo-random values each within [0, a)
60+
61+
Reminder:
62+
We give you here below a copy of the table of tests for the LCGs that have
63+
been implemented in PyRandLib, as provided in paper "TestU01, ..." - see
64+
file README.md.
65+
66+
| PyRandLib class | TU01 generator name | Memory Usage | Period | time-32bits | time-64 bits | SmallCrush fails | Crush fails | BigCrush fails |
67+
| --------------- | ---------------------------------- | --------------- | ------- | ----------- | ------------ | ---------------- | ----------- | -------------- |
68+
| FastRand32 | LCG(2^32, 69069, 1) | 1 x 4-bytes | 2^32 | 3.20 | 0.67 | 11 | 106 | *too many* |
69+
| FastRand63 | LCG(2^63, 9219741426499971445, 1) | 2 x 4-bytes | 2^63 | 4.20 | 0.75 | 0 | 5 | 7 |
70+
71+
* _small crush_ is a small set of simple tests that quickly tests some of
72+
the expected characteristics for a pretty good PRNG;
73+
* _crush_ is a bigger set of tests that test more deeply expected random
74+
characteristics;
75+
* _big crush_ is the ultimate set of difficult tests that any GOOD PRNG
76+
should definitively pass.
77+
"""
78+
79+
#-------------------------------------------------------------------------
80+
def __init__(self, _seedState: Numerical = None) -> None:
81+
"""Constructor.
82+
83+
Should _seedState be None then the local time is used as a seed (with
84+
its shuffled value).
85+
Notice: method setstate() is not implemented in base class BaseRandom.
86+
So, it must be implemented in classes inheriting BaseLCG and it must
87+
initialize attribute self._state.
88+
"""
89+
super().__init__( _seedState ) # this internally calls 'setstate()' which
90+
# MUST be implemented in inheriting classes
91+
92+
93+
#-------------------------------------------------------------------------
94+
def getstate(self) -> int:
95+
"""Returns an object capturing the current internal state of the generator.
96+
97+
This object can be passed to setstate() to restore the state.
98+
For LCG, the state is defined with a single integer, 'self._state',
99+
which has to be used in methods 'next() and 'setstate() of every
100+
inheriting class.
101+
"""
102+
return self._state
103+
104+
#===== end of module baselcg.py ========================================

0 commit comments

Comments
 (0)