Tower drop concepts (#153)
* Fix affine instantiation * drop concept from the codebase * Remove alignment requirement, this cases problem in sequences on 32-bit for t_fp12_anti_regression * slight sparse optim
This commit is contained in:
parent
ffc77cd087
commit
e23f990280
|
@ -124,6 +124,7 @@ func trySetFromCoordX*[F, Tw](
|
||||||
## will be provided, this is intended for testing purposes.
|
## will be provided, this is intended for testing purposes.
|
||||||
P.y.curve_eq_rhs(x, Tw)
|
P.y.curve_eq_rhs(x, Tw)
|
||||||
result = sqrt_if_square(P.y)
|
result = sqrt_if_square(P.y)
|
||||||
|
P.x = x
|
||||||
|
|
||||||
func neg*(P: var ECP_ShortW_Aff, Q: ECP_ShortW_Aff) =
|
func neg*(P: var ECP_ShortW_Aff, Q: ECP_ShortW_Aff) =
|
||||||
## Negate ``P``
|
## Negate ``P``
|
||||||
|
|
|
@ -12,6 +12,7 @@ import
|
||||||
std/typetraits,
|
std/typetraits,
|
||||||
# Internal
|
# Internal
|
||||||
./io_bigints, ./io_fields,
|
./io_bigints, ./io_fields,
|
||||||
|
../primitives,
|
||||||
../arithmetic/finite_fields,
|
../arithmetic/finite_fields,
|
||||||
../tower_field_extensions/tower_instantiation
|
../tower_field_extensions/tower_instantiation
|
||||||
|
|
||||||
|
@ -30,11 +31,11 @@ export tower_instantiation
|
||||||
func appendHex*(accum: var string, f: Fp2 or Fp4 or Fp6 or Fp12, order: static Endianness = bigEndian) =
|
func appendHex*(accum: var string, f: Fp2 or Fp4 or Fp6 or Fp12, order: static Endianness = bigEndian) =
|
||||||
## Hex accumulator
|
## Hex accumulator
|
||||||
accum.add static($f.typeof.genericHead() & '(')
|
accum.add static($f.typeof.genericHead() & '(')
|
||||||
for fieldName, fieldValue in fieldPairs(f):
|
staticFor i, 0, f.coords.len:
|
||||||
when fieldName != "c0":
|
when i != 0:
|
||||||
accum.add ", "
|
accum.add ", "
|
||||||
accum.add fieldName & ": "
|
accum.add "c" & $i & ": "
|
||||||
accum.appendHex(fieldValue, order)
|
accum.appendHex(f.coords[i], order)
|
||||||
accum.add ")"
|
accum.add ")"
|
||||||
|
|
||||||
func toHex*(f: Fp2 or Fp4 or Fp6 or Fp12, order: static Endianness = bigEndian): string =
|
func toHex*(f: Fp2 or Fp4 or Fp6 or Fp12, order: static Endianness = bigEndian): string =
|
||||||
|
@ -109,18 +110,14 @@ func fromHex*(T: typedesc[Fp12],
|
||||||
|
|
||||||
func fromUint*(a: var ExtensionField, src: SomeUnsignedInt) =
|
func fromUint*(a: var ExtensionField, src: SomeUnsignedInt) =
|
||||||
## Set ``a`` to the bigint value int eh extension field
|
## Set ``a`` to the bigint value int eh extension field
|
||||||
for fieldName, fA in fieldPairs(a):
|
a.coords[0].fromUint(src)
|
||||||
when fieldName == "c0":
|
staticFor i, 1, a.coords.len:
|
||||||
fA.fromUint(src)
|
a.coords[i].setZero()
|
||||||
else:
|
|
||||||
fA.setZero()
|
|
||||||
|
|
||||||
func fromInt*(a: var ExtensionField, src: SomeInteger) =
|
func fromInt*(a: var ExtensionField, src: SomeInteger) =
|
||||||
## Parse a regular signed integer
|
## Parse a regular signed integer
|
||||||
## and store it into a Fp^n
|
## and store it into a Fp^n
|
||||||
## A negative integer will be instantiated as a negated number (mod p^n)
|
## A negative integer will be instantiated as a negated number (mod p^n)
|
||||||
for fieldName, fA in fieldPairs(a):
|
a.coords[0].fromInt(src)
|
||||||
when fieldName == "c0":
|
staticFor i, 1, a.coords.len:
|
||||||
fA.fromInt(src)
|
a.coords[i].setZero()
|
||||||
else:
|
|
||||||
fA.setZero()
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import
|
||||||
std/macros,
|
std/macros,
|
||||||
../arithmetic,
|
../arithmetic,
|
||||||
../towers,
|
../towers,
|
||||||
|
../primitives,
|
||||||
../curves/zoo_frobenius
|
../curves/zoo_frobenius
|
||||||
|
|
||||||
# Frobenius Map
|
# Frobenius Map
|
||||||
|
@ -79,9 +80,9 @@ func frobenius_map*[C](r: var Fp12[C], a: Fp12[C], k: static int = 1) {.inline.}
|
||||||
## Computes a^(p^k)
|
## Computes a^(p^k)
|
||||||
## The p-power frobenius automorphism on 𝔽p12
|
## The p-power frobenius automorphism on 𝔽p12
|
||||||
static: doAssert r.c0 is Fp4
|
static: doAssert r.c0 is Fp4
|
||||||
for r_fp4, a_fp4 in fields(r, a):
|
staticFor i, 0, r.coords.len:
|
||||||
for r_fp2, a_fp2 in fields(r_fp4, a_fp4):
|
staticFor j, 0, r.coords[0].coords.len:
|
||||||
r_fp2.frobenius_map(a_fp2, k)
|
r.coords[i].coords[j].frobenius_map(a.coords[i].coords[j], k)
|
||||||
|
|
||||||
r.c0.c0.mulCheckSparse frobMapConst(C, 0, k)
|
r.c0.c0.mulCheckSparse frobMapConst(C, 0, k)
|
||||||
r.c0.c1.mulCheckSparse frobMapConst(C, 3, k)
|
r.c0.c1.mulCheckSparse frobMapConst(C, 3, k)
|
||||||
|
|
|
@ -158,18 +158,18 @@ func line_eval_add[F](
|
||||||
when F.C.getSexticTwist() == M_Twist:
|
when F.C.getSexticTwist() == M_Twist:
|
||||||
A *= SexticNonResidue # A = ξ (X₁ - Z₁X₂)
|
A *= SexticNonResidue # A = ξ (X₁ - Z₁X₂)
|
||||||
|
|
||||||
func line_eval_fused_double[F](
|
func line_eval_fused_double[Field](
|
||||||
line: var Line[F],
|
line: var Line[Field],
|
||||||
T: var ECP_ShortW_Prj[F, OnTwist]) =
|
T: var ECP_ShortW_Prj[Field, OnTwist]) =
|
||||||
## Fused line evaluation and elliptic point doubling
|
## Fused line evaluation and elliptic point doubling
|
||||||
# Grewal et al, 2012 adapted to Scott 2019 line notation
|
# Grewal et al, 2012 adapted to Scott 2019 line notation
|
||||||
var A {.noInit.}, B {.noInit.}, C {.noInit.}: F
|
var A {.noInit.}, B {.noInit.}, C {.noInit.}: Field
|
||||||
var E {.noInit.}, F {.noInit.}, G {.noInit.}: F
|
var E {.noInit.}, F {.noInit.}, G {.noInit.}: Field
|
||||||
template H: untyped = line.x
|
template H: untyped = line.x
|
||||||
const b3 = 3*F.C.getCoefB()
|
const b3 = 3*Field.C.getCoefB()
|
||||||
|
|
||||||
var snrY = T.y
|
var snrY = T.y
|
||||||
when F.C.getSexticTwist() == D_Twist:
|
when Field.C.getSexticTwist() == D_Twist:
|
||||||
snrY *= SexticNonResidue
|
snrY *= SexticNonResidue
|
||||||
|
|
||||||
A.prod(T.x, snrY)
|
A.prod(T.x, snrY)
|
||||||
|
@ -178,11 +178,11 @@ func line_eval_fused_double[F](
|
||||||
C.square(T.z) # C = Z²
|
C.square(T.z) # C = Z²
|
||||||
|
|
||||||
var snrB = B
|
var snrB = B
|
||||||
when F.C.getSexticTwist() == D_Twist:
|
when Field.C.getSexticTwist() == D_Twist:
|
||||||
snrB *= SexticNonResidue
|
snrB *= SexticNonResidue
|
||||||
|
|
||||||
E.prod(C, b3)
|
E.prod(C, b3)
|
||||||
when F.C.getSexticTwist() == M_Twist:
|
when Field.C.getSexticTwist() == M_Twist:
|
||||||
E *= SexticNonResidue # E = 3b'Z² = 3bξ Z²
|
E *= SexticNonResidue # E = 3b'Z² = 3bξ Z²
|
||||||
|
|
||||||
F.prod(E, 3) # F = 3E = 9bZ²
|
F.prod(E, 3) # F = 3E = 9bZ²
|
||||||
|
@ -195,7 +195,7 @@ func line_eval_fused_double[F](
|
||||||
|
|
||||||
line.z.square(T.x)
|
line.z.square(T.x)
|
||||||
line.z *= 3 # lz = 3X²
|
line.z *= 3 # lz = 3X²
|
||||||
when F.C.getSexticTwist() == D_Twist:
|
when Field.C.getSexticTwist() == D_Twist:
|
||||||
line.z *= SexticNonResidue
|
line.z *= SexticNonResidue
|
||||||
|
|
||||||
line.y.diff(E, snrB) # ly = E-B = 3b'Z² - Y²
|
line.y.diff(E, snrB) # ly = E-B = 3b'Z² - Y²
|
||||||
|
@ -213,7 +213,7 @@ func line_eval_fused_double[F](
|
||||||
# M-twist: (Y²+9bξZ²)²/4 - 3*(3bξZ²)²
|
# M-twist: (Y²+9bξZ²)²/4 - 3*(3bξZ²)²
|
||||||
# D-Twist: (ξY²+9bZ²)²/4 - 3*(3bZ²)²
|
# D-Twist: (ξY²+9bZ²)²/4 - 3*(3bZ²)²
|
||||||
|
|
||||||
when F.C.getSexticTwist() == D_Twist:
|
when Field.C.getSexticTwist() == D_Twist:
|
||||||
H *= SexticNonResidue
|
H *= SexticNonResidue
|
||||||
T.z.prod(snrB, H) # Z₃ = BH = Y²((Y+Z)² - (Y²+Z²)) = 2Y³Z
|
T.z.prod(snrB, H) # Z₃ = BH = Y²((Y+Z)² - (Y²+Z²)) = 2Y³Z
|
||||||
# M-twist: 2Y³Z
|
# M-twist: 2Y³Z
|
||||||
|
@ -221,26 +221,26 @@ func line_eval_fused_double[F](
|
||||||
|
|
||||||
# Correction for Fp4 towering
|
# Correction for Fp4 towering
|
||||||
H.neg() # lx = -H
|
H.neg() # lx = -H
|
||||||
when F.C.getSexticTwist() == M_Twist:
|
when Field.C.getSexticTwist() == M_Twist:
|
||||||
H *= SexticNonResidue
|
H *= SexticNonResidue
|
||||||
# else: the SNR is already integrated in H
|
# else: the SNR is already integrated in H
|
||||||
|
|
||||||
func line_eval_fused_add[F](
|
func line_eval_fused_add[Field](
|
||||||
line: var Line[F],
|
line: var Line[Field],
|
||||||
T: var ECP_ShortW_Prj[F, OnTwist],
|
T: var ECP_ShortW_Prj[Field, OnTwist],
|
||||||
Q: ECP_ShortW_Aff[F, OnTwist]) =
|
Q: ECP_ShortW_Aff[Field, OnTwist]) =
|
||||||
## Fused line evaluation and elliptic point addition
|
## Fused line evaluation and elliptic point addition
|
||||||
# Grewal et al, 2012 adapted to Scott 2019 line notation
|
# Grewal et al, 2012 adapted to Scott 2019 line notation
|
||||||
var
|
var
|
||||||
A {.noInit.}: F
|
A {.noInit.}: Field
|
||||||
B {.noInit.}: F
|
B {.noInit.}: Field
|
||||||
C {.noInit.}: F
|
C {.noInit.}: Field
|
||||||
D {.noInit.}: F
|
D {.noInit.}: Field
|
||||||
E {.noInit.}: F
|
E {.noInit.}: Field
|
||||||
F {.noInit.}: F
|
F {.noInit.}: Field
|
||||||
G {.noInit.}: F
|
G {.noInit.}: Field
|
||||||
H {.noInit.}: F
|
H {.noInit.}: Field
|
||||||
I {.noInit.}: F
|
I {.noInit.}: Field
|
||||||
|
|
||||||
template lambda: untyped = line.x
|
template lambda: untyped = line.x
|
||||||
template theta: untyped = line.z
|
template theta: untyped = line.z
|
||||||
|
@ -275,7 +275,7 @@ func line_eval_fused_add[F](
|
||||||
|
|
||||||
# Line evaluation
|
# Line evaluation
|
||||||
theta.neg()
|
theta.neg()
|
||||||
when F.C.getSexticTwist() == M_Twist:
|
when Field.C.getSexticTwist() == M_Twist:
|
||||||
lambda *= SexticNonResidue # A = ξ (X₁ - Z₁X₂)
|
lambda *= SexticNonResidue # A = ξ (X₁ - Z₁X₂)
|
||||||
|
|
||||||
# Public proc
|
# Public proc
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
../config/common,
|
../config/[common, curves],
|
||||||
../primitives,
|
../primitives,
|
||||||
../arithmetic
|
../arithmetic
|
||||||
|
|
||||||
|
@ -30,46 +30,55 @@ type
|
||||||
##
|
##
|
||||||
## Placeholder for the appropriate quadratic, cubic or sectic non-residue
|
## Placeholder for the appropriate quadratic, cubic or sectic non-residue
|
||||||
|
|
||||||
CubicExt* = concept x
|
QuadraticExt*[F] = object
|
||||||
## Cubic Extension field concept
|
## Quadratic Extension field
|
||||||
type BaseField = auto
|
coords*: array[2, F]
|
||||||
x.c0 is BaseField
|
|
||||||
x.c1 is BaseField
|
|
||||||
x.c2 is BaseField
|
|
||||||
|
|
||||||
QuadraticExt* = concept x
|
CubicExt*[F] = object
|
||||||
## Quadratic Extension field concept
|
## Cubic Extension field
|
||||||
not(x is CubicExt)
|
coords*: array[3, F]
|
||||||
|
|
||||||
type BaseField = auto
|
ExtensionField*[F] = QuadraticExt[F] or CubicExt[F]
|
||||||
x.c0 is BaseField
|
|
||||||
x.c1 is BaseField
|
|
||||||
|
|
||||||
ExtensionField* = QuadraticExt or CubicExt
|
template c0*(a: ExtensionField): auto =
|
||||||
|
a.coords[0]
|
||||||
|
template c1*(a: ExtensionField): auto =
|
||||||
|
a.coords[1]
|
||||||
|
template c2*(a: CubicExt): auto =
|
||||||
|
a.coords[2]
|
||||||
|
|
||||||
|
template `c0=`*(a: ExtensionField, v: auto) =
|
||||||
|
a.coords[0] = v
|
||||||
|
template `c1=`*(a: ExtensionField, v: auto) =
|
||||||
|
a.coords[1] = v
|
||||||
|
template `c2=`*(a: CubicExt, v: auto) =
|
||||||
|
a.coords[2] = v
|
||||||
|
|
||||||
|
template C*(E: type ExtensionField): Curve =
|
||||||
|
E.F.C
|
||||||
|
|
||||||
|
template fieldMod*(E: type ExtensionField): auto =
|
||||||
|
Fp[E.F.C].fieldMod()
|
||||||
|
|
||||||
# Initialization
|
# Initialization
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
|
|
||||||
func setZero*(a: var ExtensionField) =
|
func setZero*(a: var ExtensionField) =
|
||||||
## Set ``a`` to 0 in the extension field
|
## Set ``a`` to 0 in the extension field
|
||||||
for field in fields(a):
|
staticFor i, 0, a.coords.len:
|
||||||
field.setZero()
|
a.coords[i].setZero()
|
||||||
|
|
||||||
func setOne*(a: var ExtensionField) =
|
func setOne*(a: var ExtensionField) =
|
||||||
## Set ``a`` to 1 in the extension field
|
## Set ``a`` to 1 in the extension field
|
||||||
for fieldName, fA in fieldPairs(a):
|
a.coords[0].setOne()
|
||||||
when fieldName == "c0":
|
staticFor i, 1, a.coords.len:
|
||||||
fA.setOne()
|
a.coords[i].setZero()
|
||||||
else:
|
|
||||||
fA.setZero()
|
|
||||||
|
|
||||||
func fromBig*(a: var ExtensionField, src: BigInt) =
|
func fromBig*(a: var ExtensionField, src: BigInt) =
|
||||||
## Set ``a`` to the bigint value in the extension field
|
## Set ``a`` to the bigint value in the extension field
|
||||||
for fieldName, fA in fieldPairs(a):
|
a.coords[0].fromBig(src)
|
||||||
when fieldName == "c0":
|
staticFor i, 1, a.coords.len:
|
||||||
fA.fromBig(src)
|
a.coords[i].setZero()
|
||||||
else:
|
|
||||||
fA.setZero()
|
|
||||||
|
|
||||||
# Comparison
|
# Comparison
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
|
@ -77,32 +86,28 @@ func fromBig*(a: var ExtensionField, src: BigInt) =
|
||||||
func `==`*(a, b: ExtensionField): SecretBool =
|
func `==`*(a, b: ExtensionField): SecretBool =
|
||||||
## Constant-time equality check
|
## Constant-time equality check
|
||||||
result = CtTrue
|
result = CtTrue
|
||||||
for fA, fB in fields(a, b):
|
staticFor i, 0, a.coords.len:
|
||||||
result = result and (fA == fB)
|
result = result and (a.coords[i] == b.coords[i])
|
||||||
|
|
||||||
func isZero*(a: ExtensionField): SecretBool =
|
func isZero*(a: ExtensionField): SecretBool =
|
||||||
## Constant-time check if zero
|
## Constant-time check if zero
|
||||||
result = CtTrue
|
result = CtTrue
|
||||||
for fA in fields(a):
|
staticFor i, 0, a.coords.len:
|
||||||
result = result and fA.isZero()
|
result = result and a.coords[i].isZero()
|
||||||
|
|
||||||
func isOne*(a: ExtensionField): SecretBool =
|
func isOne*(a: ExtensionField): SecretBool =
|
||||||
## Constant-time check if one
|
## Constant-time check if one
|
||||||
result = CtTrue
|
result = CtTrue
|
||||||
for fieldName, fA in fieldPairs(a):
|
result = result and a.coords[0].isOne()
|
||||||
when fieldName == "c0":
|
staticFor i, 1, a.coords.len:
|
||||||
result = result and fA.isOne()
|
result = result and a.coords[i].isZero()
|
||||||
else:
|
|
||||||
result = result and fA.isZero()
|
|
||||||
|
|
||||||
func isMinusOne*(a: ExtensionField): SecretBool =
|
func isMinusOne*(a: ExtensionField): SecretBool =
|
||||||
## Constant-time check if -1
|
## Constant-time check if -1
|
||||||
result = CtTrue
|
result = CtTrue
|
||||||
for fieldName, fA in fieldPairs(a):
|
result = result and a.coords[0].isMinusOne()
|
||||||
when fieldName == "c0":
|
staticFor i, 1, a.coords.len:
|
||||||
result = result and fA.isMinusOne()
|
result = result and a.coords[i].isZero()
|
||||||
else:
|
|
||||||
result = result and fA.isZero()
|
|
||||||
|
|
||||||
# Copies
|
# Copies
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
|
@ -112,68 +117,56 @@ func ccopy*(a: var ExtensionField, b: ExtensionField, ctl: SecretBool) =
|
||||||
## If ctl is true: b is copied into a
|
## If ctl is true: b is copied into a
|
||||||
## if ctl is false: b is not copied and a is unmodified
|
## if ctl is false: b is not copied and a is unmodified
|
||||||
## Time and memory accesses are the same whether a copy occurs or not
|
## Time and memory accesses are the same whether a copy occurs or not
|
||||||
for fA, fB in fields(a, b):
|
staticFor i, 0, a.coords.len:
|
||||||
ccopy(fA, fB, ctl)
|
a.coords[i].ccopy(b.coords[i], ctl)
|
||||||
|
|
||||||
# Abelian group
|
# Abelian group
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
|
|
||||||
func neg*(r: var ExtensionField, a: ExtensionField) =
|
func neg*(r: var ExtensionField, a: ExtensionField) =
|
||||||
## Field out-of-place negation
|
## Field out-of-place negation
|
||||||
for fR, fA in fields(r, a):
|
staticFor i, 0, a.coords.len:
|
||||||
fR.neg(fA)
|
r.coords[i].neg(a.coords[i])
|
||||||
|
|
||||||
func neg*(a: var ExtensionField) =
|
func neg*(a: var ExtensionField) =
|
||||||
## Field in-place negation
|
## Field in-place negation
|
||||||
for fA in fields(a):
|
staticFor i, 0, a.coords.len:
|
||||||
fA.neg()
|
a.coords[i].neg()
|
||||||
|
|
||||||
func `+=`*(a: var ExtensionField, b: ExtensionField) =
|
func `+=`*(a: var ExtensionField, b: ExtensionField) =
|
||||||
## Addition in the extension field
|
## Addition in the extension field
|
||||||
for fA, fB in fields(a, b):
|
staticFor i, 0, a.coords.len:
|
||||||
fA += fB
|
a.coords[i] += b.coords[i]
|
||||||
|
|
||||||
func `-=`*(a: var ExtensionField, b: ExtensionField) =
|
func `-=`*(a: var ExtensionField, b: ExtensionField) =
|
||||||
## Substraction in the extension field
|
## Substraction in the extension field
|
||||||
for fA, fB in fields(a, b):
|
staticFor i, 0, a.coords.len:
|
||||||
fA -= fB
|
a.coords[i] -= b.coords[i]
|
||||||
|
|
||||||
func double*(r: var ExtensionField, a: ExtensionField) =
|
func double*(r: var ExtensionField, a: ExtensionField) =
|
||||||
## Field out-of-place doubling
|
## Field out-of-place doubling
|
||||||
for fR, fA in fields(r, a):
|
staticFor i, 0, a.coords.len:
|
||||||
fR.double(fA)
|
r.coords[i].double(a.coords[i])
|
||||||
|
|
||||||
func double*(a: var ExtensionField) =
|
func double*(a: var ExtensionField) =
|
||||||
## Field in-place doubling
|
## Field in-place doubling
|
||||||
for fA in fields(a):
|
staticFor i, 0, a.coords.len:
|
||||||
fA.double()
|
a.coords[i].double()
|
||||||
|
|
||||||
func div2*(a: var ExtensionField) =
|
func div2*(a: var ExtensionField) =
|
||||||
## Field in-place division by 2
|
## Field in-place division by 2
|
||||||
for fA in fields(a):
|
staticFor i, 0, a.coords.len:
|
||||||
fA.div2()
|
a.coords[i].div2()
|
||||||
|
|
||||||
func sum*(r: var QuadraticExt, a, b: QuadraticExt) =
|
func sum*(r: var ExtensionField, a, b: ExtensionField) =
|
||||||
## Sum ``a`` and ``b`` into ``r``
|
## Sum ``a`` and ``b`` into ``r``
|
||||||
r.c0.sum(a.c0, b.c0)
|
staticFor i, 0, a.coords.len:
|
||||||
r.c1.sum(a.c1, b.c1)
|
r.coords[i].sum(a.coords[i], b.coords[i])
|
||||||
|
|
||||||
func sum*(r: var CubicExt, a, b: CubicExt) =
|
func diff*(r: var ExtensionField, a, b: ExtensionField) =
|
||||||
## Sum ``a`` and ``b`` into ``r``
|
|
||||||
r.c0.sum(a.c0, b.c0)
|
|
||||||
r.c1.sum(a.c1, b.c1)
|
|
||||||
r.c2.sum(a.c2, b.c2)
|
|
||||||
|
|
||||||
func diff*(r: var QuadraticExt, a, b: QuadraticExt) =
|
|
||||||
## Diff ``a`` and ``b`` into ``r``
|
## Diff ``a`` and ``b`` into ``r``
|
||||||
r.c0.diff(a.c0, b.c0)
|
staticFor i, 0, a.coords.len:
|
||||||
r.c1.diff(a.c1, b.c1)
|
r.coords[i].diff(a.coords[i], b.coords[i])
|
||||||
|
|
||||||
func diff*(r: var CubicExt, a, b: CubicExt) =
|
|
||||||
## Diff ``a`` and ``b`` into ``r``
|
|
||||||
r.c0.diff(a.c0, b.c0)
|
|
||||||
r.c1.diff(a.c1, b.c1)
|
|
||||||
r.c2.diff(a.c2, b.c2)
|
|
||||||
|
|
||||||
func conj*(a: var QuadraticExt) =
|
func conj*(a: var QuadraticExt) =
|
||||||
## Computes the conjugate in-place
|
## Computes the conjugate in-place
|
||||||
|
@ -211,18 +204,18 @@ func conj*(r: var CubicExt, a: CubicExt) =
|
||||||
func cneg*(a: var ExtensionField, ctl: SecretBool) =
|
func cneg*(a: var ExtensionField, ctl: SecretBool) =
|
||||||
## Constant-time in-place conditional negation
|
## Constant-time in-place conditional negation
|
||||||
## Only negate if ctl is true
|
## Only negate if ctl is true
|
||||||
for fA in fields(a):
|
staticFor i, 0, a.coords.len:
|
||||||
fA.cneg(ctl)
|
a.coords[i].cneg(ctl)
|
||||||
|
|
||||||
func cadd*(a: var ExtensionField, b: ExtensionField, ctl: SecretBool) =
|
func cadd*(a: var ExtensionField, b: ExtensionField, ctl: SecretBool) =
|
||||||
## Constant-time in-place conditional addition
|
## Constant-time in-place conditional addition
|
||||||
for fA, fB in fields(a, b):
|
staticFor i, 0, a.coords.len:
|
||||||
fA.cadd(fB, ctl)
|
a.coords[i].cadd(b.coords[i], ctl)
|
||||||
|
|
||||||
func csub*(a: var ExtensionField, b: ExtensionField, ctl: SecretBool) =
|
func csub*(a: var ExtensionField, b: ExtensionField, ctl: SecretBool) =
|
||||||
## Constant-time in-place conditional substraction
|
## Constant-time in-place conditional substraction
|
||||||
for fA, fB in fields(a, b):
|
staticFor i, 0, a.coords.len:
|
||||||
fA.csub(fB, ctl)
|
a.coords[i].csub(b.coords[i], ctl)
|
||||||
|
|
||||||
# Multiplication by a small integer known at compile-time
|
# Multiplication by a small integer known at compile-time
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
|
@ -603,10 +596,9 @@ func mul_sparse_generic_by_0y(
|
||||||
var t{.noInit.}: typeof(a.c0)
|
var t{.noInit.}: typeof(a.c0)
|
||||||
|
|
||||||
t.prod(a.c1, b)
|
t.prod(a.c1, b)
|
||||||
t *= NonResidue
|
|
||||||
r.c1.prod(a.c0, b)
|
r.c1.prod(a.c0, b)
|
||||||
# aliasing: a unneeded now
|
# aliasing: a unneeded now
|
||||||
r.c0 = t
|
r.c0.prod(t, NonResidue)
|
||||||
|
|
||||||
func mul_sparse_generic_by_0y(
|
func mul_sparse_generic_by_0y(
|
||||||
r: var QuadraticExt, a: QuadraticExt,
|
r: var QuadraticExt, a: QuadraticExt,
|
||||||
|
@ -627,10 +619,9 @@ func mul_sparse_generic_by_0y(
|
||||||
var t{.noInit.}: typeof(a.c0)
|
var t{.noInit.}: typeof(a.c0)
|
||||||
|
|
||||||
t.prod(a.c1, b)
|
t.prod(a.c1, b)
|
||||||
t *= NonResidue
|
|
||||||
r.c1.prod(a.c0, b)
|
r.c1.prod(a.c0, b)
|
||||||
# aliasing: a unneeded now
|
# aliasing: a unneeded now
|
||||||
r.c0 = t
|
r.c0.prod(t, NonResidue)
|
||||||
|
|
||||||
func invImpl(r: var QuadraticExt, a: QuadraticExt) =
|
func invImpl(r: var QuadraticExt, a: QuadraticExt) =
|
||||||
## Compute the multiplicative inverse of ``a``
|
## Compute the multiplicative inverse of ``a``
|
||||||
|
|
|
@ -43,8 +43,8 @@ func prod*(r: var Fp, a: Fp, _: type NonResidue){.inline.} =
|
||||||
# ----------------------------------------------------------------
|
# ----------------------------------------------------------------
|
||||||
|
|
||||||
type
|
type
|
||||||
Fp2*[C: static Curve] = object
|
Fp2*[C: static Curve] =
|
||||||
c0*, c1*: Fp[C]
|
QuadraticExt[Fp[C]]
|
||||||
|
|
||||||
template fromComplexExtension*[F](elem: F): static bool =
|
template fromComplexExtension*[F](elem: F): static bool =
|
||||||
## Returns true if the input is a complex extension
|
## Returns true if the input is a complex extension
|
||||||
|
@ -190,11 +190,11 @@ func `/=`*(a: var Fp2, _: type NonResidue) {.inline.} =
|
||||||
# ----------------------------------------------------------------
|
# ----------------------------------------------------------------
|
||||||
|
|
||||||
type
|
type
|
||||||
Fp4*[C: static Curve] = object
|
Fp4*[C: static Curve] =
|
||||||
c0*, c1*: Fp2[C]
|
QuadraticExt[Fp2[C]]
|
||||||
|
|
||||||
Fp6*[C: static Curve] = object
|
Fp6*[C: static Curve] =
|
||||||
c0*, c1*, c2*: Fp2[C]
|
CubicExt[Fp2[C]]
|
||||||
|
|
||||||
func prod*(r: var Fp4, a: Fp4, _: type NonResidue) =
|
func prod*(r: var Fp4, a: Fp4, _: type NonResidue) =
|
||||||
## Multiply an element of 𝔽p4 by the non-residue
|
## Multiply an element of 𝔽p4 by the non-residue
|
||||||
|
@ -253,9 +253,8 @@ func `*=`*(a: var Fp6, _: type NonResidue) {.inline.} =
|
||||||
# ----------------------------------------------------------------
|
# ----------------------------------------------------------------
|
||||||
|
|
||||||
type
|
type
|
||||||
Fp12*[C: static Curve] = object
|
Fp12*[C: static Curve] =
|
||||||
c0*, c1*, c2*: Fp4[C]
|
CubicExt[Fp4[C]]
|
||||||
# c0*, c1*: Fp6[C]
|
|
||||||
|
|
||||||
# Sparse functions
|
# Sparse functions
|
||||||
# ----------------------------------------------------------------
|
# ----------------------------------------------------------------
|
||||||
|
|
|
@ -151,8 +151,8 @@ func random_unsafe(rng: var RngState, a: var FF) =
|
||||||
func random_unsafe(rng: var RngState, a: var ExtensionField) =
|
func random_unsafe(rng: var RngState, a: var ExtensionField) =
|
||||||
## Recursively initialize an extension Field element
|
## Recursively initialize an extension Field element
|
||||||
## Unsafe: for testing and benchmarking purposes only
|
## Unsafe: for testing and benchmarking purposes only
|
||||||
for field in fields(a):
|
for i in 0 ..< a.coords.len:
|
||||||
rng.random_unsafe(field)
|
rng.random_unsafe(a.coords[i])
|
||||||
|
|
||||||
func random_word_highHammingWeight(rng: var RngState): BaseType =
|
func random_word_highHammingWeight(rng: var RngState): BaseType =
|
||||||
let numZeros = rng.random_unsafe(WordBitWidth div 3) # Average Hamming Weight is 1-0.33/2 = 0.83
|
let numZeros = rng.random_unsafe(WordBitWidth div 3) # Average Hamming Weight is 1-0.33/2 = 0.83
|
||||||
|
@ -182,8 +182,8 @@ func random_highHammingWeight(rng: var RngState, a: var FF) =
|
||||||
func random_highHammingWeight(rng: var RngState, a: var ExtensionField) =
|
func random_highHammingWeight(rng: var RngState, a: var ExtensionField) =
|
||||||
## Recursively initialize an extension Field element
|
## Recursively initialize an extension Field element
|
||||||
## Unsafe: for testing and benchmarking purposes only
|
## Unsafe: for testing and benchmarking purposes only
|
||||||
for field in fields(a):
|
for i in 0 ..< a.coords.len:
|
||||||
rng.random_highHammingWeight(field)
|
rng.random_highHammingWeight(a.coords[i])
|
||||||
|
|
||||||
func random_long01Seq(rng: var RngState, a: var openArray[byte]) =
|
func random_long01Seq(rng: var RngState, a: var openArray[byte]) =
|
||||||
## Initialize a bytearray
|
## Initialize a bytearray
|
||||||
|
@ -227,8 +227,8 @@ func random_long01Seq(rng: var RngState, a: var FF) =
|
||||||
func random_long01Seq(rng: var RngState, a: var ExtensionField) =
|
func random_long01Seq(rng: var RngState, a: var ExtensionField) =
|
||||||
## Recursively initialize an extension Field element
|
## Recursively initialize an extension Field element
|
||||||
## Unsafe: for testing and benchmarking purposes only
|
## Unsafe: for testing and benchmarking purposes only
|
||||||
for field in fields(a):
|
for i in 0 ..< a.coords.len:
|
||||||
rng.random_long01Seq(field)
|
rng.random_long01Seq(a.coords[i])
|
||||||
|
|
||||||
# Elliptic curves
|
# Elliptic curves
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
|
|
|
@ -73,7 +73,7 @@ proc runFrobeniusTowerTests*[N](
|
||||||
var fa {.noInit.}: typeof(a)
|
var fa {.noInit.}: typeof(a)
|
||||||
fa.frobenius_map(a, k = 1)
|
fa.frobenius_map(a, k = 1)
|
||||||
|
|
||||||
a.powUnsafeExponent(Field.C.Mod, window = 3)
|
a.powUnsafeExponent(Field.fieldMod(), window = 3)
|
||||||
check: bool(a == fa)
|
check: bool(a == fa)
|
||||||
|
|
||||||
staticFor(curve, TestCurves):
|
staticFor(curve, TestCurves):
|
||||||
|
@ -89,8 +89,8 @@ proc runFrobeniusTowerTests*[N](
|
||||||
var fa {.noInit.}: typeof(a)
|
var fa {.noInit.}: typeof(a)
|
||||||
fa.frobenius_map(a, k = 2)
|
fa.frobenius_map(a, k = 2)
|
||||||
|
|
||||||
a.powUnsafeExponent(Field.C.Mod, window = 3)
|
a.powUnsafeExponent(Field.fieldMod(), window = 3)
|
||||||
a.powUnsafeExponent(Field.C.Mod, window = 3)
|
a.powUnsafeExponent(Field.fieldMod(), window = 3)
|
||||||
|
|
||||||
check:
|
check:
|
||||||
bool(a == fa)
|
bool(a == fa)
|
||||||
|
@ -108,9 +108,9 @@ proc runFrobeniusTowerTests*[N](
|
||||||
var fa {.noInit.}: typeof(a)
|
var fa {.noInit.}: typeof(a)
|
||||||
fa.frobenius_map(a, k = 3)
|
fa.frobenius_map(a, k = 3)
|
||||||
|
|
||||||
a.powUnsafeExponent(Field.C.Mod, window = 3)
|
a.powUnsafeExponent(Field.fieldMod(), window = 3)
|
||||||
a.powUnsafeExponent(Field.C.Mod, window = 3)
|
a.powUnsafeExponent(Field.fieldMod(), window = 3)
|
||||||
a.powUnsafeExponent(Field.C.Mod, window = 3)
|
a.powUnsafeExponent(Field.fieldMod(), window = 3)
|
||||||
check: bool(a == fa)
|
check: bool(a == fa)
|
||||||
|
|
||||||
staticFor(curve, TestCurves):
|
staticFor(curve, TestCurves):
|
||||||
|
|
Loading…
Reference in New Issue