1- #!/usr/bin/env python
2- # -*- coding: utf-8 -*-
31"""
4- Copyright (c) 2016-2022 Philippe Schmouker, schmouk (at) gmail.com
2+ Copyright (c) 2016-2025 Philippe Schmouker, schmouk (at) gmail.com
53
64Permission is hereby granted, free of charge, to any person obtaining a copy
75of this software and associated documentation files (the "Software"), to deal
2321"""
2422
2523#=============================================================================
26- from .baserandom import BaseRandom
24+ from .baserandom import BaseRandom
25+ from .annotation_types import Numerical
2726
2827
2928#=============================================================================
@@ -32,19 +31,19 @@ class BaseLCG( BaseRandom ):
3231
3332 This module is part of library PyRandLib.
3433
35- Copyright (c) 2016-2021 Philippe Schmouker
34+ Copyright (c) 2016-2025 Philippe Schmouker
3635
3736 LCG models evaluate pseudo-random numbers suites x(i) as a simple mathem-
3837 atical function of
3938
4039 x(i-1): x(i) = (a*x(i-1) + c) mod m
4140
42- Results are nevertheless considered to be poor as stated in the
43- evaluation done by Pierre L'Ecuyer and Richard Simard (Universite de
44- Montreal) in 'TestU01: A C Library for Empirical Testing of Random Number
45- Generators - ACM Transactions on Mathematical Software, vol.33 n.4,
46- pp.22-40, August 2007'. It is not recommended to use such pseudo-random
47- numbers generators for serious simulation applications.
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.
4847
4948 See FastRand32 for a 2^32 (i.e. 4.3e+9) period LC-Generator with very low
5049 computation time but shorter period and worse randomness characteristics
@@ -54,73 +53,52 @@ class BaseLCG( BaseRandom ):
5453 characteristics than for FastRand32.
5554
5655 Furthermore this class is callable:
57- rand = BaseLCG()
58- print( rand() ) # prints a uniform pseudo-random value within [0.0, 1.0)
59- print( rand(a) ) # prints a uniform pseudo-random value within [0.0, a)
60- print( rand(a,b ) ) # prints a uniform pseudo-random value within [a , b )
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 )
6160
6261 Reminder:
6362 We give you here below a copy of the table of tests for the LCGs that have
6463 been implemented in PyRandLib, as provided in paper "TestU01, ..." - see
6564 file README.md.
6665
67- | PyRabndLib class | TU01 generator name | Memory Usage | Period | time-32bits | time-64 bits | SmallCrush fails | Crush fails | BigCrush fails |
68- | ---------------- | ---------------------------------- | --------------- | ------- | ----------- | ------------ | ---------------- | ----------- | -------------- |
69- | FastRand32 | LCG(2^32, 69069, 1) | 1 x 4-bytes | 2^32 | 3.20 | 0.67 | 11 | 106 | *too many* |
70- | FastRand63 | LCG(2^63, 9219741426499971445, 1) | 2 x 4-bytes | 2^63 | 4.20 | 0.75 | 0 | 5 | 7 |
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 |
7170
7271 * _small crush_ is a small set of simple tests that quickly tests some of
73- the expected characteristics for a pretty good PRG ;
72+ the expected characteristics for a pretty good PRNG ;
7473 * _crush_ is a bigger set of tests that test more deeply expected random
7574 characteristics;
76- * _big crush_ is the ultimate set of difficult tests that any GOOD PRG
75+ * _big crush_ is the ultimate set of difficult tests that any GOOD PRNG
7776 should definitively pass.
7877 """
7978
80- #------------------------------------------------------------------------=
81- def __init__ (self , _seedState : int = None ) -> None :
79+ #-------------------------------------------------------------------------
80+ def __init__ (self , _seedState : Numerical = None ) -> None :
8281 """Constructor.
8382
84- Should inSeed be None or not an integer then the local
85- time is used (with its shuffled value) as a seed.
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.
8688 """
87- super ().__init__ ( _seedState ) # this call creates attribute self._value and sets it
89+ super ().__init__ ( _seedState ) # this internally calls 'setstate()' which
90+ # MUST be implemented in inheriting classes
8891
8992
90- #------------------------------------------------------------------------=
91- def random (self ) -> float :
92- """This is the core of the pseudo-random generator.
93-
94- Returned values are within [0.0, 1.0).
95- Inheriting classes HAVE TO IMPLEMENT this method - see FastRand32
96- for an example. It should use and initialize attribute self._value.
97- """
98- raise NotImplementedError ()
99-
100-
101- #------------------------------------------------------------------------=
93+ #-------------------------------------------------------------------------
10294 def getstate (self ) -> int :
10395 """Returns an object capturing the current internal state of the generator.
10496
10597 This object can be passed to setstate() to restore the state.
106- For LCG, the state is defined with a single integer, 'self._value ',
107- which has to be used in methods 'random () and 'setstate() of every
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
108100 inheriting class.
109101 """
110- return self ._value
111-
112-
113- #------------------------------------------------------------------------=
114- def setstate (self , _state : int ) -> None :
115- """Restores the internal state of the generator.
116-
117- _state should have been obtained from a previous call to getstate(),
118- and setstate() restores the internal state of the generator to what
119- it was at the time setstate() was called.
120- Inheriting classes HAVE TO IMPLEMENT this method - see FastRand32
121- for an example. It should initialize attribute self._value.
122- """
123- raise NotImplementedError ()
124-
102+ return self ._state
125103
126104#===== end of module baselcg.py ========================================
0 commit comments