github.com/platonnetwork/platon-go@v0.7.6/cases/tool/win/bls_win/include/mcl/fp.hpp (about) 1 #pragma once 2 /** 3 @file 4 @brief finite field class 5 @author MITSUNARI Shigeo(@herumi) 6 @license modified new BSD license 7 http://opensource.org/licenses/BSD-3-Clause 8 */ 9 #ifndef CYBOZU_DONT_USE_STRING 10 #include <iosfwd> 11 #endif 12 #ifdef _MSC_VER 13 #pragma warning(push) 14 #pragma warning(disable : 4127) 15 #pragma warning(disable : 4458) 16 #ifndef NOMINMAX 17 #define NOMINMAX 18 #endif 19 #ifndef MCL_NO_AUTOLINK 20 #ifdef NDEBUG 21 #pragma comment(lib, "mcl.lib") 22 #else 23 #pragma comment(lib, "mcl.lib") 24 #endif 25 #endif 26 #endif 27 #include <cybozu/hash.hpp> 28 #include <cybozu/stream.hpp> 29 #include <mcl/op.hpp> 30 #include <mcl/util.hpp> 31 #include <mcl/operator.hpp> 32 #include <mcl/conversion.hpp> 33 34 namespace mcl { 35 36 struct FpTag; 37 struct ZnTag; 38 39 namespace fp { 40 41 // copy src to dst as little endian 42 void copyUnitToByteAsLE(uint8_t *dst, const Unit *src, size_t byteSize); 43 // copy src to dst as little endian 44 void copyByteToUnitAsLE(Unit *dst, const uint8_t *src, size_t byteSize); 45 46 bool copyAndMask(Unit *y, const void *x, size_t xByteSize, const Op& op, MaskMode maskMode); 47 48 uint64_t getUint64(bool *pb, const fp::Block& b); 49 int64_t getInt64(bool *pb, fp::Block& b, const fp::Op& op); 50 51 const char *ModeToStr(Mode mode); 52 53 Mode StrToMode(const char *s); 54 55 #ifndef CYBOZU_DONT_USE_STRING 56 inline Mode StrToMode(const std::string& s) 57 { 58 return StrToMode(s.c_str()); 59 } 60 #endif 61 62 inline void dumpUnit(Unit x) 63 { 64 #if MCL_SIZEOF_UNIT == 4 65 printf("%08x", (uint32_t)x); 66 #else 67 printf("%016llx", (unsigned long long)x); 68 #endif 69 } 70 71 bool isEnableJIT(); // 1st call is not threadsafe 72 73 uint32_t sha256(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize); 74 uint32_t sha512(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize); 75 76 namespace local { 77 78 inline void byteSwap(void *x, size_t n) 79 { 80 char *p = (char *)x; 81 for (size_t i = 0; i < n / 2; i++) { 82 fp::swap_(p[i], p[n - 1 - i]); 83 } 84 } 85 86 } // mcl::fp::local 87 88 } // mcl::fp 89 90 template<class tag = FpTag, size_t maxBitSize = MCL_MAX_BIT_SIZE> 91 class FpT : public fp::Serializable<FpT<tag, maxBitSize>, 92 fp::Operator<FpT<tag, maxBitSize> > > { 93 typedef fp::Unit Unit; 94 typedef fp::Operator<FpT<tag, maxBitSize> > Operator; 95 typedef fp::Serializable<FpT<tag, maxBitSize>, Operator> Serializer; 96 public: 97 static const size_t maxSize = (maxBitSize + fp::UnitBitSize - 1) / fp::UnitBitSize; 98 private: 99 template<class tag2, size_t maxBitSize2> friend class FpT; 100 Unit v_[maxSize]; 101 static fp::Op op_; 102 static FpT<tag, maxBitSize> inv2_; 103 static int ioMode_; 104 static bool isETHserialization_; 105 template<class Fp> friend class FpDblT; 106 template<class Fp> friend class Fp2T; 107 template<class Fp> friend struct Fp6T; 108 public: 109 typedef FpT<tag, maxBitSize> BaseFp; 110 // return pointer to array v_[] 111 const Unit *getUnit() const { return v_; } 112 FpT* getFp0() { return this; } 113 const FpT* getFp0() const { return this; } 114 static inline size_t getUnitSize() { return op_.N; } 115 static inline size_t getBitSize() { return op_.bitSize; } 116 static inline size_t getByteSize() { return (op_.bitSize + 7) / 8; } 117 static inline const fp::Op& getOp() { return op_; } 118 void dump() const 119 { 120 const size_t N = op_.N; 121 for (size_t i = 0; i < N; i++) { 122 fp::dumpUnit(v_[N - 1 - i]); 123 } 124 printf("\n"); 125 } 126 /* 127 xi_a is used for Fp2::mul_xi(), where xi = xi_a + i and i^2 = -1 128 if xi_a = 0 then asm functions for Fp2 are not generated. 129 */ 130 static inline void init(bool *pb, int xi_a, const mpz_class& p, fp::Mode mode = fp::FP_AUTO) 131 { 132 assert(maxBitSize <= MCL_MAX_BIT_SIZE); 133 *pb = op_.init(p, maxBitSize, xi_a, mode); 134 if (!*pb) return; 135 { // set oneRep 136 FpT& one = *reinterpret_cast<FpT*>(op_.oneRep); 137 one.clear(); 138 one.v_[0] = 1; 139 one.toMont(); 140 } 141 { // set half 142 mpz_class half = (op_.mp + 1) / 2; 143 gmp::getArray(pb, op_.half, op_.N, half); 144 if (!*pb) return; 145 } 146 inv(inv2_, 2); 147 ioMode_ = 0; 148 isETHserialization_ = false; 149 #ifdef MCL_XBYAK_DIRECT_CALL 150 add = fp::func_ptr_cast<void (*)(FpT& z, const FpT& x, const FpT& y)>(op_.fp_addA_); 151 if (add == 0) add = addC; 152 sub = fp::func_ptr_cast<void (*)(FpT& z, const FpT& x, const FpT& y)>(op_.fp_subA_); 153 if (sub == 0) sub = subC; 154 neg = fp::func_ptr_cast<void (*)(FpT& y, const FpT& x)>(op_.fp_negA_); 155 if (neg == 0) neg = negC; 156 mul = fp::func_ptr_cast<void (*)(FpT& z, const FpT& x, const FpT& y)>(op_.fp_mulA_); 157 if (mul == 0) mul = mulC; 158 sqr = fp::func_ptr_cast<void (*)(FpT& y, const FpT& x)>(op_.fp_sqrA_); 159 if (sqr == 0) sqr = sqrC; 160 #endif 161 *pb = true; 162 } 163 static inline void init(bool *pb, const mpz_class& p, fp::Mode mode = fp::FP_AUTO) 164 { 165 init(pb, 0, p, mode); 166 } 167 static inline void init(bool *pb, const char *mstr, fp::Mode mode = fp::FP_AUTO) 168 { 169 mpz_class p; 170 gmp::setStr(pb, p, mstr); 171 if (!*pb) return; 172 init(pb, p, mode); 173 } 174 static inline size_t getModulo(char *buf, size_t bufSize) 175 { 176 return gmp::getStr(buf, bufSize, op_.mp); 177 } 178 static inline bool isFullBit() { return op_.isFullBit; } 179 /* 180 binary patter of p 181 @note the value of p is zero 182 */ 183 static inline const FpT& getP() 184 { 185 return *reinterpret_cast<const FpT*>(op_.p); 186 } 187 bool isOdd() const 188 { 189 fp::Block b; 190 getBlock(b); 191 return (b.p[0] & 1) == 1; 192 } 193 static inline bool squareRoot(FpT& y, const FpT& x) 194 { 195 if (isMont()) return op_.sq.get(y, x); 196 mpz_class mx, my; 197 bool b = false; 198 x.getMpz(&b, mx); 199 if (!b) return false; 200 b = op_.sq.get(my, mx); 201 if (!b) return false; 202 y.setMpz(&b, my); 203 return b; 204 } 205 FpT() {} 206 FpT(const FpT& x) 207 { 208 op_.fp_copy(v_, x.v_); 209 } 210 FpT& operator=(const FpT& x) 211 { 212 op_.fp_copy(v_, x.v_); 213 return *this; 214 } 215 void clear() 216 { 217 op_.fp_clear(v_); 218 } 219 FpT(int64_t x) { operator=(x); } 220 FpT& operator=(int64_t x) 221 { 222 if (x == 1) { 223 op_.fp_copy(v_, op_.oneRep); 224 } else { 225 clear(); 226 if (x) { 227 int64_t y = x < 0 ? -x : x; 228 if (sizeof(Unit) == 8) { 229 v_[0] = y; 230 } else { 231 v_[0] = (uint32_t)y; 232 v_[1] = (uint32_t)(y >> 32); 233 } 234 if (x < 0) neg(*this, *this); 235 toMont(); 236 } 237 } 238 return *this; 239 } 240 static inline bool isMont() { return op_.isMont; } 241 /* 242 convert normal value to Montgomery value 243 do nothing is !isMont() 244 */ 245 void toMont() 246 { 247 if (isMont()) op_.toMont(v_, v_); 248 } 249 /* 250 convert Montgomery value to normal value 251 do nothing is !isMont() 252 */ 253 void fromMont() 254 { 255 if (isMont()) op_.fromMont(v_, v_); 256 } 257 template<class InputStream> 258 void load(bool *pb, InputStream& is, int ioMode) 259 { 260 bool isMinus = false; 261 *pb = false; 262 if (ioMode & (IoArray | IoArrayRaw | IoSerialize | IoSerializeHexStr)) { 263 const size_t n = getByteSize(); 264 v_[op_.N - 1] = 0; 265 size_t readSize; 266 if (ioMode & IoSerializeHexStr) { 267 readSize = mcl::fp::readHexStr(v_, n, is); 268 } else { 269 readSize = cybozu::readSome(v_, n, is); 270 } 271 if (isETHserialization_ && ioMode & (IoSerialize | IoSerializeHexStr)) { 272 fp::local::byteSwap(v_, n); 273 } 274 if (readSize != n) return; 275 } else { 276 char buf[1024]; 277 size_t n = fp::local::loadWord(buf, sizeof(buf), is); 278 if (n == 0) return; 279 n = fp::strToArray(&isMinus, v_, op_.N, buf, n, ioMode); 280 if (n == 0) return; 281 for (size_t i = n; i < op_.N; i++) v_[i] = 0; 282 } 283 if (fp::isGreaterOrEqualArray(v_, op_.p, op_.N)) { 284 return; 285 } 286 if (isMinus) { 287 neg(*this, *this); 288 } 289 if (!(ioMode & IoArrayRaw)) { 290 toMont(); 291 } 292 *pb = true; 293 } 294 template<class OutputStream> 295 void save(bool *pb, OutputStream& os, int ioMode) const 296 { 297 const size_t n = getByteSize(); 298 if (ioMode & (IoArray | IoArrayRaw | IoSerialize | IoSerializeHexStr)) { 299 if (ioMode & IoArrayRaw) { 300 cybozu::write(pb, os, v_, n); 301 } else { 302 fp::Block b; 303 getBlock(b); 304 const char *src = (const char *)b.p; 305 char rev[fp::maxUnitSize * sizeof(fp::Unit)]; 306 if (isETHserialization_ && ioMode & (IoSerialize | IoSerializeHexStr)) { 307 for (size_t i = 0; i < n; i++) { 308 rev[i] = src[n - 1 - i]; 309 } 310 src = rev; 311 } 312 if (ioMode & IoSerializeHexStr) { 313 mcl::fp::writeHexStr(pb, os, src, n); 314 } else { 315 cybozu::write(pb, os, src, n); 316 } 317 } 318 return; 319 } 320 fp::Block b; 321 getBlock(b); 322 // use low 8-bit ioMode for (base, withPrefix) 323 char buf[2048]; 324 size_t len = mcl::fp::arrayToStr(buf, sizeof(buf), b.p, b.n, ioMode & 31, (ioMode & IoPrefix) != 0); 325 if (len == 0) { 326 *pb = false; 327 return; 328 } 329 cybozu::write(pb, os, buf + sizeof(buf) - len, len); 330 } 331 /* 332 mode = Mod : set x mod p if sizeof(S) * n <= 64 else error 333 */ 334 template<class S> 335 void setArray(bool *pb, const S *x, size_t n, mcl::fp::MaskMode mode = fp::NoMask) 336 { 337 *pb = fp::copyAndMask(v_, x, sizeof(S) * n, op_, mode); 338 toMont(); 339 } 340 /* 341 mask x with (1 << bitLen) and subtract p if x >= p 342 */ 343 template<class S> 344 void setArrayMaskMod(const S *x, size_t n) 345 { 346 fp::copyAndMask(v_, x, sizeof(S) * n, op_, fp::MaskAndMod); 347 toMont(); 348 } 349 350 /* 351 mask x with (1 << (bitLen - 1)) - 1 if x >= p 352 */ 353 template<class S> 354 void setArrayMask(const S *x, size_t n) 355 { 356 fp::copyAndMask(v_, x, sizeof(S) * n, op_, fp::SmallMask); 357 toMont(); 358 } 359 void getBlock(fp::Block& b) const 360 { 361 b.n = op_.N; 362 if (isMont()) { 363 op_.fromMont(b.v_, v_); 364 b.p = &b.v_[0]; 365 } else { 366 b.p = &v_[0]; 367 } 368 } 369 void setByCSPRNG(bool *pb, fp::RandGen rg = fp::RandGen()) 370 { 371 if (rg.isZero()) rg = fp::RandGen::get(); 372 rg.read(pb, v_, op_.N * sizeof(Unit)); // byte size 373 if (!pb) return; 374 setArrayMask(v_, op_.N); 375 } 376 #ifndef CYBOZU_DONT_USE_EXCEPTION 377 void setByCSPRNG(fp::RandGen rg = fp::RandGen()) 378 { 379 bool b; 380 setByCSPRNG(&b, rg); 381 if (!b) throw cybozu::Exception("setByCSPRNG"); 382 } 383 #endif 384 void setRand(fp::RandGen rg = fp::RandGen()) // old api 385 { 386 setByCSPRNG(rg); 387 } 388 /* 389 hash msg and mask with (1 << (bitLen - 1)) - 1 390 */ 391 void setHashOf(const void *msg, size_t msgSize) 392 { 393 char buf[MCL_MAX_HASH_BIT_SIZE / 8]; 394 uint32_t size = op_.hash(buf, static_cast<uint32_t>(sizeof(buf)), msg, static_cast<uint32_t>(msgSize)); 395 setArrayMask(buf, size); 396 } 397 void getMpz(bool *pb, mpz_class& x) const 398 { 399 fp::Block b; 400 getBlock(b); 401 gmp::setArray(pb, x, b.p, b.n); 402 } 403 void setMpz(bool *pb, const mpz_class& x) 404 { 405 if (x < 0) { 406 *pb = false; 407 return; 408 } 409 setArray(pb, gmp::getUnit(x), gmp::getUnitSize(x)); 410 } 411 #ifdef MCL_XBYAK_DIRECT_CALL 412 static void (*add)(FpT& z, const FpT& x, const FpT& y); 413 static inline void addC(FpT& z, const FpT& x, const FpT& y) { op_.fp_add(z.v_, x.v_, y.v_, op_.p); } 414 static void (*sub)(FpT& z, const FpT& x, const FpT& y); 415 static inline void subC(FpT& z, const FpT& x, const FpT& y) { op_.fp_sub(z.v_, x.v_, y.v_, op_.p); } 416 static void (*neg)(FpT& y, const FpT& x); 417 static inline void negC(FpT& y, const FpT& x) { op_.fp_neg(y.v_, x.v_, op_.p); } 418 static void (*mul)(FpT& z, const FpT& x, const FpT& y); 419 static inline void mulC(FpT& z, const FpT& x, const FpT& y) { op_.fp_mul(z.v_, x.v_, y.v_, op_.p); } 420 static void (*sqr)(FpT& y, const FpT& x); 421 static inline void sqrC(FpT& y, const FpT& x) { op_.fp_sqr(y.v_, x.v_, op_.p); } 422 #else 423 static inline void add(FpT& z, const FpT& x, const FpT& y) { op_.fp_add(z.v_, x.v_, y.v_, op_.p); } 424 static inline void sub(FpT& z, const FpT& x, const FpT& y) { op_.fp_sub(z.v_, x.v_, y.v_, op_.p); } 425 static inline void neg(FpT& y, const FpT& x) { op_.fp_neg(y.v_, x.v_, op_.p); } 426 static inline void mul(FpT& z, const FpT& x, const FpT& y) { op_.fp_mul(z.v_, x.v_, y.v_, op_.p); } 427 static inline void sqr(FpT& y, const FpT& x) { op_.fp_sqr(y.v_, x.v_, op_.p); } 428 #endif 429 static inline void addPre(FpT& z, const FpT& x, const FpT& y) { op_.fp_addPre(z.v_, x.v_, y.v_); } 430 static inline void subPre(FpT& z, const FpT& x, const FpT& y) { op_.fp_subPre(z.v_, x.v_, y.v_); } 431 static inline void mulUnit(FpT& z, const FpT& x, const Unit y) 432 { 433 if (mulSmallUnit(z, x, y)) return; 434 op_.fp_mulUnit(z.v_, x.v_, y, op_.p); 435 } 436 static inline void inv(FpT& y, const FpT& x) { op_.fp_invOp(y.v_, x.v_, op_); } 437 static inline void divBy2(FpT& y, const FpT& x) 438 { 439 #if 0 440 mul(y, x, inv2_); 441 #else 442 bool odd = (x.v_[0] & 1) != 0; 443 op_.fp_shr1(y.v_, x.v_); 444 if (odd) { 445 op_.fp_addPre(y.v_, y.v_, op_.half); 446 } 447 #endif 448 } 449 static inline void divBy4(FpT& y, const FpT& x) 450 { 451 divBy2(y, x); // QQQ : optimize later 452 divBy2(y, y); 453 } 454 bool isZero() const { return op_.fp_isZero(v_); } 455 bool isOne() const { return fp::isEqualArray(v_, op_.oneRep, op_.N); } 456 static const inline FpT& one() { return *reinterpret_cast<const FpT*>(op_.oneRep); } 457 /* 458 half = (p + 1) / 2 459 return true if half <= x < p 460 return false if 0 <= x < half 461 */ 462 bool isNegative() const 463 { 464 fp::Block b; 465 getBlock(b); 466 return fp::isGreaterOrEqualArray(b.p, op_.half, op_.N); 467 } 468 bool isValid() const 469 { 470 return fp::isLessArray(v_, op_.p, op_.N); 471 } 472 uint64_t getUint64(bool *pb) const 473 { 474 fp::Block b; 475 getBlock(b); 476 return fp::getUint64(pb, b); 477 } 478 int64_t getInt64(bool *pb) const 479 { 480 fp::Block b; 481 getBlock(b); 482 return fp::getInt64(pb, b, op_); 483 } 484 bool operator==(const FpT& rhs) const { return fp::isEqualArray(v_, rhs.v_, op_.N); } 485 bool operator!=(const FpT& rhs) const { return !operator==(rhs); } 486 /* 487 @note 488 this compare functions is slow because of calling mul if isMont is true. 489 */ 490 static inline int compare(const FpT& x, const FpT& y) 491 { 492 fp::Block xb, yb; 493 x.getBlock(xb); 494 y.getBlock(yb); 495 return fp::compareArray(xb.p, yb.p, op_.N); 496 } 497 bool isLess(const FpT& rhs) const 498 { 499 fp::Block xb, yb; 500 getBlock(xb); 501 rhs.getBlock(yb); 502 return fp::isLessArray(xb.p, yb.p, op_.N); 503 } 504 bool operator<(const FpT& rhs) const { return isLess(rhs); } 505 bool operator>=(const FpT& rhs) const { return !operator<(rhs); } 506 bool operator>(const FpT& rhs) const { return rhs < *this; } 507 bool operator<=(const FpT& rhs) const { return !operator>(rhs); } 508 /* 509 @note 510 return unexpected order if isMont is set. 511 */ 512 static inline int compareRaw(const FpT& x, const FpT& y) 513 { 514 return fp::compareArray(x.v_, y.v_, op_.N); 515 } 516 bool isLessRaw(const FpT& rhs) const 517 { 518 return fp::isLessArray(v_, rhs.v_, op_.N); 519 } 520 /* 521 set IoMode for operator<<(), or operator>>() 522 */ 523 static inline void setIoMode(int ioMode) 524 { 525 ioMode_ = ioMode; 526 } 527 static void setETHserialization(bool ETHserialization) 528 { 529 if (getBitSize() != 381) return; 530 isETHserialization_ = ETHserialization; 531 } 532 static inline bool isETHserialization() { return isETHserialization_; } 533 static inline int getIoMode() { return ioMode_; } 534 static inline size_t getModBitLen() { return getBitSize(); } 535 static inline void setHashFunc(uint32_t hash(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize)) 536 { 537 op_.hash = hash; 538 } 539 #ifndef CYBOZU_DONT_USE_STRING 540 explicit FpT(const std::string& str, int base = 0) 541 { 542 Serializer::setStr(str, base); 543 } 544 static inline void getModulo(std::string& pstr) 545 { 546 gmp::getStr(pstr, op_.mp); 547 } 548 static std::string getModulo() 549 { 550 std::string s; 551 getModulo(s); 552 return s; 553 } 554 void setHashOf(const std::string& msg) 555 { 556 setHashOf(msg.data(), msg.size()); 557 } 558 // backward compatibility 559 static inline void setModulo(const std::string& mstr, fp::Mode mode = fp::FP_AUTO) 560 { 561 init(mstr, mode); 562 } 563 friend inline std::ostream& operator<<(std::ostream& os, const FpT& self) 564 { 565 self.save(os, fp::detectIoMode(getIoMode(), os)); 566 return os; 567 } 568 friend inline std::istream& operator>>(std::istream& is, FpT& self) 569 { 570 self.load(is, fp::detectIoMode(getIoMode(), is)); 571 return is; 572 } 573 #endif 574 #ifndef CYBOZU_DONT_USE_EXCEPTION 575 static inline void init(int xi_a, const mpz_class& p, fp::Mode mode = fp::FP_AUTO) 576 { 577 bool b; 578 init(&b, xi_a, p, mode); 579 if (!b) throw cybozu::Exception("Fp:init"); 580 } 581 static inline void init(int xi_a, const std::string& mstr, fp::Mode mode = fp::FP_AUTO) 582 { 583 mpz_class p; 584 gmp::setStr(p, mstr); 585 init(xi_a, p, mode); 586 } 587 static inline void init(const mpz_class& p, fp::Mode mode = fp::FP_AUTO) 588 { 589 init(0, p, mode); 590 } 591 static inline void init(const std::string& mstr, fp::Mode mode = fp::FP_AUTO) 592 { 593 init(0, mstr, mode); 594 } 595 template<class OutputStream> 596 void save(OutputStream& os, int ioMode = IoSerialize) const 597 { 598 bool b; 599 save(&b, os, ioMode); 600 if (!b) throw cybozu::Exception("fp:save") << ioMode; 601 } 602 template<class InputStream> 603 void load(InputStream& is, int ioMode = IoSerialize) 604 { 605 bool b; 606 load(&b, is, ioMode); 607 if (!b) throw cybozu::Exception("fp:load") << ioMode; 608 } 609 /* 610 throw exception if x >= p 611 */ 612 template<class S> 613 void setArray(const S *x, size_t n) 614 { 615 bool b; 616 setArray(&b, x, n); 617 if (!b) throw cybozu::Exception("Fp:setArray"); 618 } 619 void setMpz(const mpz_class& x) 620 { 621 bool b; 622 setMpz(&b, x); 623 if (!b) throw cybozu::Exception("Fp:setMpz"); 624 } 625 uint64_t getUint64() const 626 { 627 bool b; 628 uint64_t v = getUint64(&b); 629 if (!b) throw cybozu::Exception("Fp:getUint64:large value"); 630 return v; 631 } 632 int64_t getInt64() const 633 { 634 bool b; 635 int64_t v = getInt64(&b); 636 if (!b) throw cybozu::Exception("Fp:getInt64:large value"); 637 return v; 638 } 639 void getMpz(mpz_class& x) const 640 { 641 bool b; 642 getMpz(&b, x); 643 if (!b) throw cybozu::Exception("Fp:getMpz"); 644 } 645 mpz_class getMpz() const 646 { 647 mpz_class x; 648 getMpz(x); 649 return x; 650 } 651 #endif 652 }; 653 654 template<class tag, size_t maxBitSize> fp::Op FpT<tag, maxBitSize>::op_; 655 template<class tag, size_t maxBitSize> FpT<tag, maxBitSize> FpT<tag, maxBitSize>::inv2_; 656 template<class tag, size_t maxBitSize> int FpT<tag, maxBitSize>::ioMode_ = IoAuto; 657 template<class tag, size_t maxBitSize> bool FpT<tag, maxBitSize>::isETHserialization_ = false; 658 #ifdef MCL_XBYAK_DIRECT_CALL 659 template<class tag, size_t maxBitSize> void (*FpT<tag, maxBitSize>::add)(FpT& z, const FpT& x, const FpT& y); 660 template<class tag, size_t maxBitSize> void (*FpT<tag, maxBitSize>::sub)(FpT& z, const FpT& x, const FpT& y); 661 template<class tag, size_t maxBitSize> void (*FpT<tag, maxBitSize>::neg)(FpT& y, const FpT& x); 662 template<class tag, size_t maxBitSize> void (*FpT<tag, maxBitSize>::mul)(FpT& z, const FpT& x, const FpT& y); 663 template<class tag, size_t maxBitSize> void (*FpT<tag, maxBitSize>::sqr)(FpT& y, const FpT& x); 664 #endif 665 666 } // mcl 667 668 #ifdef CYBOZU_USE_BOOST 669 namespace mcl { 670 671 template<class tag, size_t maxBitSize> 672 size_t hash_value(const mcl::FpT<tag, maxBitSize>& x, size_t v = 0) 673 { 674 return static_cast<size_t>(cybozu::hash64(x.getUnit(), x.getUnitSize(), v)); 675 } 676 677 } 678 #else 679 namespace std { CYBOZU_NAMESPACE_TR1_BEGIN 680 681 template<class tag, size_t maxBitSize> 682 struct hash<mcl::FpT<tag, maxBitSize> > { 683 size_t operator()(const mcl::FpT<tag, maxBitSize>& x, uint64_t v = 0) const 684 { 685 return static_cast<size_t>(cybozu::hash64(x.getUnit(), x.getUnitSize(), v)); 686 } 687 }; 688 689 CYBOZU_NAMESPACE_TR1_END } // std::tr1 690 #endif 691 692 #ifdef _MSC_VER 693 #pragma warning(pop) 694 #endif