cleanup some code

This commit is contained in:
jangko 2023-06-14 08:06:44 +07:00
parent 8ea95078f4
commit 1657d841e7
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
7 changed files with 102 additions and 306 deletions

View File

@ -26,7 +26,7 @@ func u256*(n: SomeInteger): UInt256 {.inline.} = n.stuint(256)
func u256*(s: string): UInt256 {.inline.} = s.parse(UInt256) func u256*(s: string): UInt256 {.inline.} = s.parse(UInt256)
func i128*(n: SomeInteger): Int128 {.inline.} = n.stint(128) func i128*(n: SomeInteger): Int128 {.inline.} = n.stint(128)
# func i128*(s: string): Int128 {.inline.} = s.parse(Int128) func i128*(s: string): Int128 {.inline.} = s.parse(Int128)
func i256*(n: SomeInteger): Int256 {.inline.} = n.stint(256) func i256*(n: SomeInteger): Int256 {.inline.} = n.stint(256)
# func i256*(s: string): Int256 {.inline.} = s.parse(Int256) func i256*(s: string): Int256 {.inline.} = s.parse(Int256)

View File

@ -25,6 +25,8 @@ const
{.push raises: [], inline, noinit, gcsafe.} {.push raises: [], inline, noinit, gcsafe.}
func sign*(a: StInt): int = func sign*(a: StInt): int =
## get the sign of `a`
## either -1, 0, or 1
if a.imp.isZero: return 0 if a.imp.isZero: return 0
if a.limbs[^1] < signMask: 1 if a.limbs[^1] < signMask: 1
else: -1 else: -1
@ -39,10 +41,12 @@ func setMSB(a: var StInt) =
a.limbs[^1] = a.limbs[^1] or signMask a.limbs[^1] = a.limbs[^1] or signMask
func negate*(a: var StInt) = func negate*(a: var StInt) =
## two complement negation
a.imp.bitnot(a.imp) a.imp.bitnot(a.imp)
a.imp.inc a.imp.inc
func neg*(a: StInt): StInt = func neg*(a: StInt): StInt =
## two complement negation
result.imp.bitnot(a.imp) result.imp.bitnot(a.imp)
result.imp.inc result.imp.inc
@ -53,6 +57,7 @@ func abs*(a: StInt): StInt =
a a
func `-`*(a: StInt): StInt = func `-`*(a: StInt): StInt =
## two complement negation
a.neg a.neg
{.pop.} {.pop.}
@ -66,6 +71,7 @@ func setZero*(a: var StInt) =
a.imp.setZero a.imp.setZero
func setOne*(a: var StInt) = func setOne*(a: var StInt) =
## Set ``a`` to 1
a.imp.setOne a.imp.setOne
func zero*[bits: static[int]](T: typedesc[StInt[bits]]): T = func zero*[bits: static[int]](T: typedesc[StInt[bits]]): T =
@ -172,12 +178,18 @@ func `shl`*(a: StInt, k: SomeInteger): StInt =
result.imp.shiftLeft(a.imp, k) result.imp.shiftLeft(a.imp, k)
func setBit*(a: var StInt, k: Natural) = func setBit*(a: var StInt, k: Natural) =
## set bit at position `k`
## k = 0..a.bits-1
a.imp.setBit(k) a.imp.setBit(k)
func clearBit*(a: var StInt, k: Natural) = func clearBit*(a: var StInt, k: Natural) =
## set bit at position `k`
## k = 0..a.bits-1
a.imp.clearBit(k) a.imp.clearBit(k)
func getBit*(a: StInt, k: Natural): bool = func getBit*(a: StInt, k: Natural): bool =
## set bit at position `k`
## k = 0..a.bits-1
a.imp.getBit(k) a.imp.getBit(k)
{.pop.} {.pop.}
@ -216,3 +228,16 @@ func `+=`*(a: var StInt, b: SomeUnsignedInt) =
a.imp.inc(Word(b)) a.imp.inc(Word(b))
{.pop.} {.pop.}
# Exponentiation
# --------------------------------------------------------
{.push raises: [], noinit, gcsafe.}
func pow*(a: StUint, e: Natural): StUint =
## Compute ``a`` to the power of ``e``,
## ``e`` must be non-negative
func pow*[aBits, eBits](a: StUint[aBits], e: StUint[eBits]): StUint[aBits] =
## Compute ``x`` to the power of ``y``,
## ``x`` must be non-negative

View File

@ -135,16 +135,22 @@ func `shl`*(a: StUint, k: Natural): StUint =
result.shiftLeft(a, k) result.shiftLeft(a, k)
func setBit*(a: var StUint, k: Natural) = func setBit*(a: var StUint, k: Natural) =
## set bit at position `k`
## k = 0..a.bits-1
let limbIndex = k div WordBitWidth let limbIndex = k div WordBitWidth
let bitIndex = k mod WordBitWidth let bitIndex = k mod WordBitWidth
setBit(a.limbs[limbIndex], bitIndex) setBit(a.limbs[limbIndex], bitIndex)
func clearBit*(a: var StUint, k: Natural) = func clearBit*(a: var StUint, k: Natural) =
## set bit at position `k`
## k = 0..a.bits-1
let limbIndex = k div WordBitWidth let limbIndex = k div WordBitWidth
let bitIndex = k mod WordBitWidth let bitIndex = k mod WordBitWidth
clearBit(a.limbs[limbIndex], bitIndex) clearBit(a.limbs[limbIndex], bitIndex)
func getBit*(a: StUint, k: Natural): bool = func getBit*(a: StUint, k: Natural): bool =
## set bit at position `k`
## k = 0..a.bits-1
let limbIndex = k div WordBitWidth let limbIndex = k div WordBitWidth
let bitIndex = k mod WordBitWidth let bitIndex = k mod WordBitWidth
getBit(a.limbs[limbIndex], bitIndex) getBit(a.limbs[limbIndex], bitIndex)

View File

@ -12,11 +12,11 @@ import
test_uint_bitops2, test_uint_bitops2,
test_uint_bitwise, test_uint_bitwise,
test_uint_comparison, test_uint_comparison,
#test_uint_divmod, test_uint_divmod,
test_uint_endianness, test_uint_endianness,
test_uint_endians2, test_uint_endians2,
test_uint_exp, test_uint_exp,
#test_uint_modular_arithmetic, test_uint_modular_arithmetic,
test_uint_mul test_uint_mul
import import
@ -25,10 +25,10 @@ import
test_int_comparison, test_int_comparison,
test_int_bitwise, test_int_bitwise,
test_int_addsub, test_int_addsub,
#[
test_int_endianness, test_int_endianness,
test_int_muldiv, test_int_muldiv
#[
import test_io, import test_io,
test_conversion test_conversion
]# ]#

View File

@ -20,36 +20,6 @@ template chkDivMod(chk: untyped, a, b, c, d: string, bits: int) =
template testdivmod(chk, tst: untyped) = template testdivmod(chk, tst: untyped) =
tst "operator `div`": tst "operator `div`":
#[chkDiv(chk, "0", "3", "0", 8)
chkDiv(chk, "1", "3", "0", 8)
chkDiv(chk, "3", "3", "1", 8)
chkDiv(chk, "3", "1", "3", 8)
chkDiv(chk, "FF", "3", "55", 8)
chkDiv(chk, "0", "3", "0", 16)
chkDiv(chk, "1", "3", "0", 16)
chkDiv(chk, "3", "3", "1", 16)
chkDiv(chk, "3", "1", "3", 16)
chkDiv(chk, "FF", "3", "55", 16)
chkDiv(chk, "FFFF", "3", "5555", 16)
chkDiv(chk, "0", "3", "0", 32)
chkDiv(chk, "1", "3", "0", 32)
chkDiv(chk, "3", "3", "1", 32)
chkDiv(chk, "3", "1", "3", 32)
chkDiv(chk, "FF", "3", "55", 32)
chkDiv(chk, "FFFF", "3", "5555", 32)
chkDiv(chk, "FFFFFFFF", "3", "55555555", 32)
chkDiv(chk, "0", "3", "0", 64)
chkDiv(chk, "1", "3", "0", 64)
chkDiv(chk, "3", "3", "1", 64)
chkDiv(chk, "3", "1", "3", 64)
chkDiv(chk, "FF", "3", "55", 64)
chkDiv(chk, "FFFF", "3", "5555", 64)
chkDiv(chk, "FFFFFFFF", "3", "55555555", 64)
chkDiv(chk, "FFFFFFFFFFFFFFFF", "3", "5555555555555555", 64)]#
chkDiv(chk, "0", "3", "0", 128) chkDiv(chk, "0", "3", "0", 128)
chkDiv(chk, "1", "3", "0", 128) chkDiv(chk, "1", "3", "0", 128)
chkDiv(chk, "3", "3", "1", 128) chkDiv(chk, "3", "3", "1", 128)
@ -61,48 +31,6 @@ template testdivmod(chk, tst: untyped) =
chkDiv(chk, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "3", "55555555555555555555555555555555", 128) chkDiv(chk, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "3", "55555555555555555555555555555555", 128)
tst "operator `mod`": tst "operator `mod`":
#[chkMod(chk, "0", "3", "0", 8)
chkMod(chk, "1", "3", "1", 8)
chkMod(chk, "3", "3", "0", 8)
chkMod(chk, "3", "1", "0", 8)
chkMod(chk, "FF", "3", "0", 8)
chkMod(chk, "FF", "4", "3", 8)
chkMod(chk, "0", "3", "0", 16)
chkMod(chk, "1", "3", "1", 16)
chkMod(chk, "3", "3", "0", 16)
chkMod(chk, "3", "1", "0", 16)
chkMod(chk, "FF", "3", "0", 16)
chkMod(chk, "FF", "4", "3", 16)
chkMod(chk, "FFFF", "3", "0", 16)
chkMod(chk, "FFFF", "4", "3", 16)
chkMod(chk, "FFFF", "17", "8", 16)
chkMod(chk, "0", "3", "0", 32)
chkMod(chk, "1", "3", "1", 32)
chkMod(chk, "3", "3", "0", 32)
chkMod(chk, "3", "1", "0", 32)
chkMod(chk, "FF", "3", "0", 32)
chkMod(chk, "FF", "4", "3", 32)
chkMod(chk, "FFFF", "3", "0", 32)
chkMod(chk, "FFFF", "17", "8", 32)
chkMod(chk, "FFFFFFFF", "3", "0", 32)
chkMod(chk, "FFFFFFFF", "23", "A", 32)
chkMod(chk, "FFFFFFFF", "27", "15", 32)
chkMod(chk, "0", "3", "0", 64)
chkMod(chk, "1", "3", "1", 64)
chkMod(chk, "3", "3", "0", 64)
chkMod(chk, "3", "1", "0", 64)
chkMod(chk, "FF", "3", "0", 64)
chkMod(chk, "FF", "4", "3", 64)
chkMod(chk, "FFFF", "3", "0", 64)
chkMod(chk, "FFFF", "17", "8", 64)
chkMod(chk, "FFFFFFFF", "3", "0", 64)
chkMod(chk, "FFFFFFFF", "23", "A", 64)
chkMod(chk, "FFFFFFFF", "27", "15", 64)
chkMod(chk, "FFFFFFFFFFFFFFFF", "27", "F", 64)]#
chkMod(chk, "0", "3", "0", 128) chkMod(chk, "0", "3", "0", 128)
chkMod(chk, "1", "3", "1", 128) chkMod(chk, "1", "3", "1", 128)
chkMod(chk, "3", "3", "0", 128) chkMod(chk, "3", "3", "0", 128)
@ -118,48 +46,6 @@ template testdivmod(chk, tst: untyped) =
chkMod(chk, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "27", "15", 128) chkMod(chk, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "27", "15", 128)
tst "operator `divmod`": tst "operator `divmod`":
#[chkDivMod(chk, "0", "3", "0", "0", 8)
chkDivMod(chk, "1", "3", "0", "1", 8)
chkDivMod(chk, "3", "3", "1", "0", 8)
chkDivMod(chk, "3", "1", "3", "0", 8)
chkDivMod(chk, "FF", "3", "55", "0", 8)
chkDivMod(chk, "FF", "4", "3F", "3", 8)
chkDivMod(chk, "0", "3", "0", "0", 16)
chkDivMod(chk, "1", "3", "0", "1", 16)
chkDivMod(chk, "3", "3", "1", "0", 16)
chkDivMod(chk, "3", "1", "3", "0", 16)
chkDivMod(chk, "FF", "3", "55", "0", 16)
chkDivMod(chk, "FF", "4", "3F", "3", 16)
chkDivMod(chk, "FFFF", "3", "5555", "0", 16)
chkDivMod(chk, "FFFF", "4", "3FFF", "3", 16)
chkDivMod(chk, "FFFF", "17", "B21", "8", 16)
chkDivMod(chk, "0", "3", "0", "0", 32)
chkDivMod(chk, "1", "3", "0", "1", 32)
chkDivMod(chk, "3", "3", "1", "0", 32)
chkDivMod(chk, "3", "1", "3", "0", 32)
chkDivMod(chk, "FF", "3", "55", "0", 32)
chkDivMod(chk, "FF", "4", "3F", "3", 32)
chkDivMod(chk, "FFFF", "3", "5555", "0", 32)
chkDivMod(chk, "FFFF", "17", "B21", "8", 32)
chkDivMod(chk, "FFFFFFFF", "3", "55555555", "0", 32)
chkDivMod(chk, "FFFFFFFF", "23", "7507507", "0A", 32)
chkDivMod(chk, "FFFFFFFF", "27", "6906906", "15", 32)
chkDivMod(chk, "0", "3", "0", "0", 64)
chkDivMod(chk, "1", "3", "0", "1", 64)
chkDivMod(chk, "3", "3", "1", "0", 64)
chkDivMod(chk, "3", "1", "3", "0", 64)
chkDivMod(chk, "FF", "3", "55", "0", 64)
chkDivMod(chk, "FF", "4", "3F", "3", 64)
chkDivMod(chk, "FFFF", "3", "5555", "0", 64)
chkDivMod(chk, "FFFF", "17", "B21", "8", 64)
chkDivMod(chk, "FFFFFFFF", "3", "55555555", "0", 64)
chkDivMod(chk, "FFFFFFFF", "23", "7507507", "0A", 64)
chkDivMod(chk, "FFFFFFFF", "27", "6906906", "15", 64)
chkDivMod(chk, "FFFFFFFFFFFFFFFF", "27", "690690690690690", "F", 64)]#
chkDivMod(chk, "0", "3", "0", "0", 128) chkDivMod(chk, "0", "3", "0", "0", 128)
chkDivMod(chk, "1", "3", "0", "1", 128) chkDivMod(chk, "1", "3", "0", "1", 128)
chkDivMod(chk, "3", "3", "1", "0", 128) chkDivMod(chk, "3", "3", "1", "0", 128)
@ -174,50 +60,47 @@ template testdivmod(chk, tst: untyped) =
chkDivMod(chk, "FFFFFFFFFFFFFFFF", "27", "690690690690690", "F", 128) chkDivMod(chk, "FFFFFFFFFFFFFFFF", "27", "690690690690690", "F", 128)
chkDivMod(chk, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "27", "6906906906906906906906906906906", "15", 128) chkDivMod(chk, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "27", "6906906906906906906906906906906", "15", 128)
static: #static:
testdivmod(ctCheck, ctTest) #testdivmod(ctCheck, ctTest)
suite "Wider unsigned int muldiv coverage": suite "Wider unsigned int muldiv coverage":
testdivmod(check, test) testdivmod(check, test)
#[
suite "Testing unsigned int division and modulo implementation": suite "Testing unsigned int division and modulo implementation":
test "Divmod(100, 13) returns the correct result": test "Divmod(100, 13) returns the correct result":
let a = 100.stuint(64) let a = 100.stuint(256)
let b = 13.stuint(64) let b = 13.stuint(256)
let qr = divmod(a, b) let qr = divmod(a, b)
check: cast[uint64](qr.quot) == 7'u64 check qr.quot == 7'u64.u256
check: cast[uint64](qr.rem) == 9'u64 check qr.rem == 9'u64.u256
# TODO - no more .lo / .hi test "Divmod(2^64, 3) returns the correct result":
# let a = 1.stuint(128) shl 64
# test "Divmod(2^64, 3) returns the correct result": let b = 3.stuint(128)
# let a = 1.stuint(128) shl 64
# let b = 3.stuint(128) let qr = divmod(a, b)
#
# let qr = divmod(a, b) let q = qr.quot
# let r = qr.rem
# let q = cast[UintImpl[uint64]](qr.quot)
# let r = cast[UintImpl[uint64]](qr.rem) check:
# q == 6148914691236517205'u64.u128
# check: q.lo == 6148914691236517205'u64 r == 1'u64.u128
# check: q.hi == 0'u64
# check: r.lo == 1'u64
# check: r.hi == 0'u64
test "Divmod(1234567891234567890, 10) returns the correct result": test "Divmod(1234567891234567890, 10) returns the correct result":
let a = cast[StUint[64]](1234567891234567890'u64) let a = 1234567891234567890'u64.u256
let b = cast[StUint[64]](10'u64) let b = 10'u64.u256
let qr = divmod(a, b) let qr = divmod(a, b)
let q = cast[uint64](qr.quot) let q = qr.quot
let r = cast[uint64](qr.rem) let r = qr.rem
check: q == 123456789123456789'u64 check:
check: r == 0'u64 q == 123456789123456789'u64.u256
r == 0'u64.u256
suite "Testing specific failures highlighted by property-based testing": suite "Testing specific failures highlighted by property-based testing":
test "Modulo: 65696211516342324 mod 174261910798982": test "Modulo: 65696211516342324 mod 174261910798982":
@ -225,23 +108,22 @@ suite "Testing specific failures highlighted by property-based testing":
let u = 65696211516342324'u64 let u = 65696211516342324'u64
let v = 174261910798982'u64 let v = 174261910798982'u64
let a = cast[StUint[64]](u) let a = u.u256
let b = cast[StUint[64]](v) let b = v.u256
let z = u mod v let z = u mod v
let tz = cast[uint64](a mod b) let tz = a mod b
check: z == tz check z.u256 == tz
test "Modulo: 15080397990160655 mod 600432699691": test "Modulo: 15080397990160655 mod 600432699691":
let u = 15080397990160655'u64 let u = 15080397990160655'u64
let v = 600432699691'u64 let v = 600432699691'u64
let a = cast[StUint[64]](u) let a = u.u256
let b = cast[StUint[64]](v) let b = v.u256
let z = u mod v let z = u mod v
let tz = cast[uint64](a mod b) let tz = a mod b
check: z == tz check z.u256 == tz
]#

View File

@ -17,20 +17,6 @@ template chkPow(chk: untyped, a: string, b: SomeInteger, c: string, bits: int) =
template testExp(chk, tst: untyped) = template testExp(chk, tst: untyped) =
tst "BigInt BigInt Pow": tst "BigInt BigInt Pow":
#[chkPow(chk, "F", "2", "E1", 8)
chkPow(chk, "F", "2", "E1", 16)
chkPow(chk, "FF", "2", "FE01", 16)
chkPow(chk, "F", "2", "E1", 32)
chkPow(chk, "FF", "2", "FE01", 32)
chkPow(chk, "FF", "3", "FD02FF", 32)
chkPow(chk, "F", "2", "E1", 64)
chkPow(chk, "FF", "2", "FE01", 64)
chkPow(chk, "FF", "3", "FD02FF", 64)
chkPow(chk, "FFF", "3", "FFD002FFF", 64)]#
chkPow(chk, "F", "2", "E1", 128) chkPow(chk, "F", "2", "E1", 128)
chkPow(chk, "FF", "2", "FE01", 128) chkPow(chk, "FF", "2", "FE01", 128)
chkPow(chk, "FF", "3", "FD02FF", 128) chkPow(chk, "FF", "3", "FD02FF", 128)
@ -38,20 +24,6 @@ template testExp(chk, tst: untyped) =
chkPow(chk, "FFFFF", "3", "ffffd00002fffff", 128) chkPow(chk, "FFFFF", "3", "ffffd00002fffff", 128)
tst "BigInt Natural Pow": tst "BigInt Natural Pow":
#[chkPow(chk, "F", 2, "E1", 8)
chkPow(chk, "F", 2, "E1", 16)
chkPow(chk, "FF", 2, "FE01", 16)
chkPow(chk, "F", 2, "E1", 32)
chkPow(chk, "FF", 2, "FE01", 32)
chkPow(chk, "FF", 3, "FD02FF", 32)
chkPow(chk, "F", 2, "E1", 64)
chkPow(chk, "FF", 2, "FE01", 64)
chkPow(chk, "FF", 3, "FD02FF", 64)
chkPow(chk, "FFF", 3, "FFD002FFF", 64)]#
chkPow(chk, "F", 2, "E1", 128) chkPow(chk, "F", 2, "E1", 128)
chkPow(chk, "FF", 2, "FE01", 128) chkPow(chk, "FF", 2, "FE01", 128)
chkPow(chk, "FF", 3, "FD02FF", 128) chkPow(chk, "FF", 3, "FD02FF", 128)
@ -64,7 +36,6 @@ static:
suite "Wider unsigned int exp coverage": suite "Wider unsigned int exp coverage":
testExp(check, test) testExp(check, test)
#[
suite "Testing unsigned exponentiation": suite "Testing unsigned exponentiation":
test "Simple exponentiation 5^3": test "Simple exponentiation 5^3":
@ -85,4 +56,3 @@ suite "Testing unsigned exponentiation":
check: a.pow(b) == "4922235242952026704037113243122008064".u256 check: a.pow(b) == "4922235242952026704037113243122008064".u256
check: a.pow(b.stuint(256)) == "4922235242952026704037113243122008064".u256 check: a.pow(b.stuint(256)) == "4922235242952026704037113243122008064".u256
]#

View File

@ -23,21 +23,6 @@ template chkPowMod(chk: untyped, a, b, m, c: string, bits: int) =
template testModArith(chk, tst: untyped) = template testModArith(chk, tst: untyped) =
tst "addmod": tst "addmod":
#[chkAddMod(chk, "F", "F", "7", "2", 8)
chkAddMod(chk, "AAAA", "AA", "F", "0", 16)
chkAddMod(chk, "BBBB", "AAAA", "9", "3", 16)
chkAddMod(chk, "F", "F", "7", "2", 32)
chkAddMod(chk, "AAAA", "AA", "F", "0", 32)
chkAddMod(chk, "BBBB", "AAAA", "9", "3", 32)
chkAddMod(chk, "BBBBBBBB", "AAAAAAAA", "9", "6", 32)
chkAddMod(chk, "F", "F", "7", "2", 64)
chkAddMod(chk, "AAAA", "AA", "F", "0", 64)
chkAddMod(chk, "BBBB", "AAAA", "9", "3", 64)
chkAddMod(chk, "BBBBBBBB", "AAAAAAAA", "9", "6", 64)
chkAddMod(chk, "BBBBBBBBBBBBBBBB", "AAAAAAAAAAAAAAAA", "9", "3", 64)]#
chkAddMod(chk, "F", "F", "7", "2", 128) chkAddMod(chk, "F", "F", "7", "2", 128)
chkAddMod(chk, "AAAA", "AA", "F", "0", 128) chkAddMod(chk, "AAAA", "AA", "F", "0", 128)
chkAddMod(chk, "BBBB", "AAAA", "9", "3", 128) chkAddMod(chk, "BBBB", "AAAA", "9", "3", 128)
@ -45,27 +30,7 @@ template testModArith(chk, tst: untyped) =
chkAddMod(chk, "BBBBBBBBBBBBBBBB", "AAAAAAAAAAAAAAAA", "9", "3", 128) chkAddMod(chk, "BBBBBBBBBBBBBBBB", "AAAAAAAAAAAAAAAA", "9", "3", 128)
chkAddMod(chk, "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "9", "6", 128) chkAddMod(chk, "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "9", "6", 128)
tst "submod": tst "submod":
#[chkSubMod(chk, "C", "3", "C", "9", 8)
chkSubMod(chk, "1", "3", "C", "A", 8)
chkSubMod(chk, "1", "FF", "C", "A", 8)
chkSubMod(chk, "C", "3", "C", "9", 16)
chkSubMod(chk, "1", "3", "C", "A", 16)
chkSubMod(chk, "1", "FFFF", "C", "A", 32)
chkSubMod(chk, "C", "3", "C", "9", 32)
chkSubMod(chk, "1", "3", "C", "A", 32)
chkSubMod(chk, "1", "FFFF", "C", "A", 32)
chkSubMod(chk, "1", "FFFFFFFF", "C", "A", 32)
chkSubMod(chk, "C", "3", "C", "9", 64)
chkSubMod(chk, "1", "3", "C", "A", 64)
chkSubMod(chk, "1", "FFFF", "C", "A", 64)
chkSubMod(chk, "1", "FFFFFFFF", "C", "A", 64)
chkSubMod(chk, "1", "FFFFFFFFFFFFFFFF", "C", "A", 64)]#
chkSubMod(chk, "C", "3", "C", "9", 128) chkSubMod(chk, "C", "3", "C", "9", 128)
chkSubMod(chk, "1", "3", "C", "A", 128) chkSubMod(chk, "1", "3", "C", "A", 128)
chkSubMod(chk, "1", "FFFF", "C", "A", 128) chkSubMod(chk, "1", "FFFF", "C", "A", 128)
@ -74,25 +39,6 @@ template testModArith(chk, tst: untyped) =
chkSubMod(chk, "1", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "C", "A", 128) chkSubMod(chk, "1", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "C", "A", 128)
tst "mulmod": tst "mulmod":
#[chkMulMod(chk, "C", "3", "C", "0", 8)
chkMulMod(chk, "1", "3", "C", "3", 8)
chkMulMod(chk, "1", "FF", "C", "3", 8)
chkMulMod(chk, "C", "3", "C", "0", 16)
chkMulMod(chk, "1", "3", "C", "3", 16)
chkMulMod(chk, "1", "FFFF", "C", "3", 16)
chkMulMod(chk, "C", "3", "C", "0", 32)
chkMulMod(chk, "1", "3", "C", "3", 32)
chkMulMod(chk, "1", "FFFF", "C", "3", 32)
chkMulMod(chk, "1", "FFFFFFFF", "C", "3", 32)
chkMulMod(chk, "C", "3", "C", "0", 64)
chkMulMod(chk, "1", "3", "C", "3", 64)
chkMulMod(chk, "1", "FFFF", "C", "3", 64)
chkMulMod(chk, "1", "FFFFFFFF", "C", "3", 64)
chkMulMod(chk, "1", "FFFFFFFFFFFFFFFF", "C", "3", 64)]#
chkMulMod(chk, "C", "3", "C", "0", 128) chkMulMod(chk, "C", "3", "C", "0", 128)
chkMulMod(chk, "1", "3", "C", "3", 128) chkMulMod(chk, "1", "3", "C", "3", 128)
chkMulMod(chk, "1", "FFFF", "C", "3", 128) chkMulMod(chk, "1", "FFFF", "C", "3", 128)
@ -100,38 +46,7 @@ template testModArith(chk, tst: untyped) =
chkMulMod(chk, "1", "FFFFFFFFFFFFFFFF", "C", "3", 128) chkMulMod(chk, "1", "FFFFFFFFFFFFFFFF", "C", "3", 128)
chkMulMod(chk, "1", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "C", "3", 128) chkMulMod(chk, "1", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "C", "3", 128)
# TODO: bug #98
when nimvm:
# this ugly branch needed due to nim-lang/Nim#12518
discard
else:
tst "powmod": tst "powmod":
#[chkPowMod(chk, "C", "3", "C", "0", 8)
chkPowMod(chk, "1", "3", "C", "1", 8)
chkPowMod(chk, "1", "FF", "C", "1", 8)
chkPowMod(chk, "FF", "3", "C", "3", 8)
chkPowMod(chk, "C", "3", "C", "0", 16)
chkPowMod(chk, "1", "3", "C", "1", 16)
chkPowMod(chk, "1", "FF", "C", "1", 16)
chkPowMod(chk, "FF", "3", "C", "3", 16)
chkPowMod(chk, "FFFF", "3", "C", "3", 16)
chkPowMod(chk, "C", "3", "C", "0", 32)
chkPowMod(chk, "1", "3", "C", "1", 32)
chkPowMod(chk, "1", "FF", "C", "1", 32)
chkPowMod(chk, "FF", "3", "C", "3", 32)
chkPowMod(chk, "FFFF", "3", "C", "3", 32)
chkPowMod(chk, "FFFFFFFF", "3", "C", "3", 32)
chkPowMod(chk, "C", "3", "C", "0", 64)
chkPowMod(chk, "1", "3", "C", "1", 64)
chkPowMod(chk, "1", "FF", "C", "1", 64)
chkPowMod(chk, "FF", "3", "C", "3", 64)
chkPowMod(chk, "FFFF", "3", "C", "3", 64)
chkPowMod(chk, "FFFFFFFF", "3", "C", "3", 64)
chkPowMod(chk, "FFFFFFFFFFFFFFFF", "3", "C", "3", 64)]#
chkPowMod(chk, "C", "3", "C", "0", 128) chkPowMod(chk, "C", "3", "C", "0", 128)
chkPowMod(chk, "1", "3", "C", "1", 128) chkPowMod(chk, "1", "3", "C", "1", 128)
chkPowMod(chk, "1", "FF", "C", "1", 128) chkPowMod(chk, "1", "FF", "C", "1", 128)
@ -141,48 +56,47 @@ template testModArith(chk, tst: untyped) =
chkPowMod(chk, "FFFFFFFFFFFFFFFF", "3", "C", "3", 128) chkPowMod(chk, "FFFFFFFFFFFFFFFF", "3", "C", "3", 128)
chkPowMod(chk, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "3", "C", "3", 128) chkPowMod(chk, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "3", "C", "3", 128)
static: #static:
testModArith(ctCheck, ctTest) #testModArith(ctCheck, ctTest)
suite "Wider unsigned Modular arithmetic coverage": suite "Wider unsigned Modular arithmetic coverage":
testModArith(check, test) testModArith(check, test)
#[
suite "Modular arithmetic": suite "Modular arithmetic":
test "Modular addition": test "Modular addition":
# uint16 rolls over at 65535 # uint16 rolls over at 65535
let a = 50000'u16.stuint(16) let a = 50000.u256
let b = 20000'u16.stuint(16) let b = 20000.u256
let m = 60000'u16.stuint(16) let m = 60000.u256
check: addmod(a, b, m) == 10000'u16.stuint(16) check: addmod(a, b, m) == 10000.u256
test "Modular substraction": test "Modular substraction":
let a = 5'u16.stuint(16) let a = 5.u256
let b = 7'u16.stuint(16) let b = 7.u256
let m = 20'u16.stuint(16) let m = 20.u256
check: submod(a, b, m) == 18'u16.stuint(16) check: submod(a, b, m) == 18.u256
test "Modular multiplication": test "Modular multiplication":
# https://www.wolframalpha.com/input/?i=(1234567890+*+987654321)+mod+999999999 # https://www.wolframalpha.com/input/?i=(1234567890+*+987654321)+mod+999999999
# --> 345_679_002 # --> 345_679_002
let a = 1234567890'u64.stuint(64) let a = 1234567890.u256
let b = 987654321'u64.stuint(64) let b = 987654321.u256
let m = 999999999'u64.stuint(64) let m = 999999999.u256
check: mulmod(a, b, m) == 345_679_002'u64.stuint(64) check: mulmod(a, b, m) == 345_679_002.u256
test "Modular exponentiation": test "Modular exponentiation":
block: # https://www.khanacademy.org/computing/computer-science/cryptography/modarithmetic/a/fast-modular-exponentiation block: # https://www.khanacademy.org/computing/computer-science/cryptography/modarithmetic/a/fast-modular-exponentiation
check: check:
powmod(5'u16.stuint(16), 117'u16.stuint(16), 19'u16.stuint(16)) == 1'u16.stuint(16) powmod(5.u256, 117.u256, 19.u256) == 1.u256
powmod(3'u16.stuint(16), 1993'u16.stuint(16), 17'u16.stuint(16)) == 14'u16.stuint(16) powmod(3.u256, 1993.u256, 17.u256) == 14.u256
check: check:
powmod(12.stuint(256), 34.stuint(256), high(UInt256)) == "4922235242952026704037113243122008064".u256 powmod(12.u256, 34.u256, high(UInt256)) == "4922235242952026704037113243122008064".u256
block: # Little Fermat theorem block: # Little Fermat theorem
# https://programmingpraxis.com/2014/08/08/big-modular-exponentiation/ # https://programmingpraxis.com/2014/08/08/big-modular-exponentiation/
@ -203,4 +117,3 @@ suite "Modular arithmetic":
check: check:
powmod(P, Q, M) == expected powmod(P, Q, M) == expected
]#