add affine test

update-fork
MITSUNARI Shigeo 5 years ago
parent 8234909744
commit 14f9e64a54
  1. 125
      include/mcl/ec.hpp
  2. 28
      test/ec_test.cpp

@ -10,8 +10,6 @@
#include <mcl/fp.hpp>
#include <mcl/ecparam.hpp>
//#define MCL_EC_USE_AFFINE
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4458)
@ -41,7 +39,8 @@ namespace ec {
enum Mode {
Jacobi = 0,
Proj = 1
Proj = 1,
Affine
};
namespace local {
@ -151,13 +150,8 @@ class EcT : public fp::Serializable<EcT<_Fp> > {
public:
typedef _Fp Fp;
typedef _Fp BaseFp;
#ifdef MCL_EC_USE_AFFINE
Fp x, y;
bool inf_;
#else
Fp x, y, z;
static int mode_;
#endif
static Fp a_;
static Fp b_;
static int specialA_;
@ -178,13 +172,8 @@ public:
}
bool isNormalized() const
{
#ifdef MCL_EC_USE_AFFINE
return true;
#else
return isZero() || z.isOne();
#endif
}
#ifndef MCL_EC_USE_AFFINE
private:
void normalizeJacobi()
{
@ -202,7 +191,6 @@ private:
{
return ec::isValidProj(a_, b_, x, y, z);
}
#endif
bool isValidAffine() const
{
return ec::isValidAffine(a_, b_, x, y);
@ -210,7 +198,6 @@ private:
public:
void normalize()
{
#ifndef MCL_EC_USE_AFFINE
if (isNormalized()) return;
switch (mode_) {
case ec::Jacobi:
@ -220,7 +207,6 @@ public:
normalizeProj();
break;
}
#endif
}
static void normalize(EcT& y, const EcT& x)
{
@ -243,13 +229,9 @@ public:
order_ = 0;
mulArrayGLV = 0;
mulVecNGLV = 0;
#ifdef MCL_EC_USE_AFFINE
cybozu::disable_warning_unused_variable(mode);
#else
assert(mode == ec::Jacobi || mode == ec::Proj);
mode_ = mode;
#endif
}
static inline int getMode() { return mode_; }
/*
verify the order of *this is equal to order if order != 0
in constructor, set, setStr, operator<<().
@ -288,34 +270,25 @@ public:
bool isValid() const
{
if (isZero()) return true;
bool isOK = false;
#ifndef MCL_EC_USE_AFFINE
if (!z.isOne()) {
switch (mode_) {
case ec::Jacobi:
isOK = isValidJacobi();
if (!isValidJacobi()) return false;
break;
case ec::Proj:
isOK = isValidProj();
if (!isValidProj()) return false;
break;
case ec::Affine:
if (!isValidAffine()) return false;
break;
}
} else
#endif
{
isOK = isValidAffine();
}
if (!isOK) return false;
if (verifyOrder_) return isValidOrder();
return true;
}
void set(bool *pb, const Fp& x, const Fp& y, bool verify = true)
{
this->x = x; this->y = y;
#ifdef MCL_EC_USE_AFFINE
inf_ = false;
#else
this->x = x;
this->y = y;
z = 1;
#endif
if (!verify || (isValidAffine() && (!verifyOrder_ || isValidOrder()))) {
*pb = true;
return;
@ -325,15 +298,10 @@ public:
}
void clear()
{
#ifdef MCL_EC_USE_AFFINE
inf_ = true;
#else
z.clear();
#endif
x.clear();
y.clear();
z.clear();
}
#ifndef MCL_EC_USE_AFFINE
static inline void dblNoVerifyInfJacobi(EcT& R, const EcT& P)
{
Fp S, M, t, y2;
@ -449,10 +417,8 @@ public:
Fp::sub(R.y, t, w);
R.y -= w;
}
#endif
static inline void dblNoVerifyInf(EcT& R, const EcT& P)
static inline void dblNoVerifyInfAffine(EcT& R, const EcT& P)
{
#ifdef MCL_EC_USE_AFFINE
Fp t, s;
Fp::sqr(t, P.x);
Fp::add(s, t, t);
@ -468,8 +434,10 @@ public:
s *= t;
Fp::sub(R.y, s, P.y);
R.x = x3;
R.inf_ = false;
#else
R.z = 1;
}
static inline void dblNoVerifyInf(EcT& R, const EcT& P)
{
switch (mode_) {
case ec::Jacobi:
dblNoVerifyInfJacobi(R, P);
@ -477,8 +445,10 @@ public:
case ec::Proj:
dblNoVerifyInfProj(R, P);
break;
case ec::Affine:
dblNoVerifyInfAffine(R, P);
break;
}
#endif
}
static inline void dbl(EcT& R, const EcT& P)
{
@ -488,7 +458,6 @@ public:
}
dblNoVerifyInf(R, P);
}
#ifndef MCL_EC_USE_AFFINE
static inline void addJacobi(EcT& R, const EcT& P, const EcT& Q, bool isPzOne, bool isQzOne)
{
Fp r, U1, S1, H, H3;
@ -615,27 +584,22 @@ public:
R.y *= r;
R.y -= vv;
}
#endif
static inline void add(EcT& R, const EcT& P, const EcT& Q) {
if (P.isZero()) { R = Q; return; }
if (Q.isZero()) { R = P; return; }
if (&P == &Q) {
dblNoVerifyInf(R, P);
return;
}
#ifdef MCL_EC_USE_AFFINE
static inline void addAffine(EcT& R, const EcT& P, const EcT& Q)
{
Fp t;
Fp::neg(t, Q.y);
if (P.y == t) { R.clear(); return; }
Fp::sub(t, Q.x, P.x);
if (t.isZero()) {
if (P.y == Q.y) {
dblNoVerifyInf(R, P);
} else {
R.clear();
}
return;
}
Fp s;
Fp::sub(s, Q.y, P.y);
Fp::div(t, s, t);
R.inf_ = false;
R.z = 1;
Fp x3;
Fp::sqr(x3, t);
x3 -= P.x;
@ -644,7 +608,14 @@ public:
s *= t;
Fp::sub(R.y, s, P.y);
R.x = x3;
#else
}
static inline void add(EcT& R, const EcT& P, const EcT& Q) {
if (P.isZero()) { R = Q; return; }
if (Q.isZero()) { R = P; return; }
if (&P == &Q) {
dblNoVerifyInf(R, P);
return;
}
bool isPzOne = P.z.isOne();
bool isQzOne = Q.z.isOne();
switch (mode_) {
@ -654,8 +625,10 @@ public:
case ec::Proj:
addProj(R, P, Q, isPzOne, isQzOne);
break;
case ec::Affine:
addAffine(R, P, Q);
break;
}
#endif
}
static inline void sub(EcT& R, const EcT& P, const EcT& Q)
{
@ -671,11 +644,7 @@ public:
}
R.x = P.x;
Fp::neg(R.y, P.y);
#ifdef MCL_EC_USE_AFFINE
R.inf_ = false;
#else
R.z = P.z;
#endif
}
template<class tag, size_t maxBitSize, template<class _tag, size_t _maxBitSize>class FpT>
static inline void mul(EcT& z, const EcT& x, const FpT<tag, maxBitSize>& y)
@ -742,11 +711,7 @@ public:
}
bool isZero() const
{
#ifdef MCL_EC_USE_AFFINE
return inf_;
#else
return z.isZero();
#endif
}
static inline bool isMSBserialize()
{
@ -772,9 +737,7 @@ public:
cybozu::writeChar(pb, os, sep);
if (!*pb) return;
}
#ifndef MCL_EC_USE_AFFINE
z.save(pb, os, ioMode);
#endif
return;
}
EcT P(*this);
@ -874,11 +837,7 @@ public:
template<class InputStream>
void load(bool *pb, InputStream& is, int ioMode)
{
#ifdef MCL_EC_USE_AFFINE
inf_ = false;
#else
z = 1;
#endif
if (ioMode & IoEcAffineSerialize) {
if (b_ == 0) { // assume Zero if x = y = 0
*pb = false;
@ -983,9 +942,13 @@ public:
if (!*pb) return;
} else if (c == '4') {
y.load(pb, is, ioMode); if (!*pb) return;
#ifndef MCL_EC_USE_AFFINE
z.load(pb, is, ioMode); if (!*pb) return;
#endif
if (mode_ == ec::Affine) {
if (!z.isZero() && !z.isOne()) {
*pb = false;
return;
}
}
} else {
*pb = false;
return;
@ -1369,9 +1332,7 @@ template<class Fp> bool EcT<Fp>::verifyOrder_;
template<class Fp> mpz_class EcT<Fp>::order_;
template<class Fp> void (*EcT<Fp>::mulArrayGLV)(EcT& z, const EcT& x, const fp::Unit *y, size_t yn, bool isNegative, bool constTime);
template<class Fp> size_t (*EcT<Fp>::mulVecNGLV)(EcT& z, const EcT *xVec, const mpz_class *yVec, size_t yn);
#ifndef MCL_EC_USE_AFFINE
template<class Fp> int EcT<Fp>::mode_;
#endif
// r = the order of Ec
template<class Ec, class _Fr>

@ -1,8 +1,8 @@
//#define MCL_EC_USE_AFFINE
#define PUT(x) std::cout << #x "=" << (x) << std::endl
#define CYBOZU_TEST_DISABLE_AUTO_RUN
#include <cybozu/test.hpp>
#include <cybozu/benchmark.hpp>
#include <cybozu/xorshift.hpp>
#include <mcl/gmp_util.hpp>
#include <mcl/fp.hpp>
@ -19,11 +19,7 @@ typedef mcl::EcT<Fp> Ec;
CYBOZU_TEST_AUTO(sizeof)
{
CYBOZU_TEST_EQUAL(sizeof(Fp), sizeof(mcl::fp::Unit) * Fp::maxSize);
#ifdef MCL_EC_USE_AFFINE
CYBOZU_TEST_EQUAL(sizeof(Ec), sizeof(Fp) * 2 + sizeof(mcl::fp::Unit));
#else
CYBOZU_TEST_EQUAL(sizeof(Ec), sizeof(Fp) * 3);
#endif
}
struct Test {
@ -96,9 +92,9 @@ struct Test {
{
Ec::dbl(R, P);
#ifndef MCL_EC_USE_AFFINE
if (Ec::getMode() != mcl::ec::Affine) {
CYBOZU_TEST_ASSERT(!R.isNormalized());
#endif
}
CYBOZU_TEST_ASSERT(R.isValid());
Ec R2 = P + P;
CYBOZU_TEST_EQUAL(R, R2);
@ -162,13 +158,17 @@ struct Test {
Ec R2;
P += P;
Q += P;
if (Ec::getMode() == mcl::ec::Affine) {
CYBOZU_TEST_ASSERT(P.z.isOne());
CYBOZU_TEST_ASSERT(Q.z.isOne());
} else {
CYBOZU_TEST_ASSERT(!P.z.isOne());
CYBOZU_TEST_ASSERT(!Q.z.isOne());
}
Ec::add(R2, P, Q);
P.normalize();
CYBOZU_TEST_ASSERT(P.z.isOne());
CYBOZU_TEST_ASSERT(!Q.z.isOne());
// affine + generic
Ec::add(R, P, Q);
CYBOZU_TEST_EQUAL(R, R2);
@ -177,14 +177,17 @@ struct Test {
CYBOZU_TEST_EQUAL(R, R2);
Q.normalize();
CYBOZU_TEST_ASSERT(P.z.isOne());
CYBOZU_TEST_ASSERT(Q.z.isOne());
// affine + affine
Ec::add(R, P, Q);
CYBOZU_TEST_EQUAL(R, R2);
P += P;
if (Ec::getMode() == mcl::ec::Affine) {
CYBOZU_TEST_ASSERT(P.z.isOne());
} else {
CYBOZU_TEST_ASSERT(!P.z.isOne());
}
// generic
Ec::dbl(R2, P);
@ -546,6 +549,7 @@ void naiveMulVec(Ec& out, const Ec *xVec, const Zn *yVec, size_t n)
void mulVec(const mcl::EcParam& para)
{
if (para.bitSize > 384) return;
cybozu::XorShift rg;
const Fp x(para.gx);
const Fp y(para.gy);
Ec P(x, y);
@ -558,7 +562,7 @@ void mulVec(const mcl::EcParam& para)
Ec::dbl(P, P);
for (size_t i = 0; i < N; i++) {
Ec::mul(xVec[i], P, i + 3);
yVec[i].setByCSPRNG();
yVec[i].setByCSPRNG(rg);
}
const size_t nTbl[] = { 1, 2, 3, 5, 30, 31, 32, 33 };
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(nTbl); i++) {
@ -582,6 +586,8 @@ void test_sub_sub(const mcl::EcParam& para, mcl::fp::Mode fpMode)
Test(para, fpMode, mcl::ec::Proj).run();
puts("Jacobi");
Test(para, fpMode, mcl::ec::Jacobi).run();
puts("Affine");
Test(para, fpMode, mcl::ec::Affine).run();
}
void test_sub(const mcl::EcParam *para, size_t paraNum)
@ -595,8 +601,8 @@ void test_sub(const mcl::EcParam *para, size_t paraNum)
#endif
#ifdef MCL_USE_XBYAK
test_sub_sub(para[i], mcl::fp::FP_XBYAK);
mulVec(para[i]);
#endif
mulVec(para[i]);
}
}

Loading…
Cancel
Save