test against intx library
This commit is contained in:
parent
ea02d7db68
commit
d198ec031e
|
@ -30,11 +30,11 @@ jobs:
|
|||
shell: bash
|
||||
- target:
|
||||
os: macos
|
||||
builder: macos-11
|
||||
builder: macos-12
|
||||
shell: bash
|
||||
- target:
|
||||
os: windows
|
||||
builder: windows-2019
|
||||
builder: windows-latest
|
||||
shell: msys2 {0}
|
||||
|
||||
defaults:
|
||||
|
@ -47,22 +47,29 @@ jobs:
|
|||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set GCC 10 as default compiler (Linux)
|
||||
if: runner.os == 'Linux' && matrix.target.cpu != 'i386'
|
||||
run: |
|
||||
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 \
|
||||
--slave /usr/bin/g++ g++ /usr/bin/g++-10 \
|
||||
--slave /usr/bin/gcov gcov /usr/bin/gcov-10
|
||||
|
||||
- name: Install build dependencies (Linux i386)
|
||||
if: runner.os == 'Linux' && matrix.target.cpu == 'i386'
|
||||
run: |
|
||||
sudo dpkg --add-architecture i386
|
||||
sudo apt-fast update -qq
|
||||
sudo DEBIAN_FRONTEND='noninteractive' apt-fast install \
|
||||
--no-install-recommends -yq gcc-multilib g++-multilib \
|
||||
libssl-dev:i386
|
||||
--no-install-recommends -yq gcc-10-multilib g++-10-multilib \
|
||||
libssl-dev:i386 linux-libc-dev:i386
|
||||
mkdir -p external/bin
|
||||
cat << EOF > external/bin/gcc
|
||||
#!/bin/bash
|
||||
exec $(which gcc) -m32 "\$@"
|
||||
exec $(which gcc-10) -m32 "\$@"
|
||||
EOF
|
||||
cat << EOF > external/bin/g++
|
||||
#!/bin/bash
|
||||
exec $(which g++) -m32 "\$@"
|
||||
exec $(which g++-10) -m32 "\$@"
|
||||
EOF
|
||||
chmod 755 external/bin/gcc external/bin/g++
|
||||
echo '${{ github.workspace }}/external/bin' >> $GITHUB_PATH
|
||||
|
@ -155,6 +162,6 @@ jobs:
|
|||
nim --version
|
||||
nimble --version
|
||||
nimble install -y --depsOnly
|
||||
#nimble install -y https://github.com/alehander42/nim-quicktest ttmath
|
||||
env TEST_LANG="c" nimble test
|
||||
#env TEST_LANG="cpp" nimble test
|
||||
# run test against intx
|
||||
env TEST_LANG="cpp" nimble test
|
||||
|
|
|
@ -28,12 +28,6 @@ task test_internal, "Run tests for internal procs":
|
|||
task test_public_api, "Run all tests - prod implementation (StUint[64] = uint64":
|
||||
test "", "tests/all_tests"
|
||||
|
||||
task test_uint256_ttmath, "Run random tests Uint256 vs TTMath":
|
||||
requires "https://github.com/alehander42/nim-quicktest >= 0.18.0", "https://github.com/status-im/nim-ttmath"
|
||||
putEnv("TEST_LANG", "cpp")
|
||||
switch("define", "release")
|
||||
test "", "tests/test_uint256_ttmath"
|
||||
|
||||
task test, "Run all tests":
|
||||
exec "nimble test_internal"
|
||||
exec "nimble test_public_api"
|
||||
|
|
|
@ -38,3 +38,6 @@ import
|
|||
test_bugfix,
|
||||
test_features
|
||||
|
||||
when defined(cpp):
|
||||
import
|
||||
test_vs_intx
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,163 @@
|
|||
import strutils
|
||||
from os import DirSep
|
||||
|
||||
const intxPath = currentSourcePath.rsplit(DirSep, 1)[0]
|
||||
{.passc: "-I" & intxPath.}
|
||||
{.passc: "-std=c++20".}
|
||||
|
||||
const INTX_HEADER = intxPath & "/intx.hpp"
|
||||
|
||||
static:
|
||||
debugEcho INTX_HEADER
|
||||
|
||||
type
|
||||
UInt*[NumBits: static[int]] {.importcpp: "intx::uint<'0>", header: INTX_HEADER.} = object
|
||||
|
||||
TTInt = UInt
|
||||
|
||||
stdString {.importc: "std::string", header: "<string.h>".} = object
|
||||
|
||||
proc `+`*(a, b: TTInt): TTInt {.importcpp: "(# + #)".}
|
||||
proc `-`*(a, b: TTInt): TTInt {.importcpp: "(# - #)".}
|
||||
proc `*`*(a, b: TTInt): TTInt {.importcpp: "(# * #)".}
|
||||
proc `/`*(a, b: TTInt): TTInt {.importcpp: "(# / #)".}
|
||||
proc `div`*(a, b: TTInt): TTInt {.importcpp: "(# / #)".}
|
||||
proc `mod`*(a, b: TTInt): TTInt {.importcpp: "(# % #)".}
|
||||
|
||||
proc `==`*(a, b: TTInt): bool {.importcpp: "(# == #)".}
|
||||
proc `<`*(a, b: TTInt): bool {.importcpp: "(# < #)".}
|
||||
proc `<=`*(a, b: TTInt): bool {.importcpp: "(# <= #)".}
|
||||
|
||||
proc `+=`*(a: var TTInt, b: TTInt) {.importcpp: "# += #".}
|
||||
proc `-=`*(a: var TTInt, b: TTInt) {.importcpp: "# -= #".}
|
||||
proc `*=`*(a: var TTInt, b: TTInt) {.importcpp: "# *= #".}
|
||||
proc `/=`*(a: var TTInt, b: TTInt) {.importcpp: "# /= #".}
|
||||
|
||||
proc `and`*(a, b: TTInt): TTInt {.importcpp: "(# & #)".}
|
||||
proc `or`*(a, b: TTInt): TTInt {.importcpp: "(# | #)".}
|
||||
proc `xor`*(a, b: TTInt): TTInt {.importcpp: "(# ^ #)".}
|
||||
|
||||
proc `|=`*(a: var TTInt, b: TTInt) {.importcpp: "(# |= #)".}
|
||||
proc `&=`*(a: var TTInt, b: TTInt) {.importcpp: "(# &= #)".}
|
||||
proc `^=`*(a: var TTInt, b: TTInt) {.importcpp: "(# ^= #)".}
|
||||
|
||||
proc `shl`*(a: UInt, b: uint64): UInt {.importcpp: "(# << #)".}
|
||||
proc `shr`*(a: UInt, b: uint64): UInt {.importcpp: "(# >> #)".}
|
||||
proc pow*(a, b: TTInt): TTInt {.importcpp: "exp(#,#)".}
|
||||
|
||||
proc ToString(a: TTInt, base: cint): stdString {.importcpp: "to_string", header: INTX_HEADER.}
|
||||
proc toString*(a: TTInt, base: int = 10): string =
|
||||
let tmp = a.ToString(cint(base))
|
||||
var tmps: cstring
|
||||
{.emit: """
|
||||
`tmps` = const_cast<char*>(`tmp`.c_str());
|
||||
""".}
|
||||
result = $tmps
|
||||
|
||||
proc `$`*(a: TTInt): string {.inline.} = a.toString()
|
||||
proc initUInt[T](a: uint64): T {.importcpp: "'0{#}".}
|
||||
|
||||
proc pow*(a: UInt, b: uint64): UInt =
|
||||
pow(a, initUInt[UInt](b))
|
||||
|
||||
#[
|
||||
proc FromString(a: var TTInt, s: cstring, base: uint) {.importcpp, header: INTX_HEADER.}
|
||||
proc fromString*(a: var TTInt, s: cstring, base: int = 10) = a.FromString(s, uint(base))
|
||||
proc fromHex*(a: var TTInt, s: string) {.inline.} = a.fromString(s, 16)
|
||||
|
||||
proc initInt[T](a: int64): T {.importcpp: "'0((int)#)".}
|
||||
|
||||
proc initInt[T](a: cstring): T {.importcpp: "'0(#)".}
|
||||
|
||||
template defineIntConstructor(typ: typedesc, name: untyped{nkIdent}) =
|
||||
template name*(a: int64): typ = initInt[typ](a)
|
||||
template name*(a: cstring): typ = initInt[typ](a)
|
||||
template `+`*(a: typ, b: int): typ = a + initInt[typ](b)
|
||||
template `+`*(a: int, b: typ): typ = initInt[typ](a) + b
|
||||
template `-`*(a: typ, b: int): typ = a - initInt[typ](b)
|
||||
template `-`*(a: int, b: typ): typ = initInt[typ](a) - b
|
||||
template `+=`*(a: var typ, b: int) = a += initInt[typ](b)
|
||||
template `-=`*(a: var typ, b: int) = a -= initInt[typ](b)
|
||||
|
||||
defineIntConstructor(Int256, i256)
|
||||
defineIntConstructor(Int512, i512)
|
||||
defineIntConstructor(Int1024, i1024)
|
||||
defineIntConstructor(Int2048, i2048)
|
||||
|
||||
template defineUIntConstructor(typ: typedesc, name: untyped{nkIdent}) =
|
||||
template name*(a: uint64): typ = initUInt[typ](a)
|
||||
template name*(a: cstring): typ = initInt[typ](a)
|
||||
template `+`*(a: typ, b: int): typ = a + initUInt[typ](b)
|
||||
template `+`*(a: int, b: typ): typ = initUInt[typ](a) + b
|
||||
template `-`*(a: typ, b: int): typ = a - initUInt[typ](b)
|
||||
template `-`*(a: int, b: typ): typ = initUInt[typ](a) - b
|
||||
template `+=`*(a: var typ, b: uint) = a += initUInt[typ](b)
|
||||
template `-=`*(a: var typ, b: uint) = a -= initUInt[typ](b)
|
||||
|
||||
defineUIntConstructor(UInt256, u256)
|
||||
defineUIntConstructor(UInt512, u512)
|
||||
defineUIntConstructor(UInt1024, u1024)
|
||||
defineUIntConstructor(UInt2048, u2048)
|
||||
|
||||
proc `-`*(a: Int): Int {.importcpp: "(- #)".}
|
||||
|
||||
proc pow*(a: Int, b: int): Int =
|
||||
var tmp = a
|
||||
tmp.inplacePow(initInt[Int](b))
|
||||
result = tmp
|
||||
|
||||
proc pow*(a: UInt, b: uint64): UInt =
|
||||
var tmp = a
|
||||
tmp.inplacePow(initUInt[UInt](b))
|
||||
result = tmp
|
||||
|
||||
proc `shl`*(a: Int, b: int): Int {.importcpp: "(# << #)".}
|
||||
proc `shr`*(a: Int, b: int): Int {.importcpp: "(# >> #)".}
|
||||
|
||||
|
||||
proc getInt*(a: Int): int {.importcpp: "ToInt", header: INTX_HEADER.}
|
||||
proc getUInt*(a: UInt): uint64 {.importcpp: "ToUInt", header: INTX_HEADER.}
|
||||
|
||||
proc setZero*(a: var TTInt) {.importcpp: "SetZero", header: INTX_HEADER.}
|
||||
proc setOne*(a: var TTInt) {.importcpp: "SetOne", header: INTX_HEADER.}
|
||||
proc setMin*(a: var TTInt) {.importcpp: "SetMin", header: INTX_HEADER.}
|
||||
proc setMax*(a: var TTInt) {.importcpp: "SetMax", header: INTX_HEADER.}
|
||||
proc clearFirstBits*(a: var TTInt, n: uint) {.importcpp: "ClearFirstBits", header: INTX_HEADER.}
|
||||
|
||||
template max*[T: TTInt]: TTInt =
|
||||
var r = initInt[T](0)
|
||||
r.setMax()
|
||||
r
|
||||
|
||||
|
||||
|
||||
proc hexToUInt*[N](hexStr: string): UInt[N] {.inline.} = result.fromHex(hexStr)
|
||||
proc toHex*(a: TTInt): string {.inline.} = a.toString(16)
|
||||
|
||||
proc toByteArrayBE*[N](num: UInt[N]): array[N div 8, byte] {.noSideEffect, noinit, inline.} =
|
||||
## Convert a TTInt (in native host endianness) to a big-endian byte array
|
||||
const N = result.len
|
||||
for i in 0 ..< N:
|
||||
{.unroll: 4.}
|
||||
result[i] = byte getUInt(num shr uint((N-1-i) * 8))
|
||||
|
||||
proc readUIntBE*[N](ba: openArray[byte]): UInt[N] {.noSideEffect, inline.} =
|
||||
## Convert a big-endian array of Bytes to an UInt256 (in native host endianness)
|
||||
const sz = N div 8
|
||||
assert(ba.len >= sz)
|
||||
for i in 0 ..< sz:
|
||||
{.unroll: 4.}
|
||||
result = result shl 8 or initUInt[UInt[N]](ba[i])
|
||||
|
||||
proc inc*(a: var TTInt, n = 1) {.inline.} =
|
||||
when a is Int:
|
||||
a += initInt[type a](n)
|
||||
else:
|
||||
a += initUInt[type a](n.uint)
|
||||
|
||||
proc dec*(a: var TTInt, n = 1) {.inline.} =
|
||||
when a is Int:
|
||||
a -= initInt[type a](n)
|
||||
else:
|
||||
a -= initUInt[type a](n.uint)
|
||||
]#
|
|
@ -0,0 +1,18 @@
|
|||
import
|
||||
../../stint,
|
||||
./intx
|
||||
|
||||
export intx
|
||||
|
||||
template asSt*(val: UInt): auto =
|
||||
type TargetType = StUint[val.NumBits]
|
||||
cast[ptr TargetType](unsafeAddr val)[]
|
||||
|
||||
template asTT*[N: static[int]](arr: array[N, uint64]): auto =
|
||||
type TargetType = UInt[N * 64]
|
||||
cast[ptr TargetType](unsafeAddr arr[0])[]
|
||||
|
||||
template asTT*(x: StUint): auto =
|
||||
type TargetType = UInt[x.bits]
|
||||
var arr = x.toBytes(cpuEndian)
|
||||
cast[ptr TargetType](addr arr[0])[]
|
|
@ -1,337 +0,0 @@
|
|||
# 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.
|
||||
|
||||
|
||||
# Requires "https://github.com/status-im/nim-ttmath#master"
|
||||
# Note that currently importing both Stint and TTMath will crash the compiler for unknown reason
|
||||
import ../stint, unittest, quicktest, ttmath_compat
|
||||
|
||||
const itercount = 10_000
|
||||
|
||||
suite "Property-based testing (testing with random inputs) of Uint256":
|
||||
|
||||
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)"
|
||||
|
||||
let hi = 1'u shl (sizeof(uint64)*7)
|
||||
|
||||
quicktest "`or`", itercount do(x0: uint64(min=0, max=hi),
|
||||
x1: uint64(min=0, max=hi),
|
||||
x2: uint64(min=0, max=hi),
|
||||
x3: uint64(min=0, max=hi),
|
||||
y0: uint64(min=0, max=hi),
|
||||
y1: uint64(min=0, max=hi),
|
||||
y2: uint64(min=0, max=hi),
|
||||
y3: uint64(min=0, max=hi)):
|
||||
|
||||
let
|
||||
x = [x0, x1, x2, x3]
|
||||
y = [y0, y1, y2, y3]
|
||||
|
||||
ttm_x = x.asTT
|
||||
ttm_y = y.asTT
|
||||
mp_x = cast[StUint[256]](x)
|
||||
mp_y = cast[StUint[256]](y)
|
||||
|
||||
let
|
||||
ttm_z = ttm_x or ttm_y
|
||||
mp_z = mp_x or mp_y
|
||||
|
||||
check ttm_z.asSt == mp_z
|
||||
|
||||
quicktest "`and`", itercount do(x0: uint64(min=0, max=hi),
|
||||
x1: uint64(min=0, max=hi),
|
||||
x2: uint64(min=0, max=hi),
|
||||
x3: uint64(min=0, max=hi),
|
||||
y0: uint64(min=0, max=hi),
|
||||
y1: uint64(min=0, max=hi),
|
||||
y2: uint64(min=0, max=hi),
|
||||
y3: uint64(min=0, max=hi)):
|
||||
|
||||
let
|
||||
x = [x0, x1, x2, x3]
|
||||
y = [y0, y1, y2, y3]
|
||||
|
||||
ttm_x = x.asTT
|
||||
ttm_y = y.asTT
|
||||
mp_x = cast[StUint[256]](x)
|
||||
mp_y = cast[StUint[256]](y)
|
||||
|
||||
let
|
||||
ttm_z = ttm_x and ttm_y
|
||||
mp_z = mp_x and mp_y
|
||||
|
||||
check ttm_z.asSt == mp_z
|
||||
|
||||
quicktest "`xor`", itercount do(x0: uint64(min=0, max=hi),
|
||||
x1: uint64(min=0, max=hi),
|
||||
x2: uint64(min=0, max=hi),
|
||||
x3: uint64(min=0, max=hi),
|
||||
y0: uint64(min=0, max=hi),
|
||||
y1: uint64(min=0, max=hi),
|
||||
y2: uint64(min=0, max=hi),
|
||||
y3: uint64(min=0, max=hi)):
|
||||
|
||||
let
|
||||
x = [x0, x1, x2, x3]
|
||||
y = [y0, y1, y2, y3]
|
||||
|
||||
ttm_x = x.asTT
|
||||
ttm_y = y.asTT
|
||||
mp_x = cast[StUint[256]](x)
|
||||
mp_y = cast[StUint[256]](y)
|
||||
|
||||
let
|
||||
ttm_z = ttm_x xor ttm_y
|
||||
mp_z = mp_x xor mp_y
|
||||
|
||||
check ttm_z.asSt == mp_z
|
||||
|
||||
# Not defined for ttmath
|
||||
# quicktest "`not`", itercount do(x0: uint64(min=0, max=hi),
|
||||
# x1: uint64(min=0, max=hi),
|
||||
# x2: uint64(min=0, max=hi),
|
||||
# x3: uint64(min=0, max=hi):
|
||||
|
||||
# let
|
||||
# x = [x0, x1, x2, x3]
|
||||
# y = [y0, y1, y2, y3]
|
||||
|
||||
# ttm_x = cast[ttmath.UInt256](x)
|
||||
# mp_x = cast[StUint[256]](x)
|
||||
|
||||
# let
|
||||
# ttm_z = not ttm_x
|
||||
# mp_z = not mp_x
|
||||
|
||||
# check(cast[array[4, uint64]](ttm_z) == cast[array[4, uint64]](mp_z))
|
||||
|
||||
quicktest "`<`", itercount do(x0: uint64(min=0, max=hi),
|
||||
x1: uint64(min=0, max=hi),
|
||||
x2: uint64(min=0, max=hi),
|
||||
x3: uint64(min=0, max=hi),
|
||||
y0: uint64(min=0, max=hi),
|
||||
y1: uint64(min=0, max=hi),
|
||||
y2: uint64(min=0, max=hi),
|
||||
y3: uint64(min=0, max=hi)):
|
||||
|
||||
let
|
||||
x = [x0, x1, x2, x3]
|
||||
y = [y0, y1, y2, y3]
|
||||
|
||||
ttm_x = x.asTT
|
||||
ttm_y = y.asTT
|
||||
mp_x = cast[StUint[256]](x)
|
||||
mp_y = cast[StUint[256]](y)
|
||||
|
||||
let
|
||||
ttm_z = ttm_x < ttm_y
|
||||
mp_z = mp_x < mp_y
|
||||
|
||||
check(ttm_z == mp_z)
|
||||
|
||||
|
||||
quicktest "`<=`", itercount do(x0: uint64(min=0, max=hi),
|
||||
x1: uint64(min=0, max=hi),
|
||||
x2: uint64(min=0, max=hi),
|
||||
x3: uint64(min=0, max=hi),
|
||||
y0: uint64(min=0, max=hi),
|
||||
y1: uint64(min=0, max=hi),
|
||||
y2: uint64(min=0, max=hi),
|
||||
y3: uint64(min=0, max=hi)):
|
||||
|
||||
let
|
||||
x = [x0, x1, x2, x3]
|
||||
y = [y0, y1, y2, y3]
|
||||
|
||||
ttm_x = x.asTT
|
||||
ttm_y = y.asTT
|
||||
mp_x = cast[StUint[256]](x)
|
||||
mp_y = cast[StUint[256]](y)
|
||||
|
||||
let
|
||||
ttm_z = ttm_x <= ttm_y
|
||||
mp_z = mp_x <= mp_y
|
||||
|
||||
check(ttm_z == mp_z)
|
||||
|
||||
quicktest "`+`", itercount do(x0: uint64(min=0, max=hi),
|
||||
x1: uint64(min=0, max=hi),
|
||||
x2: uint64(min=0, max=hi),
|
||||
x3: uint64(min=0, max=hi),
|
||||
y0: uint64(min=0, max=hi),
|
||||
y1: uint64(min=0, max=hi),
|
||||
y2: uint64(min=0, max=hi),
|
||||
y3: uint64(min=0, max=hi)):
|
||||
|
||||
let
|
||||
x = [x0, x1, x2, x3]
|
||||
y = [y0, y1, y2, y3]
|
||||
|
||||
ttm_x = x.asTT
|
||||
ttm_y = y.asTT
|
||||
mp_x = cast[StUint[256]](x)
|
||||
mp_y = cast[StUint[256]](y)
|
||||
|
||||
let
|
||||
ttm_z = ttm_x + ttm_y
|
||||
mp_z = mp_x + mp_y
|
||||
|
||||
check ttm_z.asSt == mp_z
|
||||
|
||||
quicktest "`-`", itercount do(x0: uint64(min=0, max=hi),
|
||||
x1: uint64(min=0, max=hi),
|
||||
x2: uint64(min=0, max=hi),
|
||||
x3: uint64(min=0, max=hi),
|
||||
y0: uint64(min=0, max=hi),
|
||||
y1: uint64(min=0, max=hi),
|
||||
y2: uint64(min=0, max=hi),
|
||||
y3: uint64(min=0, max=hi)):
|
||||
|
||||
let
|
||||
x = [x0, x1, x2, x3]
|
||||
y = [y0, y1, y2, y3]
|
||||
|
||||
ttm_x = x.asTT
|
||||
ttm_y = y.asTT
|
||||
mp_x = cast[StUint[256]](x)
|
||||
mp_y = cast[StUint[256]](y)
|
||||
|
||||
let
|
||||
ttm_z = ttm_x - ttm_y
|
||||
mp_z = mp_x - mp_y
|
||||
|
||||
check ttm_z.asSt == mp_z
|
||||
|
||||
quicktest "`*`", itercount do(x0: uint64(min=0, max=hi),
|
||||
x1: uint64(min=0, max=hi),
|
||||
x2: uint64(min=0, max=hi),
|
||||
x3: uint64(min=0, max=hi),
|
||||
y0: uint64(min=0, max=hi),
|
||||
y1: uint64(min=0, max=hi),
|
||||
y2: uint64(min=0, max=hi),
|
||||
y3: uint64(min=0, max=hi)):
|
||||
|
||||
let
|
||||
x = [x0, x1, x2, x3]
|
||||
y = [y0, y1, y2, y3]
|
||||
|
||||
ttm_x = x.asTT
|
||||
ttm_y = y.asTT
|
||||
mp_x = cast[StUint[256]](x)
|
||||
mp_y = cast[StUint[256]](y)
|
||||
|
||||
let
|
||||
ttm_z = ttm_x * ttm_y
|
||||
mp_z = mp_x * mp_y
|
||||
|
||||
check ttm_z.asSt == mp_z
|
||||
|
||||
quicktest "`shl`", itercount do(x0: uint64(min=0, max=hi),
|
||||
x1: uint64(min=0, max=hi),
|
||||
x2: uint64(min=0, max=hi),
|
||||
x3: uint64(min=0, max=hi),
|
||||
y: int(min = 0, max=(255))):
|
||||
|
||||
let
|
||||
x = [x0, x1, x2, x3]
|
||||
|
||||
ttm_x = x.asTT
|
||||
mp_x = cast[StUint[256]](x)
|
||||
|
||||
let
|
||||
ttm_z = ttm_x shl y.uint
|
||||
mp_z = mp_x shl y
|
||||
|
||||
check ttm_z.asSt == mp_z
|
||||
|
||||
quicktest "`shr`", itercount do(x0: uint64(min=0, max=hi),
|
||||
x1: uint64(min=0, max=hi),
|
||||
x2: uint64(min=0, max=hi),
|
||||
x3: uint64(min=0, max=hi),
|
||||
y: int(min = 0, max=(255))):
|
||||
|
||||
let
|
||||
x = [x0, x1, x2, x3]
|
||||
|
||||
ttm_x = x.asTT
|
||||
mp_x = cast[StUint[256]](x)
|
||||
|
||||
let
|
||||
ttm_z = ttm_x shr y.uint
|
||||
mp_z = mp_x shr y
|
||||
|
||||
check ttm_z.asSt == mp_z
|
||||
|
||||
quicktest "`mod`", itercount do(x0: uint64(min=0, max=hi),
|
||||
x1: uint64(min=0, max=hi),
|
||||
x2: uint64(min=0, max=hi),
|
||||
x3: uint64(min=0, max=hi),
|
||||
y0: uint64(min=0, max=hi),
|
||||
y1: uint64(min=0, max=hi),
|
||||
y2: uint64(min=0, max=hi),
|
||||
y3: uint64(min=0, max=hi)):
|
||||
|
||||
let
|
||||
x = [x0, x1, x2, x3]
|
||||
y = [y0, y1, y2, y3]
|
||||
|
||||
ttm_x = x.asTT
|
||||
ttm_y = y.asTT
|
||||
mp_x = cast[StUint[256]](x)
|
||||
mp_y = cast[StUint[256]](y)
|
||||
|
||||
let
|
||||
ttm_z = ttm_x mod ttm_y
|
||||
mp_z = mp_x mod mp_y
|
||||
|
||||
check ttm_z.asSt == mp_z
|
||||
|
||||
quicktest "`div`", itercount do(x0: uint64(min=0, max=hi),
|
||||
x1: uint64(min=0, max=hi),
|
||||
x2: uint64(min=0, max=hi),
|
||||
x3: uint64(min=0, max=hi),
|
||||
y0: uint64(min=0, max=hi),
|
||||
y1: uint64(min=0, max=hi),
|
||||
y2: uint64(min=0, max=hi),
|
||||
y3: uint64(min=0, max=hi)):
|
||||
|
||||
let
|
||||
x = [x0, x1, x2, x3]
|
||||
y = [y0, y1, y2, y3]
|
||||
|
||||
ttm_x = x.asTT
|
||||
ttm_y = y.asTT
|
||||
mp_x = cast[StUint[256]](x)
|
||||
mp_y = cast[StUint[256]](y)
|
||||
|
||||
let
|
||||
ttm_z = ttm_x div ttm_y
|
||||
mp_z = mp_x div mp_y
|
||||
|
||||
check ttm_z.asSt == mp_z
|
||||
|
||||
quicktest "pow", itercount do(x0: uint64(min=0, max=hi),
|
||||
x1: uint64(min=0, max=hi),
|
||||
x2: uint64(min=0, max=hi),
|
||||
x3: uint64(min=0, max=hi),
|
||||
y : int(min=0, max=high(int))):
|
||||
|
||||
let
|
||||
x = [x0, x1, x2, x3]
|
||||
ttm_x = x.asTT
|
||||
mp_x = cast[StUint[256]](x)
|
||||
|
||||
let
|
||||
ttm_z = ttm_x.pow(y.uint)
|
||||
mp_z = mp_x.pow y
|
||||
|
||||
check ttm_z.asSt == mp_z
|
|
@ -0,0 +1,155 @@
|
|||
# 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
|
|
@ -1,19 +0,0 @@
|
|||
import ../stint, ttmath/ttmath
|
||||
export ttmath
|
||||
|
||||
template asSt*(val: UInt): auto =
|
||||
type TargetType = StUint[val.NumBits]
|
||||
cast[ptr TargetType](unsafeAddr val)[]
|
||||
|
||||
template asSt*(val: Int): auto =
|
||||
type TargetType = StInt[val.NumBits]
|
||||
cast[ptr TargetType](unsafeAddr val)[]
|
||||
|
||||
template asTT*[N: static[int]](arr: array[N, uint64]): auto =
|
||||
type TargetType = UInt[N * 64]
|
||||
cast[ptr TargetType](unsafeAddr arr[0])[]
|
||||
|
||||
template asTT*[N: static[int]](arr: array[N, int64]): auto =
|
||||
type TargetType = Int[N * 64]
|
||||
cast[ptr TargetType](unsafeAddr arr[0])[]
|
||||
|
Loading…
Reference in New Issue