1+ #!/usr/bin/env python
2+ # -*- coding: utf-8 -*-
13"""
2- Copyright (c) 2016-2025 Philippe Schmouker, schmouk (at) gmail.com
4+ Copyright (c) 2016-2022 Philippe Schmouker, schmouk (at) gmail.com
35
46Permission is hereby granted, free of charge, to any person obtaining a copy
57of this software and associated documentation files (the "Software"), to deal
2123"""
2224
2325#=============================================================================
24- from .baserandom import BaseRandom
25- from .annotation_types import Numerical
26+ from .baserandom import BaseRandom
2627
2728
2829#=============================================================================
@@ -31,19 +32,19 @@ class BaseLCG( BaseRandom ):
3132
3233 This module is part of library PyRandLib.
3334
34- Copyright (c) 2016-2025 Philippe Schmouker
35+ Copyright (c) 2016-2021 Philippe Schmouker
3536
3637 LCG models evaluate pseudo-random numbers suites x(i) as a simple mathem-
3738 atical function of
3839
3940 x(i-1): x(i) = (a*x(i-1) + c) mod m
4041
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.
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.
4748
4849 See FastRand32 for a 2^32 (i.e. 4.3e+9) period LC-Generator with very low
4950 computation time but shorter period and worse randomness characteristics
@@ -53,52 +54,73 @@ class BaseLCG( BaseRandom ):
5354 characteristics than for FastRand32.
5455
5556 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 )
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 )
6061
6162 Reminder:
6263 We give you here below a copy of the table of tests for the LCGs that have
6364 been implemented in PyRandLib, as provided in paper "TestU01, ..." - see
6465 file README.md.
6566
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 |
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 |
7071
7172 * _small crush_ is a small set of simple tests that quickly tests some of
72- the expected characteristics for a pretty good PRNG ;
73+ the expected characteristics for a pretty good PRG ;
7374 * _crush_ is a bigger set of tests that test more deeply expected random
7475 characteristics;
75- * _big crush_ is the ultimate set of difficult tests that any GOOD PRNG
76+ * _big crush_ is the ultimate set of difficult tests that any GOOD PRG
7677 should definitively pass.
7778 """
7879
79- #-------------------------------------------------------------------------
80- def __init__ (self , _seedState : Numerical = None ) -> None :
80+ #------------------------------------------------------------------------=
81+ def __init__ (self , _seedState : int = None ) -> None :
8182 """Constructor.
8283
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.
84+ Should inSeed be None or not an integer then the local
85+ time is used (with its shuffled value) as a seed.
8886 """
89- super ().__init__ ( _seedState ) # this internally calls 'setstate()' which
90- # MUST be implemented in inheriting classes
87+ super ().__init__ ( _seedState ) # this call creates attribute self._value and sets it
9188
9289
93- #-------------------------------------------------------------------------
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+ #------------------------------------------------------------------------=
94102 def getstate (self ) -> int :
95103 """Returns an object capturing the current internal state of the generator.
96104
97105 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
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
100108 inheriting class.
101109 """
102- return self ._state
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+
103125
104126#===== end of module baselcg.py ========================================
0 commit comments