* Added more support for legacy 'rannyi' RNG from our Fortran codes,
including one from normal gaussian PDF.
This commit is contained in:
@@ -7,7 +7,7 @@
|
|||||||
import numpy
|
import numpy
|
||||||
|
|
||||||
class rng_base(object):
|
class rng_base(object):
|
||||||
"""Bas class for random number generator."""
|
"""Base class for random number generator."""
|
||||||
|
|
||||||
# Standard classes
|
# Standard classes
|
||||||
from wpylib.math.random.rng_lcg48 import lcg48
|
from wpylib.math.random.rng_lcg48 import lcg48
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ Implementation of 48-bit Linear Congruential pseudorandom number generator
|
|||||||
|
|
||||||
This RNG is used only for testing and regression purposes.
|
This RNG is used only for testing and regression purposes.
|
||||||
|
|
||||||
|
This module contains a python implementation of the Fortran 'rannyu' function
|
||||||
|
(including the hardcoded seed library).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from wpylib.math.random import rng_base
|
from wpylib.math.random import rng_base
|
||||||
@@ -43,12 +44,51 @@ class lcg48(rng_base):
|
|||||||
self.m = 34522712143931 # 11**13
|
self.m = 34522712143931 # 11**13
|
||||||
self.update_seed(rannyu_seed_lib[index])
|
self.update_seed(rannyu_seed_lib[index])
|
||||||
|
|
||||||
|
|
||||||
|
class rannyu(lcg48):
|
||||||
|
"""Simulation of Fortran rannyu method with support for normal
|
||||||
|
(Gaussian) PDF."""
|
||||||
|
def __init__(self, seed=None):
|
||||||
|
if seed==None:
|
||||||
|
seed = numpy.random.randint(102)+1
|
||||||
|
self.use_seed_lib(seed)
|
||||||
|
def normal(self, size):
|
||||||
|
rslt = numpy.empty(size)
|
||||||
|
size = numpy.product(rslt.shape)
|
||||||
|
for i in xrange(size):
|
||||||
|
rslt.flat[i] = GaussianRandom(self)
|
||||||
|
return rslt
|
||||||
|
|
||||||
|
|
||||||
|
def GaussianRandom(rnd):
|
||||||
|
"""Same implementation as in my perl or Fortran code.
|
||||||
|
rnd is a random number generator object (i.e. the rannyu object)."""
|
||||||
|
from numpy import sqrt, log
|
||||||
|
if not hasattr(rnd, "_gr_next_rnd"):
|
||||||
|
while True:
|
||||||
|
x = 2.0 * rnd() - 1.0
|
||||||
|
y = 2.0 * rnd() - 1.0
|
||||||
|
r2 = x*x + y*y
|
||||||
|
if 0.0 < r2 < 1.0: break
|
||||||
|
|
||||||
|
z = sqrt(-2.0 * log(r2) / r2)
|
||||||
|
rnd._gr_next_rnd = z * x # v
|
||||||
|
return z * y # u
|
||||||
|
else:
|
||||||
|
v = rnd._gr_next_rnd
|
||||||
|
del rnd._gr_next_rnd
|
||||||
|
return v
|
||||||
|
|
||||||
|
|
||||||
def mkint48(N):
|
def mkint48(N):
|
||||||
"""Generates a 48-bit number from four integers.
|
"""Generates a 48-bit number from four integers.
|
||||||
Used for encoding conversion for legacy rannyu library."""
|
Used for encoding conversion for legacy rannyu library."""
|
||||||
return N[3] + (N[2] << 12) + (N[1] << 24) + (N[0] << 36)
|
return N[3] + (N[2] << 12) + (N[1] << 24) + (N[0] << 36)
|
||||||
|
|
||||||
|
|
||||||
def split48(value):
|
def split48(value):
|
||||||
|
"""Splits a 48-bit integer into a 4-tuple of 12-bit integers.
|
||||||
|
"""
|
||||||
i4 = value & 0xFFF
|
i4 = value & 0xFFF
|
||||||
value >>= 12
|
value >>= 12
|
||||||
i3 = value & 0xFFF
|
i3 = value & 0xFFF
|
||||||
|
|||||||
Reference in New Issue
Block a user