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