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
44Permission is hereby granted, free of charge, to any person obtaining a copy
55of this software and associated documentation files (the "Software"), to deal
2323#=============================================================================
2424from typing import Final
2525
26- from .baserandom import BaseRandom
26+ from .listindexstate import ListIndexState
2727from .annotation_types import Numerical , SeedStateType , StateType
2828from .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