diff --git a/stint/modular_arithmetic.nim b/stint/modular_arithmetic.nim index d7f2914..8018366 100644 --- a/stint/modular_arithmetic.nim +++ b/stint/modular_arithmetic.nim @@ -113,13 +113,6 @@ func mulmod*(a, b, m: StUint): StUint = func powmod*(a, b, m: StUint): StUint = ## Modular exponentiation - when nimvm: - doAssert false, "cannot use powmod at compile-time" - else: - # we need this ugly branch - # because of nim-lang/Nim#12517 - discard - let a_m = if a < m: a else: a mod m diff --git a/stint/private/uint_div.nim b/stint/private/uint_div.nim index b033a4c..34d2061 100644 --- a/stint/private/uint_div.nim +++ b/stint/private/uint_div.nim @@ -47,7 +47,7 @@ func shlAddMod_multi(a: var openArray[Word], c: Word, M: openArray[Word], mBits: int): Word = ## Fused modular left-shift + add ## Shift input `a` by a word and add `c` modulo `M` - ## + ## ## Specialized for M being a multi-precision integer. ## ## With a word W = 2^WordBitWidth and a modulus M @@ -55,7 +55,7 @@ func shlAddMod_multi(a: var openArray[Word], c: Word, ## and returns q = (a * W + c ) / M ## ## The modulus `M` most-significant bit at `mBits` MUST be set. - + # Assuming 64-bit words let hi = a[^1] # Save the high word to detect carries let R = mBits and (WordBitWidth - 1) # R = mBits mod 64 @@ -128,7 +128,7 @@ func shlAddMod(a: var openArray[Word], c: Word, M: openArray[Word], mBits: int): Word {.inline.}= ## Fused modular left-shift + add ## Shift input `a` by a word and add `c` modulo `M` - ## + ## ## With a word W = 2^WordBitWidth and a modulus M ## Does a <- a * W + c (mod M) ## and returns q = (a * W + c ) / M @@ -182,13 +182,28 @@ func divRem*( copyWords(r, 0, a, aOffset+1, bLen-1) r[rLen-1] = 0 # Now shift-left the copied words while adding the new word mod b - for i in countdown(aOffset, 0): - q[i] = shlAddMod( - r.toOpenArray(0, rLen-1), - a[i], - b.toOpenArray(0, bLen-1), - bBits - ) + + when nimvm: + # workaround nim bug #22095 + var rr = @(r.toOpenArray(0, rLen-1)) + var bb = @(b.toOpenArray(0, bLen-1)) + for i in countdown(aOffset, 0): + q[i] = shlAddMod( + rr, + a[i], + bb, + bBits + ) + for i in 0..rLen-1: + r[i] = rr[i] + else: + for i in countdown(aOffset, 0): + q[i] = shlAddMod( + r.toOpenArray(0, rLen-1), + a[i], + b.toOpenArray(0, bLen-1), + bBits + ) # Clean up extra words for i in aOffset+1 ..< q.len: @@ -229,7 +244,7 @@ func divRem*( # - An Efficient Multiple-Precision Division Algorithm, # Liusheng Huang, Hong Zhong, Hong Shen, Yonglong Luo, 2005 # https://ieeexplore.ieee.org/document/1579076 -# +# # - Efficient multiple-precision integer division algorithm # Debapriyay Mukhopadhyaya, Subhas C.Nandy, 2014 # https://www.sciencedirect.com/science/article/abs/pii/S0020019013002627 diff --git a/tests/test_int_muldiv.nim b/tests/test_int_muldiv.nim index 15d2ca4..7bb53ba 100644 --- a/tests/test_int_muldiv.nim +++ b/tests/test_int_muldiv.nim @@ -116,8 +116,8 @@ template testMuldiv(chk, tst: untyped) = chkMod(chk, 2, -5, 2, 64) chkMod(chk, -2, -5, -2, 64) -#static: - #testMuldiv(ctCheck, ctTest) +static: + testMuldiv(ctCheck, ctTest) suite "Wider signed int muldiv coverage": testMuldiv(check, test) diff --git a/tests/test_uint_divmod.nim b/tests/test_uint_divmod.nim index 12d0da1..1a8ce04 100644 --- a/tests/test_uint_divmod.nim +++ b/tests/test_uint_divmod.nim @@ -60,8 +60,8 @@ template testdivmod(chk, tst: untyped) = chkDivMod(chk, "FFFFFFFFFFFFFFFF", "27", "690690690690690", "F", 128) chkDivMod(chk, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "27", "6906906906906906906906906906906", "15", 128) -#static: - #testdivmod(ctCheck, ctTest) +static: + testdivmod(ctCheck, ctTest) suite "Wider unsigned int muldiv coverage": testdivmod(check, test) diff --git a/tests/test_uint_modular_arithmetic.nim b/tests/test_uint_modular_arithmetic.nim index 6708d64..42b9007 100644 --- a/tests/test_uint_modular_arithmetic.nim +++ b/tests/test_uint_modular_arithmetic.nim @@ -56,8 +56,8 @@ template testModArith(chk, tst: untyped) = chkPowMod(chk, "FFFFFFFFFFFFFFFF", "3", "C", "3", 128) chkPowMod(chk, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "3", "C", "3", 128) -#static: - #testModArith(ctCheck, ctTest) +static: + testModArith(ctCheck, ctTest) suite "Wider unsigned Modular arithmetic coverage": testModArith(check, test)