diff --git a/constantine/tower_field_extensions/fp12_quad_fp6.nim b/constantine/tower_field_extensions/fp12_quad_fp6.nim index 169ad53..226bb0c 100644 --- a/constantine/tower_field_extensions/fp12_quad_fp6.nim +++ b/constantine/tower_field_extensions/fp12_quad_fp6.nim @@ -71,7 +71,7 @@ template `*`(a: Fp6, _: typedesc[Gamma]): Fp6 = func `*=`(a: var Fp6, _: typedesc[Gamma]) {.inline.} = a = Gamma * a -func square*[C](r: var Fp12[C], a: Fp12[C]) = +func square*(r: var Fp12, a: Fp12) = ## Return a² in ``r`` ## ``r`` is initialized/overwritten # (c0, c1)² => (c0 + c1 w)² @@ -106,3 +106,22 @@ func square*[C](r: var Fp12[C], a: Fp12[C]) = # r1 = 2 c0c1 r.c1.double() + +func prod*[C](r: var Fp12[C], a, b: Fp12[C]) = + ## Returns r = a * b + var t {.noInit.}: Fp6[C] + + # r1 <- (a0 + a1)(b0 + b1) + r.c0.sum(a.c0, a.c1) + t.sum(b.c0, b.c1) + r.c1.prod(r.c0, t) + + # r0 <- a0 b0 + γ a1 b1 + # r1 <- (a0 + a1)(b0 + b1) - a0 b0 - a1 b1 + r.c0.prod(a.c0, b.c0) + t.prod(a.c1, b.c1) + r.c1 -= r.c0 + r.c1 -= t + + # r0 <- a0 b0 + γ a1 b1 + r.c0 -= Gamma * t diff --git a/constantine/tower_field_extensions/fp2_complex.nim b/constantine/tower_field_extensions/fp2_complex.nim index eb29b6c..616a678 100644 --- a/constantine/tower_field_extensions/fp2_complex.nim +++ b/constantine/tower_field_extensions/fp2_complex.nim @@ -158,8 +158,12 @@ func inv*(r: var Fp2, a: Fp2) = t1.neg(t0) # t0 = -1 / (a0² + a1²) r.c1.prod(a.c1, t1) # r1 = -a1 / (a0² + a1²) +func square*(a: var Fp2) {.inline.} = + let t = a + a.square(t) + func `*=`*(a: var Fp2, b: Fp2) {.inline.} = a.prod(a, b) -func `*`*(a, b: Fp2): Fp2 {.inline.} = +func `*`*(a, b: Fp2): Fp2 {.inline, noInit.} = result.prod(a, b) diff --git a/constantine/tower_field_extensions/fp6_1_plus_i.nim b/constantine/tower_field_extensions/fp6_1_plus_i.nim index d00434e..1e97c36 100644 --- a/constantine/tower_field_extensions/fp6_1_plus_i.nim +++ b/constantine/tower_field_extensions/fp6_1_plus_i.nim @@ -81,7 +81,7 @@ func square*[C](r: var Fp6[C], a: Fp6[C]) = v4 += a.c2 v5.prod(a.c1, a.c2) v5.double() - v4.square(v4) + v4.square() r.c0 = Xi * v5 r.c0 += v3 r.c2.sum(v2, v4) @@ -178,9 +178,9 @@ func inv*[C](r: var Fp6[C], a: Fp6[C]) = r.c2.prod(v2, v3) func `*=`*(a: var Fp6, b: Fp6) {.inline.} = - var t: Fp6 - t.prod(a, b) - a = t + # Need to ensure different buffers for ``a`` and result + let t = a + a.prod(t, b) -func `*`*(a, b: Fp6): Fp6 {.inline.} = +func `*`*(a, b: Fp6): Fp6 {.inline, noInit.} = result.prod(a, b) diff --git a/tests/test_fp2.nim b/tests/test_fp2.nim index 068a0d1..73bfe72 100644 --- a/tests/test_fp2.nim +++ b/tests/test_fp2.nim @@ -53,8 +53,6 @@ suite "𝔽p2 = 𝔽p[𝑖] (irreducible polynomial x²+1)": test(BN254) test(BLS12_381) - test(P256) - test(Secp256k1) test "Squaring 1 returns 1": template test(C: static Curve) = @@ -76,8 +74,6 @@ suite "𝔽p2 = 𝔽p[𝑖] (irreducible polynomial x²+1)": testInstance() test(BN254) - test(P256) - test(Secp256k1) test(BLS12_377) test(BLS12_381) test(BN446) @@ -129,30 +125,29 @@ suite "𝔽p2 = 𝔽p[𝑖] (irreducible polynomial x²+1)": test(BLS12_381): r.prod(One, x) check: bool(r == x) - test(P256): - r.prod(x, Zero) - check: bool(r == Zero) - test(P256): - r.prod(Zero, x) - check: bool(r == Zero) - test(P256): - r.prod(x, One) - check: bool(r == x) - test(P256): - r.prod(One, x) - check: bool(r == x) - test(Secp256k1): - r.prod(x, Zero) - check: bool(r == Zero) - test(Secp256k1): - r.prod(Zero, x) - check: bool(r == Zero) - test(Secp256k1): - r.prod(x, One) - check: bool(r == x) - test(Secp256k1): - 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(Fp2[C]) + var rMul{.noInit.}, rSqr{.noInit.}: Fp2[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 "𝔽p2 = 𝔽p[𝑖] addition is associative and commutative": proc abelianGroup(curve: static Curve) = @@ -197,8 +192,6 @@ suite "𝔽p2 = 𝔽p[𝑖] (irreducible polynomial x²+1)": bool(r0 == r4) abelianGroup(BN254) - abelianGroup(P256) - abelianGroup(Secp256k1) abelianGroup(BLS12_377) abelianGroup(BLS12_381) abelianGroup(BN446) @@ -249,8 +242,6 @@ suite "𝔽p2 = 𝔽p[𝑖] (irreducible polynomial x²+1)": bool(r0 == r4) commutativeRing(BN254) - commutativeRing(P256) - commutativeRing(Secp256k1) commutativeRing(BLS12_377) commutativeRing(BLS12_381) commutativeRing(BN446) @@ -274,8 +265,6 @@ suite "𝔽p2 = 𝔽p[𝑖] (irreducible polynomial x²+1)": check: bool(r == one) mulInvOne(BN254) - mulInvOne(P256) - mulInvOne(Secp256k1) mulInvOne(BLS12_377) mulInvOne(BLS12_381) mulInvOne(BN446) diff --git a/tests/test_fp6.nim b/tests/test_fp6.nim index 39fdfd3..eb670b4 100644 --- a/tests/test_fp6.nim +++ b/tests/test_fp6.nim @@ -227,6 +227,29 @@ suite "𝔽p6 = 𝔽p2[∛(1+𝑖)] (irreducible polynomial x³ - (1+𝑖))": 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 ..< 1: # Iters: + let a = rng.random(Fp6[C]) + var rMul{.noInit.}, rSqr{.noInit.}: Fp6[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 "𝔽p6 = 𝔽p2[∛(1+𝑖)] addition is associative and commutative": proc abelianGroup(curve: static Curve) = for _ in 0 ..< Iters: @@ -270,8 +293,6 @@ suite "𝔽p6 = 𝔽p2[∛(1+𝑖)] (irreducible polynomial x³ - (1+𝑖))": bool(r0 == r4) abelianGroup(BN254) - abelianGroup(P256) - abelianGroup(Secp256k1) abelianGroup(BLS12_377) abelianGroup(BLS12_381) abelianGroup(BN446)