Skip to content

Commit 0cbbfb9

Browse files
authored
Merge pull request #258 from schmouk/release-2-1
Release 2 1
2 parents 59e231f + fe5fd93 commit 0cbbfb9

File tree

512 files changed

+69341
-7483
lines changed

Some content is hidden

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

512 files changed

+69341
-7483
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-2025 Philippe Schmouker, schmouk (at) gmail.com.
3+
Copyright (c) 2016-2025 Philippe Schmouker, ph (dot) schmouker (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

Python3.10/.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.10/PyRandLib/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
It is provided under MIT License.
44
Please see files README.md and LICENSE.
55
6-
Copyright (c) 2016-2025 Philippe Schmouker, schmouk (at) gmail.com
6+
Copyright (c) 2016-2025 Philippe Schmouker, ph (dot) schmouker (at) gmail.com
77
"""
88

99
from .basecwg import BaseCWG

Python3.10/PyRandLib/annotation_types.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Copyright (c) 2021-2025 Philippe Schmouker, schmouk (at) gmail.com
2+
Copyright (c) 2021-2025 Philippe Schmouker, ph (dot) schmouker (at) gmail.com
33
44
Permission is hereby granted, free of charge, to any person obtaining a copy
55
of this software and associated documentation files (the "Software"), to deal
@@ -29,5 +29,3 @@
2929

3030

3131
#===== end of PyRandLib.annotation_types ===============================
32-
33-
# type: ignore (this comment line is just to avoid boring pylance related error checking)

Python3.10/PyRandLib/basecwg.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Copyright (c) 2025 Philippe Schmouker, schmouk (at) gmail.com
2+
Copyright (c) 2025 Philippe Schmouker, ph (dot) schmouker (at) gmail.com
33
44
Permission is hereby granted, free of charge, to any person obtaining a copy
55
of this software and associated documentation files (the "Software"), to deal
@@ -50,9 +50,11 @@ class BaseCWG( BaseRandom ):
5050
See Cwg64 for a minimum 2^70 (i.e. about 1.18e+21) period CW-Generator
5151
with low computation time, medium period, 64- bits output values and very
5252
good randomness characteristics.
53+
5354
See Cwg128_64 for a minimum 2^71 (i.e. about 2.36e+21) period CW-Generator
5455
with very low computation time, medium period, 64-bits output values and
5556
very good randomness characteristics.
57+
5658
See Cwg128 for a minimum 2^135 (i.e. about 4.36e+40) period CW-generator
5759
with very low computation time, medium period, 64- bits output values and
5860
very good randomness characteristics.
@@ -70,7 +72,7 @@ class BaseCWG( BaseRandom ):
7072
| PyRandLib class | [8] generator name | Memory Usage | Period | time-32bits | time-64 bits | SmallCrush fails | Crush fails | BigCrush fails |
7173
| --------------- | ------------------ | ------------- | -------- | ----------- | ------------ | ---------------- | ----------- | -------------- |
7274
| 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 |_
75+
| Cwg128_64 | CWG128_64 | 10 x 4-bytes | >= 2^71 | n.a. | n.a. | 0 | 0 | 0 |
7476
| Cwg128 | CWG128 | 16 x 4-bytes | >= 2^135 | n.a. | n.a. | 0 | 0 | 0 |
7577
7678
* _small crush_ is a small set of simple tests that quickly tests some of
@@ -82,13 +84,13 @@ class BaseCWG( BaseRandom ):
8284
"""
8385

8486
#-------------------------------------------------------------------------
85-
def __init__(self, _seedState: SeedStateType = None, /) -> None:
87+
def __init__(self, _seedState: SeedStateType = None, /) -> None: # type: ignore
8688
"""Constructor.
8789
8890
Should _seedState be None then the local time is used as a seed (with
8991
its shuffled value).
9092
Notice: method setstate() is not implemented in base class BaseRandom.
91-
So, it must be implemented in classes inheriting BaseLCG and it must
93+
So, it must be implemented in classes inheriting BaseCWG and it must
9294
initialize attribute self._state.
9395
"""
9496
super().__init__( _seedState ) # this internally calls 'setstate()' which
@@ -99,15 +101,15 @@ def __init__(self, _seedState: SeedStateType = None, /) -> None:
99101
def getstate(self) -> StatesListAndExt:
100102
"""Returns an object capturing the current internal state of the generator.
101103
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.
104+
This object can be passed to setstate() to restore the state.
105+
For CWG, this state is defined by a list of control values
106+
(a, weyl, s and an internal state value - or a list of 4 coeffs),
107+
which are used in methods 'next() and 'setstate() of every in-
108+
heriting class.
107109
108110
All inheriting classes MUST IMPLEMENT this method.
109111
"""
110-
return (self._a, self._weyl, self._s, self._state)
111-
112+
return (self._a, self._weyl, self._s, self._state) # type: ignore
113+
112114

113115
#===== end of module basecwg.py ========================================

Python3.10/PyRandLib/baselcg.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Copyright (c) 2016-2025 Philippe Schmouker, schmouk (at) gmail.com
2+
Copyright (c) 2016-2025 Philippe Schmouker, ph (dot) schmouker (at) gmail.com
33
44
Permission is hereby granted, free of charge, to any person obtaining a copy
55
of this software and associated documentation files (the "Software"), to deal
@@ -48,6 +48,7 @@ class BaseLCG( BaseRandom ):
4848
See FastRand32 for a 2^32 (i.e. 4.3e+9) period LC-Generator with very low
4949
computation time but shorter period and worse randomness characteristics
5050
than for FastRand63.
51+
5152
See FastRand63 for a 2^63 (i.e. about 9.2e+18) period LC-Generator with
5253
low computation time also, longer period and quite better randomness
5354
characteristics than for FastRand32.
@@ -77,7 +78,7 @@ class BaseLCG( BaseRandom ):
7778
"""
7879

7980
#-------------------------------------------------------------------------
80-
def __init__(self, _seedState: Numerical = None, /) -> None:
81+
def __init__(self, _seedState: Numerical = None, /) -> None: # type: ignore
8182
"""Constructor.
8283
8384
Should _seedState be None then the local time is used as a seed (with
@@ -91,15 +92,15 @@ def __init__(self, _seedState: Numerical = None, /) -> None:
9192

9293

9394
#-------------------------------------------------------------------------
94-
def getstate(self) -> int:
95+
def getstate(self) -> int: # type: ignore
9596
"""Returns an object capturing the current internal state of the generator.
9697
9798
This object can be passed to setstate() to restore the state.
9899
For LCG, the state is defined with a single integer, 'self._state',
99100
which has to be used in methods 'next() and 'setstate() of every
100101
inheriting class.
101102
"""
102-
return self._state
103+
return self._state # type: ignore
103104

104105

105106
#===== end of module baselcg.py ========================================

Python3.10/PyRandLib/baselfib64.py

Lines changed: 26 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Copyright (c) 2016-2025 Philippe Schmouker, schmouk (at) gmail.com
2+
Copyright (c) 2016-2025 Philippe Schmouker, ph (dot) schmouker (at) gmail.com
33
44
Permission is hereby granted, free of charge, to any person obtaining a copy
55
of this software and associated documentation files (the "Software"), to deal
@@ -23,13 +23,13 @@
2323
#=============================================================================
2424
from typing import Final
2525

26-
from .baserandom import BaseRandom
26+
from .listindexstate import ListIndexState
2727
from .annotation_types import Numerical, SeedStateType, StateType
2828
from .splitmix import SplitMix64
2929

3030

3131
#=============================================================================
32-
class BaseLFib64( BaseRandom ):
32+
class BaseLFib64( ListIndexState ):
3333
"""The base class for all LFib PRNG based on 64-bits numbers.
3434
3535
Definition of the base class for all LFib pseudo-random generators based
@@ -47,7 +47,7 @@ class BaseLFib64( BaseRandom ):
4747
+ (addition),
4848
- (substraction),
4949
* (multiplication),
50-
^(bitwise exclusive-or).
50+
^ (bitwise exclusive-or).
5151
5252
With the + or - operation, such generators are in fact MRGs. They offer very large
5353
periods with the best known results in the evaluation of their randomness, as
@@ -81,10 +81,10 @@ class BaseLFib64( BaseRandom ):
8181
8282
| PyRandLib class | TU01 generator name | Memory Usage | Period | time-32bits | time-64 bits | SmallCrush fails | Crush fails | BigCrush fails |
8383
| --------------- | ------------------------ | --------------- | ------- | ----------- | ------------ | ---------------- | ----------- | -------------- |
84-
| LFibRand78 | LFib(2^64, 17, 5, +) | 34 x 4-bytes | 2^78 | n.a. | 1.1 | 0 | 0 | 0 |
85-
| LFibRand116 | LFib(2^64, 55, 24, +) | 110 x 4-bytes | 2^116 | n.a. | 1.0 | 0 | 0 | 0 |
86-
| LFibRand668 | LFib(2^64, 607, 273, +) | 1,214 x 4-bytes | 2^668 | n.a. | 0.9 | 0 | 0 | 0 |
87-
| LFibRand1340 | LFib(2^64, 1279, 861, +) | 2,558 x 4-bytes | 2^1340 | n.a. | 0.9 | 0 | 0 | 0 |
84+
| LFib78 | LFib(2^64, 17, 5, +) | 34 x 4-bytes | 2^78 | n.a. | 1.1 | 0 | 0 | 0 |
85+
| LFib116 | LFib(2^64, 55, 24, +) | 110 x 4-bytes | 2^116 | n.a. | 1.0 | 0 | 0 | 0 |
86+
| LFib668 | LFib(2^64, 607, 273, +) | 1,214 x 4-bytes | 2^668 | n.a. | 0.9 | 0 | 0 | 0 |
87+
| LFib1340 | LFib(2^64, 1279, 861, +) | 2,558 x 4-bytes | 2^1340 | n.a. | 0.9 | 0 | 0 | 0 |
8888
8989
* _small crush_ is a small set of simple tests that quickly tests some of
9090
the expected characteristics for a pretty good PRNG;
@@ -96,111 +96,58 @@ class BaseLFib64( BaseRandom ):
9696

9797

9898
#-------------------------------------------------------------------------
99-
_NORMALIZE: Final[float] = 5.421_010_862_427_522_170_037_3e-20 # i.e. 1.0 / (1 << 64)
99+
_NORMALIZE: Final[float] = 5.421_010_862_427_522_170_037_3e-20 # i.e. 1.0 / (1 << 64) # type: ignore
100100
"""The value of this class attribute MUST BE OVERRIDDEN in inheriting
101101
classes if returned random integer values are coded on anything else
102102
than 32 bits. It is THE multiplier constant value to be applied to
103103
pseudo-random number for them to be normalized in interval [0.0, 1.0).
104104
"""
105105

106-
_OUT_BITS: Final[int] = 64
106+
_OUT_BITS: Final[int] = 64 # type: ignore
107107
"""The value of this class attribute MUST BE OVERRIDDEN in inheriting
108108
classes if returned random integer values are coded on anything else
109109
than 32 bits.
110110
"""
111111

112112

113113
#-------------------------------------------------------------------------
114-
def __init__(self, _seedState: SeedStateType = None, /) -> None:
114+
def __init__(self, _stateSize: int, _seedState: SeedStateType = None, /) -> None: # type: ignore
115115
"""Constructor.
116116
117+
_stateSize is the size of the internal state list of integers.
117118
_seedState is either a valid state, an integer, a float or None.
118119
About valid state: this is a tuple containing a list of
119-
self._STATE_SIZE integers and an index in this list (index value
120-
being then in range (0,self._STATE_SIZE)). Should _seedState be
121-
a sole integer or float then it is used as initial seed for
122-
the random filling of the internal list of self._STATE_SIZE
120+
self._STATE_SIZE 64-bits integers and an index in this list
121+
(index value being then in range (0,self._STATE_SIZE)). Should
122+
_seedState be a sole integer or float then it is used as initial
123+
seed for the random filling of the internal list of self._STATE_SIZE
123124
integers. Should _seedState be anything else (e.g. None) then
124125
the shuffling of the local current time value is used as such an
125126
initial seed.
126127
"""
127-
super().__init__( _seedState )
128+
super().__init__( SplitMix64, _stateSize, _seedState )
128129
# this call creates the two attributes
129130
# self._state and self._index, and sets them
130131
# since it internally calls self.setstate().
131132

132133

133134
#-------------------------------------------------------------------------
134-
def getstate(self) -> StateType:
135-
"""Returns an object capturing the current internal state of the generator.
136-
137-
This object can be passed to setstate() to restore the state. It is a
138-
tuple containing a list of self._STATE_SIZE integers and an
139-
index in this list (index value being then in range(0,self._STATE_SIZE).
135+
def seed(self, _seed: Numerical = None, /) -> None: # type: ignore
136+
"""Initiates the internal state of this pseudo-random generator.
140137
"""
141-
return (self._state[:], self._index)
138+
super().seed( _seed )
142139

143140

144141
#-------------------------------------------------------------------------
145-
def setstate(self, _seedState: StateType, /) -> None:
142+
def setstate(self, _state: StateType = None, /) -> None: # type: ignore
146143
"""Restores the internal state of the generator.
147144
148-
_seedState should have been obtained from a previous call to
149-
getstate(), and setstate() restores the internal state of the
150-
generator to what it was at the time setstate() was called.
151-
About valid state: this is a tuple containing a list of
152-
self._STATE_SIZE integers (31-bits) and an index in this list
153-
(index value being then in range(0,self._STATE_SIZE)). Should
154-
_seedState be a sole integer or float then it is used as
155-
initial seed for the random filling of the internal list of
156-
self._STATE_SIZE integers. Should _seedState be anything else
157-
(e.g. None) then the shuffling of the local current time
158-
value is used as such an initial seed.
159-
"""
160-
try:
161-
match len( _seedState ):
162-
case 0:
163-
self._index = 0
164-
self._initstate()
165-
166-
case 1:
167-
self._index = 0
168-
self._initstate( _seedState[0] )
169-
170-
case _:
171-
self._initindex( _seedState[1] )
172-
if (len(_seedState[0]) == self._STATE_SIZE):
173-
self._state = _seedState[0][:] # each entry in _seedState MUST be integer
174-
else:
175-
self._initstate( _seedState[0] )
176-
177-
except:
178-
self._index = 0
179-
self._initstate( _seedState )
180-
181-
182-
#-------------------------------------------------------------------------
183-
def _initindex(self, _index: int, /) -> None:
184-
"""Inits the internal index pointing to the internal list.
145+
_state should have been obtained from a previous call to getstate().
146+
'setstate()' restores the internal state of the generator to what it
147+
was at the time getstate() was lastly called.
148+
Inheriting classes MUST IMPLEMENT this method.
185149
"""
186-
try:
187-
self._index = int( _index ) % self._STATE_SIZE
188-
except:
189-
self._index = 0
190-
191-
192-
#-------------------------------------------------------------------------
193-
def _initstate(self, _initialSeed: Numerical = None, /) -> None:
194-
"""Inits the internal list of values.
195-
196-
Inits the internal list of values according to some initial
197-
seed that has to be an integer or a float ranging within
198-
[0.0, 1.0). Should it be None or anything else then the
199-
current local time value is used as initial seed value.
200-
"""
201-
initRand = SplitMix64( _initialSeed )
202-
self._state = [ initRand() for _ in range(self._STATE_SIZE) ]
150+
super().setstate(_state)
203151

204152

205153
#===== end of module baselfib64.py =====================================
206-

0 commit comments

Comments
 (0)