|
|
|
@ -859,4 +859,55 @@ public: |
|
|
|
|
#endif |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Barrett Reduction |
|
|
|
|
*/ |
|
|
|
|
struct Modp { |
|
|
|
|
static const size_t unitBitSize = sizeof(mcl::fp::Unit) * 8; |
|
|
|
|
mpz_class p_; |
|
|
|
|
mpz_class u_; |
|
|
|
|
mpz_class a_; |
|
|
|
|
size_t N_; |
|
|
|
|
// x &= 1 << (unitBitSize * unitSize)
|
|
|
|
|
void shrinkSize(mpz_class &x, size_t unitSize) const |
|
|
|
|
{ |
|
|
|
|
size_t u = mcl::gmp::getUnitSize(x); |
|
|
|
|
if (u < unitSize) return; |
|
|
|
|
bool b; |
|
|
|
|
mcl::gmp::setArray(&b, x, mcl::gmp::getUnit(x), unitSize); |
|
|
|
|
assert(b); |
|
|
|
|
} |
|
|
|
|
void init(const mpz_class& p, size_t unitSize) |
|
|
|
|
{ |
|
|
|
|
p_ = p; |
|
|
|
|
N_ = unitSize; |
|
|
|
|
u_ = (mpz_class(1) << (unitBitSize * 2 * N_)) / p_; |
|
|
|
|
a_ = mpz_class(1) << (unitBitSize * (N_ + 1)); |
|
|
|
|
} |
|
|
|
|
void modp(mpz_class& r, const mpz_class& t) const |
|
|
|
|
{ |
|
|
|
|
assert(0 <= t && t < mpz_class(1) << (unitBitSize * 2 * N_)); |
|
|
|
|
if (t < p_) { |
|
|
|
|
r = t; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
mpz_class q; |
|
|
|
|
q = t; |
|
|
|
|
q >>= unitBitSize * (N_ - 1); |
|
|
|
|
q *= u_; |
|
|
|
|
q >>= unitBitSize * (N_ + 1); |
|
|
|
|
q *= p_; |
|
|
|
|
shrinkSize(q, N_ + 1); |
|
|
|
|
r = t; |
|
|
|
|
shrinkSize(r, N_ + 1); |
|
|
|
|
r -= q; |
|
|
|
|
if (r < 0) { |
|
|
|
|
r += a_; |
|
|
|
|
} |
|
|
|
|
if (r >= p_) { |
|
|
|
|
r -= p_; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
} // mcl
|
|
|
|
|