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