Skip to content

Commit 72c6def

Browse files
authored
Merge pull request #18 from schmouk/optimize-code
Optimize code
2 parents b30c523 + b85e12e commit 72c6def

File tree

14 files changed

+99
-75
lines changed

14 files changed

+99
-75
lines changed

PyRandLib/README.md

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ If you decide to use this library, please add the copyright notice to your
99
software as stated in the LICENSE file.
1010

1111
```
12-
Copyright (c) 2016-2021 Philippe Schmouker, schmouk (at) typee.ovh
12+
Copyright (c) 2016-2021 Philippe Schmouker, <ph.schmouker (at) gmail.com>
1313
1414
Permission is hereby granted, free of charge, to any person obtaining a copy
1515
of this software and associated documentation files (the "Software"), to deal
@@ -106,12 +106,21 @@ implemented in PyRabdLib, as provided in [1].
106106

107107

108108
## Implementation
109-
Current implementation of PyRandLib uses Python 3.x with no Cython version.
110-
It has been tested with Python 3.8 but should run with most of Python 3 suvbversions.
109+
Current implementation of PyRandLib uses Python 3.x with no Cython version.
110+
It has been tested with Python 3.8 but should run with all of Python 3.
111111

112-
Python 2.7 could be later available, if asked for. Cython implementations
113-
could also be later available.
112+
Note 1: PyRandLib version 1.1 and below should work with all versions of
113+
Python 3. In version 1.2, we have added underscores in numerical constants
114+
for the better readability of the code. This feature has been introduced in
115+
Python 3.6. If you want to use PyRandLib version 1.2 or above with Python
116+
3.5 or below, removing these underscores should be sufficient to have the
117+
library running correctly.
114118

119+
Note 2: no version or PyRandLib will ever be provided for Python 2 which is
120+
a no more maintained version of the Python language.
121+
122+
Note 3: a Cython version of PyRandLib might be delivered in a next release.
123+
Up today, no date is planned for this.
115124

116125

117126
## Architecture overview

PyRandLib/baselfib64.py

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
#=============================================================================
2626
from .baserandom import BaseRandom
27-
from .fastrand63 import FastRand63
27+
from .fastrand32 import FastRand32
2828
from .types import SeedStateType, StateType
2929

3030

@@ -59,7 +59,7 @@ class BaseLFib64( BaseRandom ):
5959
See LFib78, LFib116, LFib668 and LFib1340 for long period LFib generators (resp.
6060
2^78, 2^116, 2^668 and 2^1340 periods, i.e. resp. 3.0e+23, 8.3e+34, 1.2e+201 and
6161
2.4e+403 periods) while same computation time and far higher precision (64-bits
62-
calculations) then MRGs, but memory consumption (resp. 17, 55, 607 and 1279
62+
calculations) than MRGs, but more memory consumption (resp. 17, 55, 607 and 1279
6363
integers).
6464
6565
Please notice that this class and all its inheriting sub-classes are callable.
@@ -151,17 +151,24 @@ def setstate(self, _seedState: StateType) -> None:
151151
(e.g. None) then the shuffling of the local current time
152152
value is used as such an initial seed.
153153
"""
154-
if not isinstance( _seedState, tuple ):
155-
self._initIndex( 0 )
156-
self._initList( _seedState )
154+
try:
155+
count = len( _seedState )
157156

158-
elif len( _seedState ) < 2:
157+
if count == 0:
158+
self._initIndex( 0 )
159+
self._initList()
160+
161+
elif count == 1:
162+
self._initIndex( 0 )
163+
self._initList( _seedState[0] )
164+
165+
else:
166+
self._initIndex( _seedState[1] )
167+
self._list = _seedState[0][:]
168+
169+
except:
159170
self._initIndex( 0 )
160-
self._initList( _seedState[0] )
161-
162-
else:
163-
self._initIndex( _seedState[1] )
164-
self._list = _seedState[0][:]
171+
self._initList( _seedState )
165172

166173

167174
#------------------------------------------------------------------------=
@@ -183,15 +190,8 @@ def _initList(self, _initialSeed: StateType = None) -> None:
183190
[0.0, 1.0). Should it be None or anything else then the
184191
current local time value is used as initial seed value.
185192
"""
186-
myRand = FastRand63( _initialSeed )
187-
#-----------------------------------------------------------------
188-
def _getValue( _dummy ):
189-
myRand()
190-
v = myRand._value << 1
191-
return v + (1 if myRand() >= 0.5 else 0)
192-
#-----------------------------------------------------------------
193-
self._list = list( map( _getValue, range(self._LIST_SIZE) ) )
193+
myRand = FastRand32( _initialSeed )
194+
self._list = [ (int(myRand(0x1_0000_0000)) << 32) + int(myRand(0x1_0000_0000)) for _ in range(self._LIST_SIZE) ]
194195

195-
196196
#===== end of module baselfib64.py =====================================
197197

PyRandLib/basemrg.py

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -147,17 +147,24 @@ def setstate(self, _seedState: StateType) -> None:
147147
(e.g. None) then the shuffling of the local current time
148148
value is used as such an initial seed.
149149
"""
150-
if not isinstance( _seedState, tuple ):
151-
self._initIndex( 0 )
152-
self._initList( _seedState )
150+
try:
151+
count = len( _seedState )
153152

154-
elif len( _seedState ) < 2:
153+
if count == 0:
154+
self._initIndex( 0 )
155+
self._initList()
156+
157+
elif count == 1:
158+
self._initIndex( 0 )
159+
self._initList( _seedState[0] )
160+
161+
else:
162+
self._initIndex( _seedState[1] )
163+
self._list = _seedState[0][:]
164+
165+
except:
155166
self._initIndex( 0 )
156-
self._initList( _seedState[0] )
157-
158-
else:
159-
self._initIndex( _seedState[1] )
160-
self._list = _seedState[0][:]
167+
self._initList( _seedState )
161168

162169

163170
#------------------------------------------------------------------------=
@@ -181,8 +188,7 @@ def _initList(self, _initialSeed: StateType = None) -> None:
181188
"""
182189
# feeds the list according to an initial seed and the value+1 of the modulo.
183190
myRand = FastRand32( _initialSeed )
184-
my_list = list( map( lambda _ : int(myRand(self._MODULO+1)), range(self._LIST_SIZE) ) )
185-
self._list = my_list
191+
self._list = [ int(myRand(self._MODULO+1)) for _ in range(self._LIST_SIZE) ]
186192

187193

188194
#===== end of module basemrg.py ========================================

PyRandLib/baserandom.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#=============================================================================
2626
from random import Random
27+
from typing import Any
2728

2829
from .types import Numeric, SeedStateType
2930

@@ -217,12 +218,20 @@ class BaseRandom( Random ):
217218
def __init__(self, _seed: SeedStateType = None) -> None:
218219
"""Constructor.
219220
220-
Should _seed be None or not an integer then the
221-
local time is used (with its shuffled value) as a seed.
221+
Should _seed be None or not an integer then the local
222+
time is used (with its shuffled value) as a seed.
222223
"""
223224
super().__init__( _seed ) ## this call creates attribute self._value and sets it
224225

225226

227+
#------------------------------------------------------------------------=
228+
@property
229+
def value(self) -> Any:
230+
"""Read-only wrapper to built-in attribute '._value'
231+
"""
232+
return self._value
233+
234+
226235
#------------------------------------------------------------------------=
227236
def seed(self, _seed: SeedStateType = None) -> None:
228237
"""Initiates the internal state of this pseudo-random generator.

PyRandLib/fastrand32.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ def random(self) -> float:
108108
109109
Returned values are within [0.0, 1.0).
110110
"""
111-
self._value = (69069 * self._value + 1) & 0xffffffff
112-
return self._value / 4294967296.0
111+
self._value = (69069 * self._value + 1) & 0xffff_ffff
112+
return self._value / 4_294_967_296.0
113113

114114

115115
#------------------------------------------------------------------------=
@@ -123,23 +123,23 @@ def setstate(self, _state: Numeric) -> None:
123123
"""
124124
if isinstance( _state, int ):
125125
# passed initial seed is an integer, just uses it
126-
self._value = _state & 0xffffffff
126+
self._value = _state & 0xffff_ffff
127127

128128
elif isinstance( _state, float ):
129129
# transforms passed initial seed from float to integer
130130
if _state < 0.0 :
131131
_state = -_state
132132
if _state >= 1.0:
133-
self._value = int( _state + 0.5 ) & 0xffffffff
133+
self._value = int( _state + 0.5 ) & 0xffff_ffff
134134
else:
135-
self._value = int( _state * 0x100000000) & 0xffffffff
135+
self._value = int( _state * 0x1_0000_0000) & 0xffff_ffff
136136

137137
else:
138138
# uses local time as initial seed
139139
t = int( time.time() * 1000.0 )
140-
self._value = ( ((t & 0xff000000) >> 24) +
141-
((t & 0x00ff0000) >> 8) +
142-
((t & 0x0000ff00) << 8) +
143-
((t & 0x000000ff) << 24) )
140+
self._value = ( ((t & 0xff00_0000) >> 24) +
141+
((t & 0x00ff_0000) >> 8) +
142+
((t & 0x0000_ff00) << 8) +
143+
((t & 0x0000_00ff) << 24) )
144144

145145
#===== end of module fastrand32.py =====================================

PyRandLib/fastrand63.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ def random(self) -> float:
9898
9999
Returned values are within [0.0, 1.0).
100100
"""
101-
self._value = (9219741426499971445 * self._value + 1) & 0x7fffffffffffffff
102-
return self._value / 9223372036854775808.0
101+
self._value = (9_219_741_426_499_971_445 * self._value + 1) & 0x7fff_ffff_ffff_ffff
102+
return self._value / 9_223_372_036_854_775_808.0
103103

104104

105105
#------------------------------------------------------------------------=
@@ -112,24 +112,24 @@ def setstate(self, _state: Numeric) -> None:
112112
setstate() was called.
113113
"""
114114
if isinstance( _state, int ):
115-
self._value = _state & 0x7fffffffffffffff
115+
self._value = _state & 0x7fff_ffff_ffff_ffff
116116

117117
elif isinstance( _state, float ):
118118
# transforms passed initial seed from float to integer
119119
if _state < 0.0 :
120120
_state = -_state
121121

122122
if _state >= 1.0:
123-
self._value = int(_state+0.5) & 0x7fffffffffffffff
123+
self._value = int(_state+0.5) & 0x7fff_ffff_ffff_ffff
124124
else:
125-
self._value = int(_state*0x8000000000000000) & 0x7fffffffffffffff
125+
self._value = int(_state*0x8000_0000_0000_0000) & 0x7fff_ffff_ffff_ffff
126126

127127
else:
128128
t = int(time.time() * 1000.0)
129-
self._value = t & 0xffffffff
130-
self._value += (t & 0xff000000) << 8
131-
self._value += (t & 0x00ff0000) << 24
132-
self._value += (t & 0x0000ff00) << 40
133-
self._value += (t & 0x000000fe) << 63
129+
self._value = t & 0xffff_ffff
130+
self._value += (t & 0xff00_0000) << 8
131+
self._value += (t & 0x00ff_0000) << 24
132+
self._value += (t & 0x0000_ff00) << 40
133+
self._value += (t & 0x0000_00fe) << 63
134134

135135
#===== end of module fastrand63.py =====================================

PyRandLib/lfib116.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,14 +126,14 @@ def random(self) -> float:
126126
k24 += LFib116._LIST_SIZE
127127

128128
# then evaluates current value
129-
myValue = (self._list[k24] + self._list[self._index]) & 18446744073709551615
129+
myValue = (self._list[k24] + self._list[self._index]) & 18_446_744_073_709_551_615
130130
self._list[self._index] = myValue
131131

132132
# next index
133133
self._index = (self._index+1) % LFib116._LIST_SIZE
134134

135135
# then returns float value within [0.0, 1.0)
136-
return myValue / 18446744073709551616.0
136+
return myValue / 18_446_744_073_709_551_616.0
137137

138138

139139
#===== end of module lfib116.py ========================================

PyRandLib/lfib1340.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,14 +127,14 @@ def random(self) -> float:
127127
k861 += LFib1340._LIST_SIZE
128128

129129
# then evaluates current value
130-
myValue = (self._list[k861] + self._list[self._index]) & 0xffffffffffffffff
130+
myValue = (self._list[k861] + self._list[self._index]) & 0xffff_ffff_ffff_ffff
131131
self._list[self._index] = myValue
132132

133133
# next index
134134
self._index = (self._index+1) % LFib1340._LIST_SIZE
135135

136136
# then returns float value within [0.0, 1.0)
137-
return myValue / 18446744073709551616.0
137+
return myValue / 18_446_744_073_709_551_616.0
138138

139139

140140
#===== end of module lfib1340.py ======================================

PyRandLib/lfib668.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,14 +126,14 @@ def random(self) -> float:
126126
k273 += LFib668._LIST_SIZE
127127

128128
# then evaluates current value
129-
myValue = (self._list[k273] + self._list[self._index]) & 18446744073709551615
129+
myValue = (self._list[k273] + self._list[self._index]) & 18_446_744_073_709_551_615
130130
self._list[self._index] = myValue
131131

132132
# next index
133133
self._index = (self._index+1) % LFib668._LIST_SIZE
134134

135135
# then returns float value within [0.0, 1.0)
136-
return myValue / 18446744073709551616.0
136+
return myValue / 18_446_744_073_709_551_616.0
137137

138138

139139
#===== end of module lfib668.py =======================================

PyRandLib/lfib78.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,14 @@ def random(self) -> float:
125125
k5 += LFib78._LIST_SIZE
126126

127127
# then evaluates current value
128-
myValue = (self._list[k5] + self._list[self._index]) & 18446744073709551615
128+
myValue = (self._list[k5] + self._list[self._index]) & 18_446_744_073_709_551_615
129129
self._list[self._index] = myValue
130130

131131
# next index
132132
self._index = (self._index+1) % LFib78._LIST_SIZE
133133

134134
# then returns float value within [0.0, 1.0)
135-
return myValue / 18446744073709551616.0
135+
return myValue / 18_446_744_073_709_551_616.0
136136

137137

138138
#===== end of module lfib78.py =========================================

0 commit comments

Comments
 (0)