From 1ac63d456439978ed0badbf7e94fe085402466c6 Mon Sep 17 00:00:00 2001 From: Gertjan van den Burg Date: Fri, 31 Jul 2015 00:04:46 +0200 Subject: added randbelow and shuffle methods --- SyncRNG.R | 30 +++++++++++++++++++++++++++++- SyncRNG.py | 26 ++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/SyncRNG.R b/SyncRNG.R index 1849d89..ca25eef 100644 --- a/SyncRNG.R +++ b/SyncRNG.R @@ -5,10 +5,12 @@ dyn.load('RSyncRNG.so') SyncRNG <- setRefClass('SyncRNG', fields=list( seed='numeric', - state='numeric' + state='numeric', + BPF='numeric' ), methods=list( initialize=function(..., seed=0) { + BPF <<- 32 seed <<- seed tmp <- .Call('R_syncrng_seed', as.numeric(seed)) @@ -24,6 +26,32 @@ SyncRNG <- setRefClass('SyncRNG', rand=function() { r <- randi() return (r * 2.3283064365387e-10) + }, + randbelow=function(n) { + maxsize <- 2^BPF + if (n >= maxsize) { + warning(paste("Underlying random generator ", + "does not supply\n enough bits ", + "to choose from a population ", + "range this large.\n")) + return(round(rand() * n)) + } + rem <- maxsize %% n + limit <- (maxsize - rem) / maxsize + r <- rand() + while (r >= limit) + r <- rand() + return(round(r*maxsize) %% n) + }, + shuffle=function(x) { + y <- x + for (i in rev(1:(length(y)-1))) { + j <- randbelow(i+1) + tmp <- y[i+1] + y[i+1] <- y[j+1] + y[j+1] <- tmp + } + return(y) } ) ) diff --git a/SyncRNG.py b/SyncRNG.py index 7137439..7ef6fd6 100644 --- a/SyncRNG.py +++ b/SyncRNG.py @@ -4,11 +4,16 @@ used to seed and pull numbers from the RNG. """ +from __future__ import division + +from warnings import warn as _warn + import syncrng class SyncRNG(object): def __init__(self, seed=0): + self.BPF = 32 self.seed = seed self.state = syncrng.seed(seed) @@ -19,3 +24,24 @@ class SyncRNG(object): def rand(self): return self.randi() * 2.3283064365387e-10 + + def randbelow(self, n): + maxsize = 1<= maxsize: + _warn("Underlying random generator does not supply \n" + "enough bits to choose from a population range this " + "large.\n") + return int(self.rand() * n) + rem = maxsize % n + limit = (maxsize - rem) / maxsize + r = self.rand() + while r >= limit: + r = self.rand() + return int(r*maxsize) % n + + def shuffle(self, x): + y = x[:] + for i in reversed(range(1, len(y))): + j = self.randbelow(i+1) + y[i], y[j] = y[j], y[i] + return y -- cgit v1.2.3