mirror of
https://github.com/codex-storage/constantine.git
synced 2025-01-27 11:04:51 +00:00
Benchmark: BigInt -> Montgomery conversion:
- shlAddMod (with assembly division) is already 4x slower than Montgomery Multiplication based. - constant-time division will be even slower - use montgomery-multiplication based conversion
This commit is contained in:
parent
bd1430157f
commit
10346d83a4
48
benchmarks/big_to_fq.nim
Normal file
48
benchmarks/big_to_fq.nim
Normal file
@ -0,0 +1,48 @@
|
||||
# Constantine
|
||||
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||
# Licensed and distributed under either of
|
||||
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
# Benchmark of the conversion from Big Int to Fq
|
||||
#
|
||||
# ############################################################
|
||||
|
||||
# 2 implementations are possible
|
||||
# - 1 based on Montgomery Multiplication
|
||||
# - 1 based on modular left shift which involves multiple divisions
|
||||
|
||||
import
|
||||
../constantine/config/[common, curves],
|
||||
../constantine/math/[bigints_checked, finite_fields],
|
||||
random, std/monotimes, times, strformat
|
||||
|
||||
const Iters = 1_000_000
|
||||
|
||||
randomize(1234)
|
||||
|
||||
proc main() =
|
||||
var x: BigInt[381]
|
||||
x.setInternalBitLength()
|
||||
for i in 0 ..< x.limbs.len - 1:
|
||||
# Set x to a random value guaranteed below the prime
|
||||
x.limbs[i] = Word(rand(BaseType.high.int))
|
||||
|
||||
|
||||
let start = getMonotime()
|
||||
for _ in 0 ..< Iters:
|
||||
let y = Fq[BLS12_381].fromBig(x)
|
||||
let stop = getMonotime()
|
||||
|
||||
echo &"Time for {Iters} iterations: {inMilliseconds(stop-start)} ms"
|
||||
|
||||
|
||||
main()
|
||||
# 1_000_000 iterations with -d:danger on i9-9980XE all-core turbo 4.1GHz
|
||||
# Montgomery Multiplication based: 254ms
|
||||
# shlAddMod based (using assembly div2n1n!!): 907 ms
|
||||
# Note: shlAddMod will be even slower when division is made constant-time
|
@ -120,14 +120,7 @@ func unsafeMontyResidue*[mBits](mres: var BigInt[mBits], a, N, r2modN: BigInt[mB
|
||||
## Caller must take care of properly switching between
|
||||
## the natural and montgomery domain.
|
||||
## Nesting Montgomery form is possible by applying this function twice.
|
||||
# TODO: benchmark
|
||||
when true:
|
||||
# Montgomery multiplication based
|
||||
montyResidue(mres.view, a.view, N.view, r2modN.view, Word(negInvModWord))
|
||||
else:
|
||||
# Modular left shift based
|
||||
mres = a
|
||||
montyResidue(mres.view, N.view)
|
||||
montyResidue(mres.view, a.view, N.view, r2modN.view, Word(negInvModWord))
|
||||
|
||||
func unsafeRedc*[mBits](mres: var BigInt[mBits], N: BigInt[mBits], negInvModWord: static BaseType) =
|
||||
## Convert a BigInt from its Montgomery n-residue form
|
||||
|
@ -49,11 +49,11 @@ debug:
|
||||
#
|
||||
# ############################################################
|
||||
|
||||
func fromBig*(T: type Fq, src: BigInt): T =
|
||||
func fromBig*[C: static Curve](T: type Fq[C], src: BigInt): Fq[C] {.noInit.} =
|
||||
## Convert a BigInt to its Montgomery form
|
||||
result.mres.unsafeMontyResidue(src, Fq.C.Mod.mres, Fq.C.getR2modP(), Fq.C.getNegInvModWord())
|
||||
result.mres.unsafeMontyResidue(src, C.Mod.mres, C.getR2modP(), C.getNegInvModWord())
|
||||
|
||||
func toBig*(src: Fq): auto =
|
||||
func toBig*(src: Fq): auto {.noInit.} =
|
||||
## Convert a finite-field element to a BigInt in natral representation
|
||||
result = src.mres
|
||||
result.unsafeRedC(Fq.C.Mod.mres, Fq.C.getNegInvModWord())
|
||||
|
Loading…
x
Reference in New Issue
Block a user