constantine/constantine/arithmetic/finite_fields_inversion.nim
Mamy Ratsimbazafy bea798e27c
Field sqrt optimization (#168)
* add more Fp tests for Twisted Edwards curves

* add fused sqrt+division bench

* Significant fused sqrt+division improvement for any prime field over algorithm described in  "High-Speed High-Security Signature", Bernstein et al, p15 "Fast decompression", https://ed25519.cr.yp.to/ed25519-20110705.pdf

* Activate secp256k1 field benches + spring renaming of field multiplication

* addition chains for inversion and sqrt of Curve25519

* Make isSquare use addition chains

* add double-prec mul/square bench for <256-bit prime fields.
2022-01-01 16:19:35 +01:00

65 lines
2.2 KiB
Nim

# 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.
import
../config/[curves, type_ff],
./bigints,
../curves/zoo_inversions
export zoo_inversions
# ############################################################
#
# Finite field inversion
#
# ############################################################
# No exceptions allowed
{.push raises: [].}
{.push inline.}
func inv_euclid*(r: var FF, a: FF) =
## Inversion modulo p via
## Niels Moller constant-time version of
## Stein's GCD derived from extended binary Euclid algorithm
r.mres.steinsGCD(a.mres, FF.getR2modP(), FF.fieldMod(), FF.getPrimePlus1div2())
func inv*(r: var FF, a: FF) =
## Inversion modulo p
##
## The inverse of 0 is 0.
## Incidentally this avoids extra check
## to convert Jacobian and Projective coordinates
## to affine for elliptic curve
# For now we don't activate the addition chains
# Performance is slower than Euclid-based inversion on newer CPUs
#
# - Montgomery multiplication/squaring can skip the final substraction
# - For generalized Mersenne Prime curves, modular reduction can be made extremely cheap.
# - For BW6-761 the addition chain is over 2x slower than Euclid-based inversion
# due to multiplication being so costly with 12 limbs (grows quadratically)
# while Euclid costs grows linearly.
when false and
FF is Fp and FF.C.hasInversionAddchain() and
FF.C notin {BW6_761}:
r.inv_addchain(a)
else:
r.inv_euclid(a)
func inv*(a: var FF) =
## Inversion modulo p
##
## The inverse of 0 is 0.
## Incidentally this avoids extra check
## to convert Jacobian and Projective coordinates
## to affine for elliptic curve
a.inv(a)
{.pop.} # inline
{.pop.} # raises no exceptions