diff --git a/include/mcl/ec.hpp b/include/mcl/ec.hpp index 1ab508a..bbaabd7 100644 --- a/include/mcl/ec.hpp +++ b/include/mcl/ec.hpp @@ -1009,6 +1009,20 @@ public: { mulArrayBase(z, x, gmp::getUnit(y), gmp::getUnitSize(y), y < 0, constTime); } + /* + z = sum_{i=0}^{n-1} xVec[i] * yVec[i] + */ + templateclass FpT> + static inline void mulVec(EcT& z, const EcT *xVec, const FpT *yVec, size_t n) + { + EcT r, t; + r.clear(); + for (size_t i = 0; i < n; i++) { + mul(t, xVec[i], yVec[i]); + r += t; + } + z = r; + } #ifndef CYBOZU_DONT_USE_EXCEPTION static inline void init(const std::string& astr, const std::string& bstr, int mode = ec::Jacobi) { diff --git a/test/bls12_test.cpp b/test/bls12_test.cpp index 5af112f..c86fed2 100644 --- a/test/bls12_test.cpp +++ b/test/bls12_test.cpp @@ -6,6 +6,7 @@ cybozu::CpuClock clk; #include #include #include +#include "common_test.hpp" #if defined(__EMSCRIPTEN__) && !defined(MCL_AVOID_EXCEPTION_TEST) #define MCL_AVOID_EXCEPTION_TEST @@ -383,6 +384,7 @@ CYBOZU_TEST_AUTO(naive) testPairing(P, Q, ts.e); testPrecomputed(P, Q); testMillerLoop2(P, Q); + testCommon(); testBench(P, Q); } int count = (int)clk.getCount(); diff --git a/test/bn384_test.cpp b/test/bn384_test.cpp index b5674a9..a8c7cdb 100644 --- a/test/bn384_test.cpp +++ b/test/bn384_test.cpp @@ -5,6 +5,7 @@ #include #include #include +#include "common_test.hpp" using namespace mcl::bn384; @@ -39,6 +40,7 @@ void testCurve(const mcl::CurveParam& cp) pairing(e2, aP, bQ); GT::pow(e1, e1, a * b); CYBOZU_TEST_EQUAL(e1, e2); + testCommon(); testBench(P, Q); testSquareRoot(); testLagrange(); diff --git a/test/bn512_test.cpp b/test/bn512_test.cpp index 905bfd3..db2aff1 100644 --- a/test/bn512_test.cpp +++ b/test/bn512_test.cpp @@ -5,6 +5,7 @@ #include #include #include +#include "common_test.hpp" using namespace mcl::bn512; @@ -33,6 +34,7 @@ void testCurve(const mcl::CurveParam& cp) pairing(e2, aP, bQ); GT::pow(e1, e1, a * b); CYBOZU_TEST_EQUAL(e1, e2); + testCommon(); testBench(P, Q); testSquareRoot(); testLagrange(); diff --git a/test/bn_test.cpp b/test/bn_test.cpp index b66cad8..a2557a3 100644 --- a/test/bn_test.cpp +++ b/test/bn_test.cpp @@ -6,6 +6,7 @@ cybozu::CpuClock clk; #include #include #include +#include "common_test.hpp" #if defined(__EMSCRIPTEN__) && !defined(MCL_AVOID_EXCEPTION_TEST) #define MCL_AVOID_EXCEPTION_TEST @@ -401,6 +402,7 @@ CYBOZU_TEST_AUTO(naive) testPrecomputed(P, Q); testMillerLoop2(P, Q); testMillerLoopVec(); + testCommon(); testBench(P, Q); benchAddDblG1(); benchAddDblG2(); diff --git a/test/common_test.hpp b/test/common_test.hpp new file mode 100644 index 0000000..e29fd1f --- /dev/null +++ b/test/common_test.hpp @@ -0,0 +1,25 @@ +void testMulVec() +{ + using namespace mcl::bn; + const size_t n = 5; + G1 xVec[n]; + Fr yVec[n]; + G1 ok; + ok.clear(); + char c = 'a'; + for (size_t i = 0; i < n; i++) { + hashAndMapToG1(xVec[i], &c, 1); + yVec[i].setByCSPRNG(); + G1 t; + G1::mul(t, xVec[i], yVec[i]); + ok += t; + } + G1 z; + G1::mulVec(z, xVec, yVec, n); + CYBOZU_TEST_EQUAL(z, ok); +} + +void testCommon() +{ + testMulVec(); +}