/* * Z2k.cpp * */ #include #include "Math/Integer.h" template const int Z2::N_BITS; template const int Z2::N_BYTES; template Z2::Z2(const bigint& x) : Z2() { auto mp = x.get_mpz_t(); memcpy(a, mp->_mp_d, min((size_t)N_BYTES, sizeof(mp_limb_t) * abs(mp->_mp_size))); if (mp->_mp_size < 0) *this = Z2() - *this; normalize(); } template Z2::Z2(const Integer& x) : Z2((uint64_t)x.get()) { } template bool Z2::get_bit(int i) const { return 1 & (a[i / N_LIMB_BITS] >> (i % N_LIMB_BITS)); } template bool Z2::operator==(const Z2& other) const { #ifdef DEBUG_MPN for (int i = 0; i < N_WORDS; i++) cout << "cmp " << hex << a[i] << " " << other.a[i] << endl; #endif return mpn_cmp(a, other.a, N_WORDS) == 0; } template Z2& Z2::invert() { if (get_bit(0) != 1) throw division_by_zero(); Z2 res = 1; for (int i = 0; i < K; i++) { res += Z2((Z2(1) - Z2::Mul(*this, res)).get_bit(i)) << i; } *this = res; return *this; } template Z2 Z2::sqrRoot() { assert(a[0] % 8 == 1); Z2 res = 1; for (int i = 0; i < K - 1; i++) { res += Z2((*this - Z2::Mul(res, res)).get_bit(i + 1)) << i; #ifdef DEBUG_SQR cout << "sqr " << dec << i << " " << hex << res << " " << res * res << " " << (*this - res * res) << endl; #endif } return res; } template void Z2::input(istream& s, bool human) { if (human) { s >> bigint::tmp; *this = bigint::tmp; } else s.read((char*)a, N_BYTES); } template void Z2::output(ostream& s, bool human) const { if (human) { bigint::tmp = *this; s << bigint::tmp; } else s.write((char*)a, N_BYTES); } template ostream& operator<<(ostream& o, const Z2& x) { x.output(o, true); return o; } #define X(N) \ template class Z2; \ template ostream& operator<<(ostream& o, const Z2& x); X(32) X(64) X(96) X(128) X(160) X(192) X(224) X(256) X(288) X(320) X(352) X(384) X(416) X(448) X(512) X(672) X(48) X(112) X(208) X(114) X(130) X(162) X(194) X(324) X(388) X(66) X(210) X(258)