a portable and fast pairing-based cryptography library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
mcl/include/mcl/window_method.hpp

156 lines
3.1 KiB

#pragma once
/**
@file
@brief window method
@author MITSUNARI Shigeo(@herumi)
*/
#include <vector>
#include <mcl/fp.hpp>
namespace mcl { namespace fp {
/*
get w-bit size from x[0, bitSize)
@param x [in] data
@param bitSize [in] data size
@param w [in] split size < UnitBitSize
*/
template<class T>
struct ArrayIterator {
static const size_t TbitSize = sizeof(T) * 8;
ArrayIterator(const T *x, size_t bitSize, size_t w)
: x(x)
, bitSize(bitSize)
, w(w)
, pos(0)
, mask((w == TbitSize ? 0 : (T(1) << w)) - 1)
{
assert(w <= TbitSize);
}
bool hasNext() const { return bitSize > 0; }
T getNext()
{
if (w == TbitSize) {
bitSize -= w;
return *x++;
}
if (pos + w < TbitSize) {
T v = (*x >> pos) & mask;
pos += w;
if (bitSize < w) {
bitSize = 0;
} else {
bitSize -= w;
}
return v;
}
if (pos + bitSize <= TbitSize) {
assert(bitSize <= w);
T v = *x >> pos;
assert((v >> bitSize) == 0);
bitSize = 0;
return v & mask;
}
assert(pos > 0);
T v = (x[0] >> pos) | (x[1] << (TbitSize - pos));
v &= mask;
pos = (pos + w) - TbitSize;
bitSize -= w;
x++;
return v;
}
const T *x;
size_t bitSize;
size_t w;
size_t pos;
T mask;
};
template<class Ec>
class WindowMethod {
public:
typedef std::vector<Ec> EcV;
size_t bitSize_;
size_t winSize_;
std::vector<EcV> tbl_;
WindowMethod(const Ec& x, size_t bitSize, size_t winSize)
{
init(x, bitSize, winSize);
}
WindowMethod()
: bitSize_(0)
, winSize_(0)
{
}
/*
@param x [in] base index
@param bitSize [in] exponent bit length
@param winSize [in] window size
*/
void init(const Ec& x, size_t bitSize, size_t winSize)
{
bitSize_ = bitSize;
winSize_ = winSize;
const size_t tblNum = (bitSize + winSize - 1) / winSize;
const size_t r = size_t(1) << winSize;
tbl_.resize(tblNum);
Ec t(x);
for (size_t i = 0; i < tblNum; i++) {
tbl_[i].resize(r);
EcV& w = tbl_[i];
for (size_t d = 1; d < r; d *= 2) {
for (size_t j = 0; j < d; j++) {
Ec::add(w[j + d], w[j], t);
}
Ec::dbl(t, t);
}
}
}
/*
@param z [out] x multiplied by y
@param y [in] exponent
*/
template<class tag2, size_t maxBitSize2>
void mul(Ec& z, const FpT<tag2, maxBitSize2>& y) const
{
fp::Block b;
y.getBlock(b);
powArray(z, b.p, b.n, false);
}
void mul(Ec& z, int y) const
{
Unit u = std::abs(y);
powArray(z, &u, 1, y < 0);
}
void mul(Ec& z, const mpz_class& y) const
{
powArray(z, gmp::getUnit(y), abs(y.get_mpz_t()->_mp_size), y < 0);
}
void powArray(Ec& z, const Unit* y, size_t n, bool isNegative) const
{
z.clear();
while (n > 0) {
if (y[n - 1]) break;
n--;
}
if (n == 0) return;
if (n > tbl_.size()) throw cybozu::Exception("mcl:WindowMethod:powArray:bad n") << n << tbl_.size();
assert(y[n - 1]);
const size_t bitSize = (n - 1) * UnitBitSize + cybozu::bsr<Unit>(y[n - 1]) + 1;
size_t i = 0;
ArrayIterator<Unit> ai(y, bitSize, winSize_);
do {
Unit v = ai.getNext();
if (v) {
Ec::add(z, z, tbl_[i][v]);
}
i++;
} while (ai.hasNext());
if (isNegative) {
Ec::neg(z, z);
}
}
};
} } // mcl::fp