github.com/platonnetwork/platon-go@v0.7.6/cases/tool/win/bls_win/include/mcl/window_method.hpp (about)

     1  #pragma once
     2  /**
     3  	@file
     4  	@brief window method
     5  	@author MITSUNARI Shigeo(@herumi)
     6  */
     7  #include <mcl/array.hpp>
     8  #include <mcl/fp.hpp>
     9  
    10  namespace mcl { namespace fp {
    11  
    12  /*
    13  	get w-bit size from x[0, bitSize)
    14  	@param x [in] data
    15  	@param bitSize [in] data size
    16  	@param w [in] split size < UnitBitSize
    17  */
    18  template<class T>
    19  struct ArrayIterator {
    20  	static const size_t TbitSize = sizeof(T) * 8;
    21  	ArrayIterator(const T *x, size_t bitSize, size_t w)
    22  		: x(x)
    23  		, bitSize(bitSize)
    24  		, w(w)
    25  		, pos(0)
    26  		, mask((w == TbitSize ? 0 : (T(1) << w)) - 1)
    27  	{
    28  		assert(w <= TbitSize);
    29  	}
    30  	bool hasNext() const { return bitSize > 0; }
    31  	T getNext()
    32  	{
    33  		if (w == TbitSize) {
    34  			bitSize -= w;
    35  			return *x++;
    36  		}
    37  		if (pos + w < TbitSize) {
    38  			T v = (*x >> pos) & mask;
    39  			pos += w;
    40  			if (bitSize < w) {
    41  				bitSize = 0;
    42  			} else {
    43  				bitSize -= w;
    44  			}
    45  			return v;
    46  		}
    47  		if (pos + bitSize <= TbitSize) {
    48  			assert(bitSize <= w);
    49  			T v = *x >> pos;
    50  			assert((v >> bitSize) == 0);
    51  			bitSize = 0;
    52  			return v & mask;
    53  		}
    54  		assert(pos > 0);
    55  		T v = (x[0] >> pos) | (x[1] << (TbitSize - pos));
    56  		v &= mask;
    57  		pos = (pos + w) - TbitSize;
    58  		bitSize -= w;
    59  		x++;
    60  		return v;
    61  	}
    62  	const T *x;
    63  	size_t bitSize;
    64  	size_t w;
    65  	size_t pos;
    66  	T mask;
    67  };
    68  
    69  template<class Ec>
    70  class WindowMethod {
    71  public:
    72  	size_t bitSize_;
    73  	size_t winSize_;
    74  	mcl::Array<Ec> tbl_;
    75  	WindowMethod(const Ec& x, size_t bitSize, size_t winSize)
    76  	{
    77  		init(x, bitSize, winSize);
    78  	}
    79  	WindowMethod()
    80  		: bitSize_(0)
    81  		, winSize_(0)
    82  	{
    83  	}
    84  	/*
    85  		@param x [in] base index
    86  		@param bitSize [in] exponent bit length
    87  		@param winSize [in] window size
    88  	*/
    89  	void init(bool *pb, const Ec& x, size_t bitSize, size_t winSize)
    90  	{
    91  		bitSize_ = bitSize;
    92  		winSize_ = winSize;
    93  		const size_t tblNum = (bitSize + winSize - 1) / winSize;
    94  		const size_t r = size_t(1) << winSize;
    95  		*pb = tbl_.resize(tblNum * r);
    96  		if (!*pb) return;
    97  		Ec t(x);
    98  		for (size_t i = 0; i < tblNum; i++) {
    99  			Ec* w = &tbl_[i * r];
   100  			w[0].clear();
   101  			for (size_t d = 1; d < r; d *= 2) {
   102  				for (size_t j = 0; j < d; j++) {
   103  					Ec::add(w[j + d], w[j], t);
   104  				}
   105  				Ec::dbl(t, t);
   106  			}
   107  			for (size_t j = 0; j < r; j++) {
   108  				w[j].normalize();
   109  			}
   110  		}
   111  	}
   112  #ifndef CYBOZU_DONT_USE_EXCEPTION
   113  	void init(const Ec& x, size_t bitSize, size_t winSize)
   114  	{
   115  		bool b;
   116  		init(&b, x, bitSize, winSize);
   117  		if (!b) throw cybozu::Exception("mcl:WindowMethod:init") << bitSize << winSize;
   118  	}
   119  #endif
   120  	/*
   121  		@param z [out] x multiplied by y
   122  		@param y [in] exponent
   123  	*/
   124  	template<class tag2, size_t maxBitSize2>
   125  	void mul(Ec& z, const FpT<tag2, maxBitSize2>& y) const
   126  	{
   127  		fp::Block b;
   128  		y.getBlock(b);
   129  		powArray(z, b.p, b.n, false);
   130  	}
   131  	void mul(Ec& z, int64_t y) const
   132  	{
   133  #if MCL_SIZEOF_UNIT == 8
   134  		Unit u = fp::abs_(y);
   135  		powArray(z, &u, 1, y < 0);
   136  #else
   137  		uint64_t ua = fp::abs_(y);
   138  		Unit u[2] = { uint32_t(ua), uint32_t(ua >> 32) };
   139  		size_t un = u[1] ? 2 : 1;
   140  		powArray(z, u, un, y < 0);
   141  #endif
   142  	}
   143  	void mul(Ec& z, const mpz_class& y) const
   144  	{
   145  		powArray(z, gmp::getUnit(y), gmp::getUnitSize(y), y < 0);
   146  	}
   147  	void powArray(Ec& z, const Unit* y, size_t n, bool isNegative) const
   148  	{
   149  		z.clear();
   150  		while (n > 0) {
   151  			if (y[n - 1]) break;
   152  			n--;
   153  		}
   154  		if (n == 0) return;
   155  		assert((n << winSize_) <= tbl_.size());
   156  		if ((n << winSize_) > tbl_.size()) return;
   157  		assert(y[n - 1]);
   158  		const size_t bitSize = (n - 1) * UnitBitSize + cybozu::bsr<Unit>(y[n - 1]) + 1;
   159  		size_t i = 0;
   160  		ArrayIterator<Unit> ai(y, bitSize, winSize_);
   161  		do {
   162  			Unit v = ai.getNext();
   163  			if (v) {
   164  				Ec::add(z, z, tbl_[(i << winSize_) + v]);
   165  			}
   166  			i++;
   167  		} while (ai.hasNext());
   168  		if (isNegative) {
   169  			Ec::neg(z, z);
   170  		}
   171  	}
   172  };
   173  
   174  } } // mcl::fp
   175