test against intx library
This commit is contained in:
parent
ea02d7db68
commit
d198ec031e
|
@ -30,11 +30,11 @@ jobs:
|
||||||
shell: bash
|
shell: bash
|
||||||
- target:
|
- target:
|
||||||
os: macos
|
os: macos
|
||||||
builder: macos-11
|
builder: macos-12
|
||||||
shell: bash
|
shell: bash
|
||||||
- target:
|
- target:
|
||||||
os: windows
|
os: windows
|
||||||
builder: windows-2019
|
builder: windows-latest
|
||||||
shell: msys2 {0}
|
shell: msys2 {0}
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
|
@ -47,22 +47,29 @@ jobs:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
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)
|
- name: Install build dependencies (Linux i386)
|
||||||
if: runner.os == 'Linux' && matrix.target.cpu == 'i386'
|
if: runner.os == 'Linux' && matrix.target.cpu == 'i386'
|
||||||
run: |
|
run: |
|
||||||
sudo dpkg --add-architecture i386
|
sudo dpkg --add-architecture i386
|
||||||
sudo apt-fast update -qq
|
sudo apt-fast update -qq
|
||||||
sudo DEBIAN_FRONTEND='noninteractive' apt-fast install \
|
sudo DEBIAN_FRONTEND='noninteractive' apt-fast install \
|
||||||
--no-install-recommends -yq gcc-multilib g++-multilib \
|
--no-install-recommends -yq gcc-10-multilib g++-10-multilib \
|
||||||
libssl-dev:i386
|
libssl-dev:i386 linux-libc-dev:i386
|
||||||
mkdir -p external/bin
|
mkdir -p external/bin
|
||||||
cat << EOF > external/bin/gcc
|
cat << EOF > external/bin/gcc
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
exec $(which gcc) -m32 "\$@"
|
exec $(which gcc-10) -m32 "\$@"
|
||||||
EOF
|
EOF
|
||||||
cat << EOF > external/bin/g++
|
cat << EOF > external/bin/g++
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
exec $(which g++) -m32 "\$@"
|
exec $(which g++-10) -m32 "\$@"
|
||||||
EOF
|
EOF
|
||||||
chmod 755 external/bin/gcc external/bin/g++
|
chmod 755 external/bin/gcc external/bin/g++
|
||||||
echo '${{ github.workspace }}/external/bin' >> $GITHUB_PATH
|
echo '${{ github.workspace }}/external/bin' >> $GITHUB_PATH
|
||||||
|
@ -155,6 +162,6 @@ jobs:
|
||||||
nim --version
|
nim --version
|
||||||
nimble --version
|
nimble --version
|
||||||
nimble install -y --depsOnly
|
nimble install -y --depsOnly
|
||||||
#nimble install -y https://github.com/alehander42/nim-quicktest ttmath
|
|
||||||
env TEST_LANG="c" nimble test
|
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":
|
task test_public_api, "Run all tests - prod implementation (StUint[64] = uint64":
|
||||||
test "", "tests/all_tests"
|
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":
|
task test, "Run all tests":
|
||||||
exec "nimble test_internal"
|
exec "nimble test_internal"
|
||||||
exec "nimble test_public_api"
|
exec "nimble test_public_api"
|
||||||
|
|
|
@ -38,3 +38,6 @@ import
|
||||||
test_bugfix,
|
test_bugfix,
|
||||||
test_features
|
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