From 3a2b35ba26cb4770dfb642d9f9be6516289e8245 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mamy=20Andr=C3=A9-Ratsimbazafy?= Date: Thu, 9 Apr 2020 13:37:45 +0200 Subject: [PATCH] =?UTF-8?q?Fix=20multiplication=20in=20=F0=9D=94=BDp12?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tower_field_extensions/fp12_quad_fp6.nim | 6 +- tests/test_fp12.nim | 180 ++++++++++++++++++ tests/test_fp6.nim | 2 +- 3 files changed, 185 insertions(+), 3 deletions(-) diff --git a/constantine/tower_field_extensions/fp12_quad_fp6.nim b/constantine/tower_field_extensions/fp12_quad_fp6.nim index 226bb0c..54958c5 100644 --- a/constantine/tower_field_extensions/fp12_quad_fp6.nim +++ b/constantine/tower_field_extensions/fp12_quad_fp6.nim @@ -109,6 +109,8 @@ func square*(r: var Fp12, a: Fp12) = func prod*[C](r: var Fp12[C], a, b: Fp12[C]) = ## Returns r = a * b + # r0 = a0 b0 + γ a1 b1 + # r1 = (a0 + a1) (b0 + b1) - a0 b0 - a1 b1 (Karatsuba) var t {.noInit.}: Fp6[C] # r1 <- (a0 + a1)(b0 + b1) @@ -116,7 +118,7 @@ func prod*[C](r: var Fp12[C], a, b: Fp12[C]) = t.sum(b.c0, b.c1) r.c1.prod(r.c0, t) - # r0 <- a0 b0 + γ a1 b1 + # r0 <- a0 b0 # r1 <- (a0 + a1)(b0 + b1) - a0 b0 - a1 b1 r.c0.prod(a.c0, b.c0) t.prod(a.c1, b.c1) @@ -124,4 +126,4 @@ func prod*[C](r: var Fp12[C], a, b: Fp12[C]) = r.c1 -= t # r0 <- a0 b0 + γ a1 b1 - r.c0 -= Gamma * t + r.c0 += Gamma * t diff --git a/tests/test_fp12.nim b/tests/test_fp12.nim index 54b2264..4494d65 100644 --- a/tests/test_fp12.nim +++ b/tests/test_fp12.nim @@ -169,3 +169,183 @@ suite "𝔽p12 = 𝔽p6[√∛(1+𝑖)]": test(FKM12_447) test(BLS12_461) test(BN462) + + test "Multiplication by 0 and 1": + template test(C: static Curve, body: untyped) = + block: + proc testInstance() = + let Zero {.inject, used.} = block: + var Z{.noInit.}: Fp12[C] + Z.setZero() + Z + let One {.inject, used.} = block: + var O{.noInit.}: Fp12[C] + O.setOne() + O + + for _ in 0 ..< Iters: + let x {.inject.} = rng.random(Fp12[C]) + var r{.noinit, inject.}: Fp12[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) + + test "Multiplication and Squaring are consistent": + template test(C: static Curve) = + block: + proc testInstance() = + for _ in 0 ..< Iters: + let a = rng.random(Fp12[C]) + var rMul{.noInit.}, rSqr{.noInit.}: Fp12[C] + + rMul.prod(a, a) + rSqr.square(a) + + check: bool(rMul == rSqr) + + testInstance() + + test(BN254) + test(BLS12_377) + test(BLS12_381) + test(BN446) + test(FKM12_447) + test(BLS12_461) + test(BN462) + + test "𝔽p12 = 𝔽p6[√∛(1+𝑖)] addition is associative and commutative": + proc abelianGroup(curve: static Curve) = + for _ in 0 ..< Iters: + let a = rng.random(Fp12[curve]) + let b = rng.random(Fp12[curve]) + let c = rng.random(Fp12[curve]) + + var tmp1{.noInit.}, tmp2{.noInit.}: Fp12[curve] + + # r0 = (a + b) + c + tmp1.sum(a, b) + tmp2.sum(tmp1, c) + let r0 = tmp2 + + # r1 = a + (b + c) + tmp1.sum(b, c) + tmp2.sum(a, tmp1) + let r1 = tmp2 + + # r2 = (a + c) + b + tmp1.sum(a, c) + tmp2.sum(tmp1, b) + let r2 = tmp2 + + # r3 = a + (c + b) + tmp1.sum(c, b) + tmp2.sum(a, tmp1) + let r3 = tmp2 + + # r4 = (c + a) + b + tmp1.sum(c, a) + tmp2.sum(tmp1, b) + let r4 = tmp2 + + # ... + + check: + bool(r0 == r1) + bool(r0 == r2) + bool(r0 == r3) + bool(r0 == r4) + + abelianGroup(BN254) + abelianGroup(BLS12_377) + abelianGroup(BLS12_381) + abelianGroup(BN446) + abelianGroup(FKM12_447) + abelianGroup(BLS12_461) + abelianGroup(BN462) + + test "𝔽p12 = 𝔽p6[√∛(1+𝑖)] multiplication is associative and commutative": + proc commutativeRing(curve: static Curve) = + for _ in 0 ..< Iters: + let a = rng.random(Fp12[curve]) + let b = rng.random(Fp12[curve]) + let c = rng.random(Fp12[curve]) + + var tmp1{.noInit.}, tmp2{.noInit.}: Fp12[curve] + + # r0 = (a * b) * c + tmp1.prod(a, b) + tmp2.prod(tmp1, c) + let r0 = tmp2 + + # r1 = a * (b * c) + tmp1.prod(b, c) + tmp2.prod(a, tmp1) + let r1 = tmp2 + + # r2 = (a * c) * b + tmp1.prod(a, c) + tmp2.prod(tmp1, b) + let r2 = tmp2 + + # r3 = a * (c * b) + tmp1.prod(c, b) + tmp2.prod(a, tmp1) + let r3 = tmp2 + + # r4 = (c * a) * b + tmp1.prod(c, a) + tmp2.prod(tmp1, b) + let r4 = tmp2 + + # ... + + check: + bool(r0 == r1) + bool(r0 == r2) + bool(r0 == r3) + bool(r0 == r4) + + commutativeRing(BN254) + commutativeRing(BLS12_377) + commutativeRing(BLS12_381) + commutativeRing(BN446) + commutativeRing(FKM12_447) + commutativeRing(BLS12_461) + commutativeRing(BN462) diff --git a/tests/test_fp6.nim b/tests/test_fp6.nim index eb670b4..bafc4e8 100644 --- a/tests/test_fp6.nim +++ b/tests/test_fp6.nim @@ -231,7 +231,7 @@ suite "𝔽p6 = 𝔽p2[∛(1+𝑖)] (irreducible polynomial x³ - (1+𝑖))": template test(C: static Curve) = block: proc testInstance() = - for _ in 0 ..< 1: # Iters: + for _ in 0 ..< Iters: let a = rng.random(Fp6[C]) var rMul{.noInit.}, rSqr{.noInit.}: Fp6[C]