Fix extended prec multiplication carry. Passing modulo tests against medium BigInt (192~256 bits)
This commit is contained in:
parent
73b71a184c
commit
8d160189d1
|
@ -19,4 +19,5 @@ task test, "Run all tests":
|
|||
test "", "tests/test_primitives.nim"
|
||||
test "", "tests/test_io.nim"
|
||||
test "", "tests/test_bigints.nim"
|
||||
test "", "tests/test_bigints_multimod.nim"
|
||||
test " -d:testingCurves", "tests/test_field_fp.nim"
|
||||
|
|
|
@ -57,6 +57,8 @@ from sugar import distinctBase
|
|||
type Word* = Ct[uint32]
|
||||
## Logical BigInt word
|
||||
## A logical BigInt word is of size physical MachineWord-1
|
||||
type DoubleWord = Ct[uint64]
|
||||
|
||||
type BaseType* = uint32
|
||||
## Physical BigInt for conversion in "normal integers"
|
||||
|
||||
|
@ -357,17 +359,15 @@ func shlAddMod(a: BigIntViewMut, c: Word, M: BigIntViewConst) =
|
|||
var qp_lo: Word
|
||||
|
||||
block: # q*p
|
||||
var qp_hi: Word
|
||||
unsafeExtendedPrecMul(qp_hi, qp_lo, q, M[i]) # q * p
|
||||
qp_lo += carry # Add carry from previous limb
|
||||
|
||||
carry = qp_hi shl 1 + qp_lo.isMsbSet.Word # New carry
|
||||
qp_lo = qp_lo and MaxWord # Normalize to u63
|
||||
# q * p + carry (doubleword) carry from previous limb
|
||||
let qp = unsafeExtPrecMul(q, M[i]) + carry.DoubleWord
|
||||
carry = Word(qp shr WordBitSize) # New carry: high digit besides LSB
|
||||
qp_lo = qp.Word and MaxWord # Normalize to u63
|
||||
|
||||
block: # a*2^63 - q*p
|
||||
a[i] -= qp_lo
|
||||
carry += Word(a[i].isMsbSet) # Adjust if borrow
|
||||
a[i] = a[i] and MaxWord # Normalize to u63
|
||||
carry += Word(a[i].isMsbSet) # Adjust if borrow
|
||||
a[i] = a[i] and MaxWord # Normalize to u63
|
||||
|
||||
over_p = mux(
|
||||
a[i] == M[i], over_p,
|
||||
|
|
|
@ -38,7 +38,7 @@ func asm_x86_64_extMul(hi, lo: var uint64, a, b: uint64) {.inline.}=
|
|||
:
|
||||
"""
|
||||
|
||||
func unsafeExtendedPrecMul*(hi, lo: var Ct[uint64], a, b: Ct[uint64]) {.inline.}=
|
||||
func unsafeExtPrecMul*(hi, lo: var Ct[uint64], a, b: Ct[uint64]) {.inline.}=
|
||||
## Extended precision multiplication uint64 * uint64 --> uint128
|
||||
##
|
||||
## TODO, at the moment only x86_64 architecture are supported
|
||||
|
@ -57,13 +57,9 @@ func unsafeExtendedPrecMul*(hi, lo: var Ct[uint64], a, b: Ct[uint64]) {.inline.}
|
|||
else:
|
||||
asm_x86_64_extMul(T(hi), T(lo), T(a), T(b))
|
||||
|
||||
import strutils
|
||||
|
||||
func unsafeExtendedPrecMul*(hi, lo: var Ct[uint32], a, b: Ct[uint32]) {.inline.}=
|
||||
## Extended precision multiplication uint32 * uint32 --> uint32
|
||||
let extMul = uint64(a) * uint64(b)
|
||||
hi = (Ct[uint32])(extMul shr 32)
|
||||
lo = (Ct[uint32])(extMul and ((1'u64 shl 32) - 1))
|
||||
template unsafeExtPrecMul*(a, b: Ct[uint32]): Ct[uint64] =
|
||||
## Extended precision multiplication uint32 * uint32 --> uint64
|
||||
Ct[uint64](uint64(a) * uint64(b))
|
||||
|
||||
func asm_x86_64_div2n1n(q, r: var uint64, n_hi, n_lo, d: uint64) {.inline.}=
|
||||
## Division uint128 by uint64
|
||||
|
|
|
@ -10,7 +10,7 @@ import
|
|||
# Standard library
|
||||
unittest, random, strutils,
|
||||
# Third-party
|
||||
../constantine/[io, bigints, primitives]
|
||||
../constantine/[io, bigints_raw, bigints_public, primitives]
|
||||
|
||||
suite "Bigints - Multiprecision modulo":
|
||||
test "bitsize 237 mod bitsize 192":
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
-d:debugConstantine
|
Loading…
Reference in New Issue