add precomupted miller loop

dev
MITSUNARI Shigeo 8 years ago
parent 6a931814dd
commit 9f93fe6900
  1. 92
      include/mcl/bn.hpp
  2. 24
      test/bn_test.cpp

@ -541,6 +541,13 @@ struct BNT {
addLineWithoutP(l, R, Q);
updateLine(l, P);
}
static void Fp6_cb_mul_G1_xy(Fp6& l, const G1& P)
{
assert(P.isNormalized());
Fp2::mulFp(l.c, l.c, P.x);
Fp2::mulFp(l.b, l.b, P.y);
}
static void convertFp6toFp12(Fp12& y, const Fp6& x)
{
y.clear();
@ -1001,21 +1008,22 @@ struct BNT {
#endif
exp_d1(y, y);
}
static void pairing(Fp12& f, const G2& Q, const G1& P)
static void millerLoop(Fp12& f, const G2& Q, const G1& P)
{
P.normalize();
Q.normalize();
Fp6 l;
G2 T = Q;
f = 1;
G2 negQ;
if (param.useNAF) {
G2::neg(negQ, Q);
}
Fp6 d;
dblLine(d, T, P);
Fp6 e;
assert(param.siTbl[1] == 1);
addLine(e, T, Q, P);
mul_024_024(f, d, e);
Fp6 l;
for (size_t i = 2; i < param.siTbl.size(); i++) {
dblLine(l, T, P);
Fp12::sqr(f, f);
@ -1042,8 +1050,86 @@ struct BNT {
Fp12 ft;
mul_024_024(ft, d, e);
f *= ft;
}
static void pairing(Fp12& f, const G2& Q, const G1& P)
{
millerLoop(f, Q, P);
finalExp(f, f);
}
static void precomputeG2(std::vector<Fp6>& Qcoeff, const G2& Q)
{
Qcoeff.clear();
Q.normalize();
G2 T = Q;
G2 negQ;
if (param.useNAF) {
G2::neg(negQ, Q);
}
Fp6 d;
dblLineWithoutP(d, T);
Qcoeff.push_back(d);
Fp6 e;
assert(param.siTbl[1] == 1);
addLineWithoutP(e, T, Q);
Qcoeff.push_back(e);
Fp6 l;
for (size_t i = 2; i < param.siTbl.size(); i++) {
dblLineWithoutP(l, T);
Qcoeff.push_back(l);
if (param.siTbl[i]) {
if (param.siTbl[i] > 0) {
addLineWithoutP(l, T, Q);
} else {
addLineWithoutP(l, T, negQ);
}
Qcoeff.push_back(l);
}
}
G2 Q1, Q2;
FrobeniusOnTwist(Q1, Q);
FrobeniusOnTwist(Q2, Q1);
G2::neg(Q2, Q2);
if (param.z < 0) {
G2::neg(T, T);
}
addLineWithoutP(d, T, Q1);
Qcoeff.push_back(d);
addLineWithoutP(e, T, Q2);
Qcoeff.push_back(e);
}
static void precomputedMillerLoop(Fp12& f, const std::vector<Fp6>& Qcoeff, const G1& P)
{
P.normalize();
size_t idx = 0;
Fp6 d = Qcoeff[idx++];
Fp6_cb_mul_G1_xy(d, P);
Fp6 e = Qcoeff[idx++];
Fp6_cb_mul_G1_xy(e, P);
mul_024_024(f, d, e);
Fp6 l;
for (size_t i = 2; i < param.siTbl.size(); i++) {
l = Qcoeff[idx++];
Fp6_cb_mul_G1_xy(l, P);
Fp12::sqr(f, f);
mul_024(f, f, l);
if (param.siTbl[i]) {
l = Qcoeff[idx++];
Fp6_cb_mul_G1_xy(l, P);
mul_024(f, f, l);
}
}
if (param.z < 0) {
Fp6::neg(f.b, f.b);
}
d = Qcoeff[idx++];
Fp6_cb_mul_G1_xy(d, P);
e = Qcoeff[idx++];
Fp6_cb_mul_G1_xy(e, P);
Fp12 ft;
mul_024_024(ft, d, e);
f *= ft;
}
};
template<class Fp>

@ -161,7 +161,18 @@ void testCompress()
CYBOZU_TEST_EQUAL(b, c);
}
void test(const TestSet& ts)
void testPrecomputed(const G2& Q, const G1& P)
{
Fp12 e1, e2;
BN::pairing(e1, Q, P);
std::vector<Fp6> Qcoeff;
BN::precomputeG2(Qcoeff, Q);
BN::precomputedMillerLoop(e2, Qcoeff, P);
BN::finalExp(e2, e2);
CYBOZU_TEST_EQUAL(e1, e2);
}
void testPairing(const TestSet& ts)
{
G1 P(ts.g1.a, ts.g1.b);
G2 Q(Fp2(ts.g2.aa, ts.g2.ab), Fp2(ts.g2.ba, ts.g2.bb));
@ -171,16 +182,8 @@ void test(const TestSet& ts)
{
std::stringstream ss(ts.e);
ss >> e2;
// mpz_class x = BN::param.z;
// x = 2 * x * (6 * x * x + 3 * x + 1);
// Fp12::pow(e1, e1, x);
}
CYBOZU_TEST_EQUAL(e1, e2);
/*
ate-pairing on Haswell
miller loop : 700Kclk
final exp : 460Kclk
*/
#if 0
for (int i = 0; i < 1000; i++) BN::pairing(e1, Q, P);
// CYBOZU_BENCH_C("pairing", 1000, BN::pairing, e1, Q, P); // 2.4Mclk
@ -209,6 +212,7 @@ void test(const TestSet& ts)
CYBOZU_BENCH("pairing", BN::pairing, e1, Q, P); // 2.4Mclk
CYBOZU_BENCH("finalExp", BN::finalExp, e1, e1); // 1.3Mclk
#endif
testPrecomputed(Q, P);
}
CYBOZU_TEST_AUTO(naive)
@ -222,7 +226,7 @@ CYBOZU_TEST_AUTO(naive)
testMapToG2();
testCyclotomic();
testCompress();
test(ts);
testPairing(ts);
//break;
}
int count = (int)clk.getCount();

Loading…
Cancel
Save