summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2017-01-08 00:53:23 +0100
committerAraq <rumpf_a@web.de>2017-01-08 00:53:23 +0100
commit13649778c1fc4ffba0d51368f231fc2ff1a0c86d (patch)
tree5881d3a8034a0466a7ba4fd8cdd9d165e2b9b2b9 /lib
parent9c47bb9cc0fda686ca403f5abd0ae2f06d364c74 (diff)
downloadNim-13649778c1fc4ffba0d51368f231fc2ff1a0c86d.tar.gz
random.nim: added shuffle proc; fixes 'mod' bias
Diffstat (limited to 'lib')
-rw-r--r--lib/pure/random.nim14
1 files changed, 12 insertions, 2 deletions
diff --git a/lib/pure/random.nim b/lib/pure/random.nim
index 67f085dac..9484557a9 100644
--- a/lib/pure/random.nim
+++ b/lib/pure/random.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2016 Andreas Rumpf
+#        (c) Copyright 2017 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -22,6 +22,8 @@ when defined(JS):
 else:
   type ui = uint64
 
+const randMax = 18_446_744_073_709_551_615u64
+
 type
   RandomGenState = object
     a0, a1: ui
@@ -72,7 +74,10 @@ proc random*(max: int): int {.benign.} =
   ## random number is always the same, unless `randomize` is called
   ## which initializes the random number generator with a "random"
   ## number, i.e. a tickcount.
-  result = int(next(state) mod uint64(max))
+  while true:
+    let x = next(state)
+    if x < randMax - (randMax mod uint64(max)):
+      return int(x mod uint64(max))
 
 proc random*(max: float): float {.benign.} =
   ## Returns a random number in the range 0..<max. The sequence of
@@ -99,6 +104,11 @@ proc randomize*(seed: int) {.benign.} =
   state.a0 = ui(seed shr 16)
   state.a1 = ui(seed and 0xffff)
 
+proc shuffle*[T](x: var seq[T]) =
+  for i in countdown(x.high, 0):
+    let j = random(i + 1)
+    swap(x[i], x[j])
+
 when not defined(nimscript):
   import times