156 lines
3.7 KiB
Nim
156 lines
3.7 KiB
Nim
# Stint
|
|
# Copyright 2018 Status Research & Development GmbH
|
|
# Licensed under either of
|
|
#
|
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
|
#
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
import
|
|
std/[times, random],
|
|
unittest,
|
|
./intx/intx_compat,
|
|
../stint,
|
|
../helpers/prng_unsafe
|
|
|
|
const
|
|
itercount = 10_000
|
|
|
|
let seed = uint32(getTime().toUnix() and (1'i64 shl 32 - 1)) # unixTime mod 2^32
|
|
var rng: RngState
|
|
rng.seed(seed)
|
|
|
|
template testLoopImpl(bits: static int, name: string, gen: RandomGen, body: untyped) =
|
|
test name & " " & $gen & " " & $bits & " bits":
|
|
for _ in 0 ..< itercount:
|
|
let
|
|
mp_x {.inject.} = rng.random_elem(StUint[bits], gen)
|
|
mp_y {.inject.} = rng.random_elem(StUint[bits], gen)
|
|
ttm_x {.inject.} = asTT(mp_x)
|
|
ttm_y {.inject.} = asTT(mp_y)
|
|
|
|
body
|
|
|
|
template testLoop(bits: static int, name: string, body: untyped) =
|
|
testLoopImpl(bits, name, Long01Sequence, body)
|
|
testLoopImpl(bits, name, HighHammingWeight, body)
|
|
testLoopImpl(bits, name, Uniform, body)
|
|
|
|
template testYImpl(bits: static int, name: string, gen: RandomGen, maxY: uint64, body: untyped) =
|
|
test name & " " & $gen & " " & $bits & " bits":
|
|
var xrng = initRand()
|
|
for _ in 0 ..< itercount:
|
|
let
|
|
mp_x {.inject.} = rng.random_elem(StUint[bits], gen)
|
|
ttm_x {.inject.} = asTT(mp_x)
|
|
y {.inject.} = xrng.rand(maxY)
|
|
|
|
body
|
|
|
|
template testY(bits: static int, name: string, maxY: uint64, body: untyped) =
|
|
testYImpl(bits, name, Long01Sequence, maxY, body)
|
|
testYImpl(bits, name, HighHammingWeight, maxY, body)
|
|
testYImpl(bits, name, Uniform, maxY, body)
|
|
|
|
suite "Property-based testing (testing with random inputs) of UInt":
|
|
|
|
when defined(release):
|
|
echo "Testing in release mode with " & $itercount & " random tests for each proc."
|
|
else:
|
|
echo "Testing in debug mode " & $itercount & " random tests for each proc. (StUint[64] = 2x uint32)"
|
|
|
|
testLoop(256, "`or`"):
|
|
let
|
|
ttm_z = ttm_x or ttm_y
|
|
mp_z = mp_x or mp_y
|
|
|
|
check ttm_z.asSt == mp_z
|
|
|
|
testLoop(256, "`and`"):
|
|
let
|
|
ttm_z = ttm_x and ttm_y
|
|
mp_z = mp_x and mp_y
|
|
|
|
check ttm_z.asSt == mp_z
|
|
|
|
testLoop(256, "`xor`"):
|
|
let
|
|
ttm_z = ttm_x xor ttm_y
|
|
mp_z = mp_x xor mp_y
|
|
|
|
check ttm_z.asSt == mp_z
|
|
|
|
testLoop(256, "`<`"):
|
|
let
|
|
ttm_z = ttm_x < ttm_y
|
|
mp_z = mp_x < mp_y
|
|
|
|
check(ttm_z == mp_z)
|
|
|
|
testLoop(256, "`<=`"):
|
|
let
|
|
ttm_z = ttm_x <= ttm_y
|
|
mp_z = mp_x <= mp_y
|
|
|
|
check(ttm_z == mp_z)
|
|
|
|
testLoop(256, "`+`"):
|
|
let
|
|
ttm_z = ttm_x + ttm_y
|
|
mp_z = mp_x + mp_y
|
|
|
|
check ttm_z.asSt == mp_z
|
|
|
|
testLoop(256, "`-`"):
|
|
let
|
|
ttm_z = ttm_x - ttm_y
|
|
mp_z = mp_x - mp_y
|
|
|
|
check ttm_z.asSt == mp_z
|
|
|
|
testLoop(256, "`*`"):
|
|
let
|
|
ttm_z = ttm_x * ttm_y
|
|
mp_z = mp_x * mp_y
|
|
|
|
check ttm_z.asSt == mp_z
|
|
|
|
testLoop(256, "`div`"):
|
|
if not mp_y.isZero:
|
|
let
|
|
ttm_z = ttm_x div ttm_y
|
|
mp_z = mp_x div mp_y
|
|
|
|
check ttm_z.asSt == mp_z
|
|
|
|
testLoop(256, "`mod`"):
|
|
if not mp_y.isZero:
|
|
let
|
|
ttm_z = ttm_x mod ttm_y
|
|
mp_z = mp_x mod mp_y
|
|
|
|
check ttm_z.asSt == mp_z
|
|
|
|
testY(256, "`pow`", high(int).uint64):
|
|
let
|
|
ttm_z = ttm_x.pow y.uint64
|
|
mp_z = mp_x.pow y
|
|
|
|
check ttm_z.asSt == mp_z
|
|
|
|
testY(256, "`shl`", 255'u64):
|
|
let
|
|
ttm_z = ttm_x shl y.uint
|
|
mp_z = mp_x shl y
|
|
|
|
check ttm_z.asSt == mp_z
|
|
|
|
testY(256, "`shr`", 255'u64):
|
|
|
|
let
|
|
ttm_z = ttm_x shr y.uint
|
|
mp_z = mp_x shr y
|
|
|
|
check ttm_z.asSt == mp_z
|