diff options
-rwxr-xr-x | lib/pure/math.nim | 47 | ||||
-rw-r--r-- | tests/run/tmath.nim | 49 |
2 files changed, 82 insertions, 14 deletions
diff --git a/lib/pure/math.nim b/lib/pure/math.nim index 587671165..8a894e080 100755 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -123,17 +123,22 @@ proc variance*(x: openarray[float]): float {.noSideEffect.} = result = result + diff*diff result = result / toFloat(len(x)) -when not defined(ECMAScript): - proc random*(max: int): int - ## returns a random number in the range 0..max-1. The sequence of - ## random number is always the same, unless `randomize` is called - ## which initializes the random number generator with a "random" - ## number, i.e. a tickcount. - proc randomize*() - ## initializes the random number generator with a "random" - ## number, i.e. a tickcount. Note: Does nothing for the ECMAScript target, - ## as ECMAScript does not support this. +proc random*(max: int): int + ## returns a random number in the range 0..max-1. The sequence of + ## random number is always the same, unless `randomize` is called + ## which initializes the random number generator with a "random" + ## number, i.e. a tickcount. +proc random*(max: float): float + ## returns a random number in the range 0..<max. The sequence of + ## random number is always the same, unless `randomize` is called + ## which initializes the random number generator with a "random" + ## number, i.e. a tickcount. +proc randomize*() + ## initializes the random number generator with a "random" + ## number, i.e. a tickcount. Note: Does nothing for the ECMAScript target, + ## as ECMAScript does not support this. +when not defined(ECMAScript): proc sqrt*(x: float): float {.importc: "sqrt", header: "<math.h>".} ## computes the square root of `x`. @@ -179,10 +184,18 @@ when not defined(ECMAScript): # C procs: proc gettime(dummy: ptr cint): cint {.importc: "time", header: "<time.h>".} proc srand(seed: cint) {.importc: "srand", nodecl.} + proc srand48(seed: cint) {.importc: "srand48", nodecl.} proc rand(): cint {.importc: "rand", nodecl.} + proc drand48(): float {.importc: "drand48", nodecl.} - proc randomize() = srand(gettime(nil)) - proc random(max: int): int = return int(rand()) mod max + proc randomize() = + let x = gettime(nil) + srand(x) + srand48(x) + proc random(max: int): int = + result = int(rand()) mod max + proc random(max: float): float = + result = drand48() * max proc trunc*(x: float): float {.importc: "trunc", nodecl.} proc floor*(x: float): float {.importc: "floor", nodecl.} @@ -194,8 +207,11 @@ else: proc mathrandom(): float {.importc: "Math.random", nodecl.} proc floor*(x: float): float {.importc: "Math.floor", nodecl.} proc ceil*(x: float): float {.importc: "Math.ceil", nodecl.} - proc random*(max: int): int = return int(floor(mathrandom() * float(max))) - proc randomize*() = nil + proc random(max: int): int = + result = int(floor(mathrandom() * float(max))) + proc random(max: float): float = + result = float(mathrandom() * float(max)) + proc randomize() = nil proc sqrt*(x: float): float {.importc: "Math.sqrt", nodecl.} proc ln*(x: float): float {.importc: "Math.log", nodecl.} @@ -235,6 +251,9 @@ else: proc `mod`*(x, y: float): float = result = if y == 0.0: x else: x - y * (x/y).floor +proc random*[T](x: TSlice[T]): T = + result = random(x.b - x.a) + x.a + type TRunningStat* {.pure,final.} = object ## an accumulator for statistical data n*: int ## number of pushed data diff --git a/tests/run/tmath.nim b/tests/run/tmath.nim new file mode 100644 index 000000000..65124306e --- /dev/null +++ b/tests/run/tmath.nim @@ -0,0 +1,49 @@ +import math +import unittest +import sets + +suite "random int": + test "there might be some randomness": + var set = initSet[int](128) + randomize() + for i in 1..1000: + incl(set, random(high(int))) + check len(set) == 1000 + test "single number bounds work": + randomize() + var rand: int + for i in 1..1000: + rand = random(1000) + check rand < 1000 + check rand > -1 + test "slice bounds work": + randomize() + var rand: int + for i in 1..1000: + rand = random(100..1000) + check rand < 1000 + check rand >= 100 + +suite "random float": + # Enable this once #197 has been resolved + # test "there might be some randomness": + # var set = initSet[float](128) + # for i in 1..10: + # for j in 1..10: + # randomize() + # incl(set, random(1.0)) + # check len(set) == 100 + test "single number bounds work": + randomize() + var rand: float + for i in 1..1000: + rand = random(1000.0) + check rand < 1000.0 + check rand > -1.0 + test "slice bounds work": + randomize() + var rand: float + for i in 1..1000: + rand = random(100.0..1000.0) + check rand < 1000.0 + check rand >= 100.0 |