Add multiplication in 𝔽p6 = 𝔽p2[∛(1+𝑖)]
This commit is contained in:
parent
964533494f
commit
ff4a54daba
|
@ -40,10 +40,10 @@ proc main() =
|
||||||
echo "-".repeat(80)
|
echo "-".repeat(80)
|
||||||
staticFor i, 0, AvailableCurves.len:
|
staticFor i, 0, AvailableCurves.len:
|
||||||
const curve = AvailableCurves[i]
|
const curve = AvailableCurves[i]
|
||||||
# addBench(Fp6[curve], Iters)
|
addBench(Fp6[curve], Iters)
|
||||||
# subBench(Fp6[curve], Iters)
|
subBench(Fp6[curve], Iters)
|
||||||
# negBench(Fp6[curve], Iters)
|
negBench(Fp6[curve], Iters)
|
||||||
# mulBench(Fp6[curve], Iters)
|
mulBench(Fp6[curve], Iters)
|
||||||
sqrBench(Fp6[curve], Iters)
|
sqrBench(Fp6[curve], Iters)
|
||||||
# invBench(Fp6[curve], InvIters)
|
# invBench(Fp6[curve], InvIters)
|
||||||
echo "-".repeat(80)
|
echo "-".repeat(80)
|
||||||
|
|
|
@ -48,8 +48,9 @@ task test, "Run all tests":
|
||||||
|
|
||||||
test "", "tests/test_finite_fields_vs_gmp.nim"
|
test "", "tests/test_finite_fields_vs_gmp.nim"
|
||||||
|
|
||||||
# 𝔽p2
|
# Towers of extension fields
|
||||||
test "", "tests/test_fp2.nim"
|
test "", "tests/test_fp2.nim"
|
||||||
|
test "", "tests/test_fp6.nim"
|
||||||
|
|
||||||
if sizeof(int) == 8: # 32-bit tests
|
if sizeof(int) == 8: # 32-bit tests
|
||||||
# Primitives
|
# Primitives
|
||||||
|
@ -70,8 +71,9 @@ task test, "Run all tests":
|
||||||
|
|
||||||
test "-d:Constantine32", "tests/test_finite_fields_vs_gmp.nim"
|
test "-d:Constantine32", "tests/test_finite_fields_vs_gmp.nim"
|
||||||
|
|
||||||
# 𝔽p2
|
# Towers of extension fields
|
||||||
test "", "tests/test_fp2.nim"
|
test "", "tests/test_fp2.nim"
|
||||||
|
test "", "tests/test_fp6.nim"
|
||||||
|
|
||||||
task test_no_gmp, "Run tests that don't require GMP":
|
task test_no_gmp, "Run tests that don't require GMP":
|
||||||
# -d:testingCurves is configured in a *.nim.cfg for convenience
|
# -d:testingCurves is configured in a *.nim.cfg for convenience
|
||||||
|
@ -90,8 +92,9 @@ task test_no_gmp, "Run tests that don't require GMP":
|
||||||
test "", "tests/test_finite_fields_mulsquare.nim"
|
test "", "tests/test_finite_fields_mulsquare.nim"
|
||||||
test "", "tests/test_finite_fields_powinv.nim"
|
test "", "tests/test_finite_fields_powinv.nim"
|
||||||
|
|
||||||
# 𝔽p2
|
# Towers of extension fields
|
||||||
test "", "tests/test_fp2.nim"
|
test "", "tests/test_fp2.nim"
|
||||||
|
test "", "tests/test_fp6.nim"
|
||||||
|
|
||||||
if sizeof(int) == 8: # 32-bit tests
|
if sizeof(int) == 8: # 32-bit tests
|
||||||
# Primitives
|
# Primitives
|
||||||
|
@ -108,8 +111,9 @@ task test_no_gmp, "Run tests that don't require GMP":
|
||||||
test "-d:Constantine32", "tests/test_finite_fields_mulsquare.nim"
|
test "-d:Constantine32", "tests/test_finite_fields_mulsquare.nim"
|
||||||
test "-d:Constantine32", "tests/test_finite_fields_powinv.nim"
|
test "-d:Constantine32", "tests/test_finite_fields_powinv.nim"
|
||||||
|
|
||||||
# 𝔽p2
|
# Towers of extension fields
|
||||||
test "", "tests/test_fp2.nim"
|
test "", "tests/test_fp2.nim"
|
||||||
|
test "", "tests/test_fp6.nim"
|
||||||
|
|
||||||
proc runBench(benchName: string, compiler = "") =
|
proc runBench(benchName: string, compiler = "") =
|
||||||
if not dirExists "build":
|
if not dirExists "build":
|
||||||
|
|
|
@ -99,6 +99,19 @@ func diff*(r: var CubicExtAddGroup, a, b: CubicExtAddGroup) =
|
||||||
r.c1.diff(a.c1, b.c1)
|
r.c1.diff(a.c1, b.c1)
|
||||||
r.c2.diff(a.c2, b.c2)
|
r.c2.diff(a.c2, b.c2)
|
||||||
|
|
||||||
|
func neg*(r: var CubicExtAddGroup, a: CubicExtAddGroup) =
|
||||||
|
## Negate ``a`` and store the result into r
|
||||||
|
r.c0.neg(a.c0)
|
||||||
|
r.c1.neg(a.c1)
|
||||||
|
r.c2.neg(a.c2)
|
||||||
|
|
||||||
|
# TODO: The type system is lost with out-of-place result concepts
|
||||||
|
# func `+`*(a, b: CubicExtAddGroup): CubicExtAddGroup =
|
||||||
|
# result.sum(a, b)
|
||||||
|
#
|
||||||
|
# func `-`*(a, b: CubicExtAddGroup): CubicExtAddGroup =
|
||||||
|
# result.sum(a, b)
|
||||||
|
|
||||||
# ############################################################
|
# ############################################################
|
||||||
#
|
#
|
||||||
# Quadratic Extension fields
|
# Quadratic Extension fields
|
||||||
|
@ -165,3 +178,10 @@ func neg*(r: var QuadExtAddGroup, a: QuadExtAddGroup) =
|
||||||
## Negate ``a`` into ``r``
|
## Negate ``a`` into ``r``
|
||||||
r.c0.neg(a.c0)
|
r.c0.neg(a.c0)
|
||||||
r.c1.neg(a.c1)
|
r.c1.neg(a.c1)
|
||||||
|
|
||||||
|
# TODO: The type system is lost with out-of-place result concepts
|
||||||
|
# func `+`*(a, b: CubicExtAddGroup): CubicExtAddGroup =
|
||||||
|
# result.sum(a, b)
|
||||||
|
#
|
||||||
|
# func `-`*(a, b: CubicExtAddGroup): CubicExtAddGroup =
|
||||||
|
# result.sum(a, b)
|
||||||
|
|
|
@ -157,3 +157,9 @@ func inv*(r: var Fp2, a: Fp2) =
|
||||||
r.c0.prod(a.c0, t0) # r0 = a0 / (a0² + a1²)
|
r.c0.prod(a.c0, t0) # r0 = a0 / (a0² + a1²)
|
||||||
t1.neg(t0) # t0 = -1 / (a0² + a1²)
|
t1.neg(t0) # t0 = -1 / (a0² + a1²)
|
||||||
r.c1.prod(a.c1, t1) # r1 = -a1 / (a0² + a1²)
|
r.c1.prod(a.c1, t1) # r1 = -a1 / (a0² + a1²)
|
||||||
|
|
||||||
|
func `*=`*(a: var Fp2, b: Fp2) {.inline.} =
|
||||||
|
a.prod(a, b)
|
||||||
|
|
||||||
|
func `*`*(a, b: Fp2): Fp2 {.inline.} =
|
||||||
|
result.prod(a, b)
|
||||||
|
|
|
@ -50,17 +50,25 @@ func `*`(_: typedesc[Xi], a: Fp2): Fp2 =
|
||||||
## Multiply an element of 𝔽p2 by 𝔽p6 cubic non-residue 1 + 𝑖
|
## Multiply an element of 𝔽p2 by 𝔽p6 cubic non-residue 1 + 𝑖
|
||||||
## (c0 + c1 𝑖) (1 + 𝑖) => c0 + (c0 + c1)𝑖 + c1 𝑖²
|
## (c0 + c1 𝑖) (1 + 𝑖) => c0 + (c0 + c1)𝑖 + c1 𝑖²
|
||||||
## => c0 - c1 + (c0 + c1) 𝑖
|
## => c0 - c1 + (c0 + c1) 𝑖
|
||||||
result.c0 = a.c0 - a.c1
|
result.c0.diff(a.c0, a.c1)
|
||||||
result.c1 = a.c0 + a.c1
|
result.c1.sum(a.c0, a.c1)
|
||||||
|
|
||||||
template `*`(a: Fp2, _: typedesc[Xi]): Fp2 =
|
template `*`(a: Fp2, _: typedesc[Xi]): Fp2 =
|
||||||
Xi * a
|
Xi * a
|
||||||
|
|
||||||
|
func `*=`(a: var Fp2, _: typedesc[Xi]) =
|
||||||
|
## Inplace multiply an element of 𝔽p2 by 𝔽p6 cubic non-residue 1 + 𝑖
|
||||||
|
let t = a.c0
|
||||||
|
a.c0 -= a.c1
|
||||||
|
a.c1 += t
|
||||||
|
|
||||||
func square*[C](r: var Fp6[C], a: Fp6[C]) =
|
func square*[C](r: var Fp6[C], a: Fp6[C]) =
|
||||||
## Return a²
|
## Returns r = a²
|
||||||
##
|
# Algorithm is Chung-Hasan Squaring SQR2
|
||||||
# Algorithm is Chung-Hasan Squaring SQR3
|
|
||||||
# http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf
|
# http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf
|
||||||
|
#
|
||||||
|
# TODO: change to SQR1 or SQR3 (requires div2)
|
||||||
|
# which are faster for the sizes we are interested in.
|
||||||
var v2{.noInit.}, v3{.noInit.}, v4{.noInit.}, v5{.noInit.}: Fp2[C]
|
var v2{.noInit.}, v3{.noInit.}, v4{.noInit.}, v5{.noInit.}: Fp2[C]
|
||||||
|
|
||||||
v4.prod(a.c0, a.c1)
|
v4.prod(a.c0, a.c1)
|
||||||
|
@ -80,3 +88,37 @@ func square*[C](r: var Fp6[C], a: Fp6[C]) =
|
||||||
r.c2.sum(v2, v4)
|
r.c2.sum(v2, v4)
|
||||||
r.c2 += v5
|
r.c2 += v5
|
||||||
r.c2 -= v3
|
r.c2 -= v3
|
||||||
|
|
||||||
|
func prod*[C](r: var Fp6[C], a, b: Fp6[C]) =
|
||||||
|
## Returns r = a * b
|
||||||
|
# Algorithm is Karatsuba
|
||||||
|
var v0{.noInit.}, v1{.noInit.}, v2{.noInit.}, t{.noInit.}: Fp2[C]
|
||||||
|
|
||||||
|
v0.prod(a.c0, b.c0)
|
||||||
|
v1.prod(a.c1, b.c1)
|
||||||
|
v2.prod(a.c2, b.c2)
|
||||||
|
|
||||||
|
# r.c0 = ((a.c1 + a.c2) * (b.c1 + b.c2) - v1 - v2) * Xi + v0
|
||||||
|
r.c0.sum(a.c1, a.c2)
|
||||||
|
t.sum(b.c1, b.c2)
|
||||||
|
r.c0 *= t
|
||||||
|
r.c0 -= v1
|
||||||
|
r.c0 -= v2
|
||||||
|
r.c0 *= Xi
|
||||||
|
r.c0 += v0
|
||||||
|
|
||||||
|
# r.c1 = (a.c0 + a.c1) * (b.c0 + b.c1) - v0 - v1 + Xi * v2
|
||||||
|
r.c1.sum(a.c0, a.c1)
|
||||||
|
t.sum(b.c0, b.c1)
|
||||||
|
r.c1 *= t
|
||||||
|
r.c1 -= v0
|
||||||
|
r.c1 -= v1
|
||||||
|
r.c1 += Xi * v2
|
||||||
|
|
||||||
|
# r.c2 = (a.c0 + a.c2) * (b.c0 + b.c2) - v0 - v2 + v1
|
||||||
|
r.c2.sum(a.c0, a.c2)
|
||||||
|
t.sum(b.c0, b.c2)
|
||||||
|
r.c2 *= t
|
||||||
|
r.c2 -= v0
|
||||||
|
r.c2 -= v2
|
||||||
|
r.c2 += v1
|
||||||
|
|
|
@ -43,16 +43,14 @@ suite "𝔽p6 = 𝔽p2[∛(1+𝑖)] (irreducible polynomial x³ - (1+𝑖))":
|
||||||
var r{.noinit.}: Fp6[C]
|
var r{.noinit.}: Fp6[C]
|
||||||
r.square(One)
|
r.square(One)
|
||||||
check: bool(r == One)
|
check: bool(r == One)
|
||||||
# block:
|
block:
|
||||||
# var r{.noinit.}: Fp6[C]
|
var r{.noinit.}: Fp6[C]
|
||||||
# r.prod(One, One)
|
r.prod(One, One)
|
||||||
# check: bool(r == One)
|
check: bool(r == One)
|
||||||
|
|
||||||
testInstance()
|
testInstance()
|
||||||
|
|
||||||
test(BN254)
|
test(BN254)
|
||||||
test(P256)
|
|
||||||
test(Secp256k1)
|
|
||||||
test(BLS12_377)
|
test(BLS12_377)
|
||||||
test(BLS12_381)
|
test(BLS12_381)
|
||||||
test(BN446)
|
test(BN446)
|
||||||
|
@ -75,16 +73,20 @@ suite "𝔽p6 = 𝔽p2[∛(1+𝑖)] (irreducible polynomial x³ - (1+𝑖))":
|
||||||
var Four: Fp6[C]
|
var Four: Fp6[C]
|
||||||
Four.double(Two)
|
Four.double(Two)
|
||||||
|
|
||||||
var r: Fp6[C]
|
block:
|
||||||
r.square(Two)
|
var r: Fp6[C]
|
||||||
|
r.square(Two)
|
||||||
|
|
||||||
check: bool(r == Four)
|
check: bool(r == Four)
|
||||||
|
block:
|
||||||
|
var r: Fp6[C]
|
||||||
|
r.prod(Two, Two)
|
||||||
|
|
||||||
|
check: bool(r == Four)
|
||||||
|
|
||||||
testInstance()
|
testInstance()
|
||||||
|
|
||||||
test(BN254)
|
test(BN254)
|
||||||
test(P256)
|
|
||||||
test(Secp256k1)
|
|
||||||
test(BLS12_377)
|
test(BLS12_377)
|
||||||
test(BLS12_381)
|
test(BLS12_381)
|
||||||
test(BN446)
|
test(BN446)
|
||||||
|
@ -109,16 +111,20 @@ suite "𝔽p6 = 𝔽p2[∛(1+𝑖)] (irreducible polynomial x³ - (1+𝑖))":
|
||||||
for _ in 0 ..< 9:
|
for _ in 0 ..< 9:
|
||||||
Nine += One
|
Nine += One
|
||||||
|
|
||||||
var u: Fp6[C]
|
block:
|
||||||
u.square(Three)
|
var u: Fp6[C]
|
||||||
|
u.square(Three)
|
||||||
|
|
||||||
check: bool(u == Nine)
|
check: bool(u == Nine)
|
||||||
|
block:
|
||||||
|
var u: Fp6[C]
|
||||||
|
u.prod(Three, Three)
|
||||||
|
|
||||||
|
check: bool(u == Nine)
|
||||||
|
|
||||||
testInstance()
|
testInstance()
|
||||||
|
|
||||||
test(BN254)
|
test(BN254)
|
||||||
test(P256)
|
|
||||||
test(Secp256k1)
|
|
||||||
test(BLS12_377)
|
test(BLS12_377)
|
||||||
test(BLS12_381)
|
test(BLS12_381)
|
||||||
test(BN446)
|
test(BN446)
|
||||||
|
@ -143,19 +149,80 @@ suite "𝔽p6 = 𝔽p2[∛(1+𝑖)] (irreducible polynomial x³ - (1+𝑖))":
|
||||||
for _ in 0 ..< 9:
|
for _ in 0 ..< 9:
|
||||||
Nine += One
|
Nine += One
|
||||||
|
|
||||||
var u: Fp6[C]
|
block:
|
||||||
u.square(MinusThree)
|
var u: Fp6[C]
|
||||||
|
u.square(MinusThree)
|
||||||
|
|
||||||
check: bool(u == Nine)
|
check: bool(u == Nine)
|
||||||
|
block:
|
||||||
|
var u: Fp6[C]
|
||||||
|
u.prod(MinusThree, MinusThree)
|
||||||
|
|
||||||
|
check: bool(u == Nine)
|
||||||
|
|
||||||
testInstance()
|
testInstance()
|
||||||
|
|
||||||
test(BN254)
|
test(BN254)
|
||||||
test(P256)
|
|
||||||
test(Secp256k1)
|
|
||||||
test(BLS12_377)
|
test(BLS12_377)
|
||||||
test(BLS12_381)
|
test(BLS12_381)
|
||||||
test(BN446)
|
test(BN446)
|
||||||
test(FKM12_447)
|
test(FKM12_447)
|
||||||
test(BLS12_461)
|
test(BLS12_461)
|
||||||
test(BN462)
|
test(BN462)
|
||||||
|
|
||||||
|
test "Multiplication by 0 and 1":
|
||||||
|
template test(C: static Curve, body: untyped) =
|
||||||
|
block:
|
||||||
|
proc testInstance() =
|
||||||
|
let Zero {.inject.} = block:
|
||||||
|
var Z{.noInit.}: Fp6[C]
|
||||||
|
Z.setZero()
|
||||||
|
Z
|
||||||
|
let One {.inject.} = block:
|
||||||
|
var O{.noInit.}: Fp6[C]
|
||||||
|
O.setOne()
|
||||||
|
O
|
||||||
|
|
||||||
|
for _ in 0 ..< 1: # Iters:
|
||||||
|
let x {.inject.} = rng.random(Fp6[C])
|
||||||
|
var r{.noinit, inject.}: Fp6[C]
|
||||||
|
body
|
||||||
|
|
||||||
|
testInstance()
|
||||||
|
|
||||||
|
test(BN254):
|
||||||
|
r.prod(x, Zero)
|
||||||
|
check: bool(r == Zero)
|
||||||
|
test(BN254):
|
||||||
|
r.prod(Zero, x)
|
||||||
|
check: bool(r == Zero)
|
||||||
|
test(BN254):
|
||||||
|
r.prod(x, One)
|
||||||
|
check: bool(r == x)
|
||||||
|
test(BN254):
|
||||||
|
r.prod(One, x)
|
||||||
|
check: bool(r == x)
|
||||||
|
test(BLS12_381):
|
||||||
|
r.prod(x, Zero)
|
||||||
|
check: bool(r == Zero)
|
||||||
|
test(BLS12_381):
|
||||||
|
r.prod(Zero, x)
|
||||||
|
check: bool(r == Zero)
|
||||||
|
test(BLS12_381):
|
||||||
|
r.prod(x, One)
|
||||||
|
check: bool(r == x)
|
||||||
|
test(BLS12_381):
|
||||||
|
r.prod(One, x)
|
||||||
|
check: bool(r == x)
|
||||||
|
test(BN462):
|
||||||
|
r.prod(x, Zero)
|
||||||
|
check: bool(r == Zero)
|
||||||
|
test(BN462):
|
||||||
|
r.prod(Zero, x)
|
||||||
|
check: bool(r == Zero)
|
||||||
|
test(BN462):
|
||||||
|
r.prod(x, One)
|
||||||
|
check: bool(r == x)
|
||||||
|
test(BN462):
|
||||||
|
r.prod(One, x)
|
||||||
|
check: bool(r == x)
|
||||||
|
|
Loading…
Reference in New Issue