#include <iostream>
#include <cstdint>
#include <cstdlib>
#ifndef GMP_ASSERT_ALWAYS
#define GMP_ASSERT_ALWAYS(cc) do {if (!(cc)) abort();} while (0)
#endif
#ifndef GMP_LIMB_BITS
#define GMP_LIMB_BITS 4
#endif
#define GMP_NUMB_MASK (2 * (1ul << (GMP_LIMB_BITS - 1)) - 1)
#define BINOP_MASK(op, type) \
mp_limb_t& operator op##=(const type& rhs) { \
limbo = (limbo op rhs.limbo) & GMP_NUMB_MASK; \
return *this; \
}
#define BINOP_NOMASK(op, type) \
mp_limb_t& operator op##=(const type& rhs) { \
limbo = limbo op rhs.limbo; \
return *this; \
}
typedef std::conditional<(GMP_NUMB_MASK <= 0xffff), uint16_t, uint32_t >::type type24;
typedef std::conditional<(GMP_NUMB_MASK <= 0xff), uint8_t, type24>::type mtype;
class mp_limb_t {
public:
mp_limb_t() {} mp_limb_t(const unsigned int rhs) { limbo = rhs & GMP_NUMB_MASK; }
BINOP_MASK(+, mp_limb_t)
BINOP_MASK(-, mp_limb_t)
BINOP_MASK(*, mp_limb_t)
BINOP_NOMASK(/, mp_limb_t)
BINOP_NOMASK(%, mp_limb_t)
BINOP_NOMASK(&, mp_limb_t)
BINOP_NOMASK(|, mp_limb_t)
BINOP_NOMASK(^, mp_limb_t)
mp_limb_t& operator<<=(const unsigned int rhs) {
GMP_ASSERT_ALWAYS (rhs < GMP_LIMB_BITS);
limbo = (limbo << rhs) & GMP_NUMB_MASK;
return *this;
}
mp_limb_t& operator>>=(const unsigned int rhs) {
GMP_ASSERT_ALWAYS (rhs < GMP_LIMB_BITS);
limbo = limbo >> rhs;
return *this;
}
mp_limb_t operator-() {
return static_cast<mp_limb_t>((-limbo) & GMP_NUMB_MASK);
}
mp_limb_t operator~() {
return static_cast<mp_limb_t>((~limbo) & GMP_NUMB_MASK);
}
operator unsigned int() const { return limbo; }
operator int() const { return limbo; }
#define RELOP(op) \
inline bool operator op(const mp_limb_t rhs) { \
return limbo op rhs.limbo; \
}
RELOP(==)
RELOP(!=)
RELOP(<)
RELOP(>)
RELOP(<=)
RELOP(>=)
private:
mtype limbo;
};
#define BINOP2(op, type) \
inline mp_limb_t operator op(mp_limb_t lhs, const type& rhs) { \
lhs op##= rhs; \
return lhs; \
}
BINOP2(+, mp_limb_t)
BINOP2(-, mp_limb_t)
BINOP2(*, mp_limb_t)
BINOP2(/, mp_limb_t)
BINOP2(%, mp_limb_t)
BINOP2(&, mp_limb_t)
BINOP2(|, mp_limb_t)
BINOP2(^, mp_limb_t)
BINOP2(<<, unsigned int)
BINOP2(>>, unsigned int)