constantine/constantine/arithmetic/finite_fields_inversion.nim

65 lines
2.2 KiB
Nim
Raw Normal View History

2020-03-20 23:03:52 +01:00
# 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,
2020-09-27 21:00:35 +02:00
../curves/zoo_inversions
2020-03-20 23:03:52 +01:00
2020-09-27 21:00:35 +02:00
export zoo_inversions
2020-03-20 23:03:52 +01:00
# ############################################################
#
# Finite field inversion
2020-03-20 23:03:52 +01:00
#
# ############################################################
# 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) =
2020-03-20 23:03:52 +01:00
## 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