-
-
Notifications
You must be signed in to change notification settings - Fork 62
Open
Labels
Description
In constantine/math_arbitrary_precision/arithmetic/limbs_divmod_vartime
there is a divRem_vartime
function, which I assume is supposed to implement arbitrary precision integer division with remainder.
(I couldn't find any other function implementing this operation)
However, this appears to be completely broken. For example with inputs a = 2^64 + 3
and b = 1234567
I get the result q = 0
and r = 3
Example code:
import pkg/constantine/platforms/abstractions
import pkg/constantine/math/arithmetic/bigints
import pkg/constantine/math/io/io_bigints
import pkg/constantine/math_arbitrary_precision/arithmetic/limbs_divmod_vartime
proc printSecretArray(xs: array[4, SecretWord]) =
echo " - limbs[0] = " & $uint64(xs[0])
echo " - limbs[1] = " & $uint64(xs[1])
echo " - limbs[2] = " & $uint64(xs[2])
echo " - limbs[3] = " & $uint64(xs[3])
proc main() =
var x : BigInt[256]
# let _ = x.fromDecimal("18446744073709551613") # 2^64 - 3 // this works
let _ = x.fromDecimal("18446744073709551619") # 2^64 + 3 // this doesn't
var y : BigInt[256]
let _ = y.fromDecimal("1234567")
let a: array[4, SecretWord] = x.limbs
let b: array[4, SecretWord] = y.limbs
var q: array[4, SecretWord]
var r: array[4, SecretWord]
let res = divRem_vartime(q,r,a,b)
echo "function returns: " & $res
echo "quotient limbs:"
printSecretArray(q)
echo "remainder limbs:"
printSecretArray(r)
let qbig: BigInt[256] = BigInt[256](limbs: q)
let rbig: BigInt[256] = BigInt[256](limbs: r)
echo "x = " & toDecimal(x)
echo "y = " & toDecimal(y)
echo "q = " & toDecimal(qbig)
echo "r = " & toDecimal(rbig)
var mverybig: BigInt[512]
prod[512,256,256](mverybig,qbig,y) # q*y
var mbig: BigInt[256]
copyTruncatedFrom[256,512](mbig,mverybig)
var reconstr_x: BigInt[256] = rbig
reconstr_x += mbig # q*y + r
echo "q * y = " & toDecimal(mbig)
echo "reconstructed x = " & toDecimal(reconstr_x)
echo "OK = " & $(bool(x == reconstr_x))
when isMainModule:
main()