18#ifndef MIE_ZM_VUINT_BIT_LEN
20 #define MIE_ZM_VUINT_BIT_LEN (64 * 9)
29#if !defined(_MSC_VER) || (_MSC_VER >= 1600)
40 #define MIE_ALIGN(x) __declspec(align(x))
42 #ifndef MIE_FORCE_INLINE
43 #define MIE_FORCE_INLINE __forceinline
46 #define MIE_ALLOCA_(x) _alloca(x)
50 #define MIE_ALIGN(x) __attribute__((aligned(16)))
52 #ifndef MIE_FORCE_INLINE
53 #define MIE_FORCE_INLINE __attribute__((always_inline))
56 #define MIE_ALLOCA_(x) __builtin_alloca(x)
62#if defined(_WIN64) || defined(__x86_64__)
64 #define MIE_USE_UNIT64
67 #define MIE_USE_UNIT32
84inline std::istream&
getDigits(std::istream& is, std::string& str,
bool allowNegative =
false)
86 std::ios_base::fmtflags keep = is.flags();
90 if ((
'0' <= c && c <=
'9')
91 || (pos == 1 && (str[0] ==
'0' && c ==
'x'))
92 || (
'a' <= c && c <=
'f')
93 || (
'A' <= c && c <=
'F')
94 || (allowNegative && pos == 0 && c ==
'-')) {
110static inline void errExit(
const std::string& msg =
"")
112 printf(
"err %s\n", msg.c_str());
122template<
class T,
class E = Empty<T> >
133template<
class T,
class E = Empty<T> >
144template<
class T,
class E = Empty<T> >
153template<
class T,
class E = Empty<T> >
158template<
class T,
class E = Empty<T> >
169template<
class T,
class E = Empty<T> >
185 assert(xn > 0 && yn > 0);
186 if (xn != yn)
return xn > yn ? 1 : -1;
187 for (
int i = (
int)xn - 1; i >= 0; i--) {
188 if (x[i] != y[i])
return x[i] > y[i] ? 1 : -1;
226template<
class T,
size_t = 0>
244 size_t m = v_.size();
247 std::fill(&v_[0] + m, &v_[0] + n, (
T)-1);
257 size_t size()
const {
return v_.size(); }
262template<
class T,
size_t BitLen>
265 N = (BitLen +
sizeof(
T) * 8 - 1) / (
sizeof(
T) * 8)
282 std::copy(rhs.v_, rhs.v_ + rhs.size_, v_);
295 size_t size()
const {
return size_; }
304 printf(
"n=%d, N=%d\n", (
int)n, (
int)N);
305 local::errExit(
"too large size. increase MIE_ZM_VUINT_BIT_LEN in include/zm.h");
317template<
class Buffer>
318struct VuintT :
public local::dividable<VuintT<Buffer>,
319 local::addsubmul<VuintT<Buffer>,
320 local::comparable<VuintT<Buffer>,
321 local::shiftable<VuintT<Buffer>, Buffer> > > > {
322 typedef local::PrimitiveFunction
F;
323 typedef typename Buffer::value_type
T;
355 for (
size_t i = 0; i <
size; i++) {
359 Buffer::alloc((
size + 1) / 2);
360 for (
size_t i = 0; i <
size / 2; i++) {
361 (*this)[i] = make64(x[i * 2 + 1], x[i * 2]);
377 Buffer::alloc(
size * 2);
378 for (
size_t i = 0; i <
size; i++) {
380 split64(&H, &L, x[i]);
381 (*this)[i * 2 + 0] = L;
382 (*this)[i * 2 + 1] = H;
386 for (
size_t i = 0; i <
size; i++) {
399 if (i >= this->
size()) {
409 std::ostringstream
os;
414 static const VuintT zero = 0;
417 std::vector<uint32_t> t;
425 os << t[t.size() - 1];
426 for (
size_t i = 1, n = t.size(); i < n; i++) {
427 os << std::setfill(
'0') << std::setw(9) << t[n - 1 - i];
433 os <<
"0x" << std::hex;
434 const size_t n = Buffer::size();
435 os << (*this)[n - 1];
436 for (
size_t i = 1; i < n; i++) {
437 os << std::setfill(
'0') << std::setw(
sizeof(
Unit) * 2) << (*this)[n - 1 - i];
442 local::errExit(
"toString not support base");
452 void set(
const std::string& str,
int base = 0)
455 if (str.size() >= 2 && str[0] ==
'0') {
458 if (base != 0 && base != 16) local::errExit(
"bad base in set(str)");
463 local::errExit(
"not support base in set(str) 0x");
469 if (t.empty()) t = str;
474 std::vector<uint32_t> x;
476 size_t remain = std::min((
int)t.size(), 8);
478 uint32_t v = strtoul(&t[t.size() - remain], &endp, 16);
481 t = t.substr(0, t.size() - remain);
483 set(&x[0], x.size());
489 std::vector<uint32_t> x;
491 size_t remain = std::min((
int)t.size(), 9);
493 uint32_t v = strtol(&t[t.size() - remain], &endp, 10);
496 t = t.substr(0, t.size() - remain);
499 for (
size_t i = 0, n = x.size(); i < n; i++) {
500 (*this) *= 1000000000;
501 (*this) += x[n - 1 - i];
508 throw std::invalid_argument(std::string(
"bad digit `") + str +
"`");
510 void fromStr(
const std::string& str,
int base = 10)
517 return F::compare(&x[0], x.
size(), &y[0], y.size());
519 size_t size()
const {
return Buffer::size(); }
523 return Buffer::size() == 1 && (*this)[0] == 0;
531 T v = (*this)[
size - 1];
534 size_t ret = 1 + (size_t(t.i >> 52) - (1 << 10) + 1) +
535 (
size - 1) *
sizeof(
T) * 8;
541 size_t unit_pos = i / (
sizeof(
T) * 8);
542 size_t bit_pos = i % (
sizeof(
T) * 8);
543 T mask =
T(1) << bit_pos;
544 return ((*
this)[unit_pos] & mask) != 0;
551 if (y.size() > x.
size()) {
554 size_t max = px->
size();
555 size_t min = py->
size();
557 bool c = F::addN(&out[0], &(*px)[0], &(*py)[0], min);
559 c = F::add1(&out[min], &(*px)[min], max - min, c);
566 bool c =
add_in(out, x, y);
568 out.alloc(out.size() + 1);
569 out[out.size() - 1] = 1;
576 const size_t n = x.
size();
578 bool c = F::add1(&out[0], &x[0], n, y);
586 const size_t xn = x.
size();
587 const size_t yn = y.size();
590 bool c = F::subN(&out[0], &x[0], &y[0], yn);
592 c = F::sub1(&out[yn], &x[yn], xn - yn, c);
599 bool c =
sub_in(out, x, y);
601 local::errExit(
"can't sub");
608 const size_t xn = x.
size();
610 F::mul1(&out[0], &x[0], xn, y);
615 const size_t xn = x.
size();
616 const size_t yn = y.size();
619 const Unit *px = &x[0], *py = &y[0];
633 mul(&out[0], px, xn, py, yn);
644 const size_t xn = x.
size();
648 r = F::div1(&(*q)[0], &x[0], xn, y);
651 r = F::mod1(&x[0], xn, y);
666 const size_t xn = x.
size();
667 const size_t yn = y.size();
669 if (y[0] == 0)
return false;
673 int cmp = F::compare(&x[0], xn, &y[0], yn);
679 }
else if (
cmp == 0) {
687 bool directQ =
false;
690 }
else if (q != &x && q != &y) {
691 q->alloc(xn - yn + 1);
695 qt.alloc(xn - yn + 1);
700 bool directR =
false;
701 if (&
r != &x && &
r != &y) {
709 div(pqt, prt, xn, &y[0], yn);
730 return os << x.
toString(
os.flags() & std::ios_base::hex ? 16 : 10);
735 local::getDigits(is, str);
745 const size_t xn = x.
size();
747 for (
int i = (
int)xn - 1; i >= 0; i--) {
750 std::fill(&out[0], &out[0] + n, 0);
759 const size_t unitSize =
sizeof(
T) * 8;
760 assert(0 < n && n < unitSize);
761 const size_t xn = x.
size();
765 size_t rn = unitSize - n;
766 for (
size_t i = 0; i < xn; i++) {
768 out[i] = (t << n) | (prev >> rn);
782 const size_t xn = x.
size();
787 const size_t on = xn - n;
788 for (
size_t i = 0; i < on; i++) {
800 const size_t unitSize =
sizeof(
T) * 8;
801 assert(0 < n && n < unitSize);
802 const size_t xn = x.
size();
804 size_t rn = unitSize - n;
806 for (
int i = (
int)xn - 1; i >= 0; i--) {
808 out[i] = (t >> n) | (prev << rn);
818 const size_t unitSize =
sizeof(
T) * 8;
819 size_t q = n / unitSize;
820 size_t r = n % unitSize;
836 const size_t unitSize =
sizeof(
T) * 8;
837 size_t q = n / unitSize;
838 size_t r = n % unitSize;
858 static inline double GetApp(
const T *x,
size_t xn,
bool up)
865 unsigned int len = int(di.i >> 52) - 1023 + 1;
869 di.i |= M >> (
len - 21);
874 di.i |= L >> (
len + 11);
880 di.i |= L >> (
len + 11);
897 assert(Buffer::size());
898 int i = (int)Buffer::size() - 1;
900 if ((*
this)[i])
break;
902 Buffer::alloc(i ? i + 1: 1);
904 static inline void mul(
T *out,
const T *x,
size_t xn,
const T *y,
size_t yn)
906 assert(xn > 0 && yn > 0);
912 std::fill(&out[xn + 1], &out[xn + yn], 0);
913 F::mul1(&out[0], x, xn, y[0]);
921 for (
size_t i = 1; i < yn; i++) {
922 F::mul1(&t2[0], x, xn, y[i]);
923 F::addN(&out[i], &out[i], &t2[0], xn + 1);
926 static inline void div(
T *q,
T *x,
size_t xn,
const T *y,
size_t yn)
928 assert(xn >= yn && yn >= 2);
930 std::fill(q, q + xn - yn + 1, 0);
934 double yt = GetApp(y, yn,
true);
935 while (F::compare(x, xn, y, yn) >= 0) {
937 double xt = GetApp(x, xn,
false);
938 if (F::compare(&x[xn -
len], yn, y, yn) < 0) {
939 xt *= double(1ULL << (
sizeof(
T) * 8 - 1)) * 2;
944 F::mul1(&t[0], y, yn, qt);
945 bool b = F::subN(&x[xn -
len], &x[xn -
len], &t[0],
len);
949 if (q) q[xn -
len] += qt;
951 while (xn >= yn && x[xn - 1] == 0) {
959class VsintT :
public local::addsubmul<VsintT<V>,
960 local::comparable<VsintT<V>,
961 local::dividable<VsintT<V>,
962 local::hasNegative<VsintT<V>,
963 local::shiftable<VsintT<V> > > > > > {
989 v_.set(isNeg_ ? -x : x);
997 const V&
get()
const {
return v_; }
1002 if (isNeg_)
return "-" + v_.toString(base);
1003 return v_.toString(base);
1005 void set(
const std::string& str,
int base = 10)
1008 if (str.size() > 0 && str[0] ==
'-') {
1010 v_.set(&str[1], base);
1015 void fromStr(
const std::string& str,
int base = 10)
1022 if (x.isNeg_ ^ y.isNeg_) {
1023 if (x.
isZero() && y.isZero())
return 0;
1024 return x.isNeg_ ? -1 : 1;
1027 return V::compare(x.v_, y.v_) * (x.isNeg_ ? -1 : 1);
1030 size_t size()
const {
return v_.size(); }
1035 if ((x.isNeg_ ^ y.isNeg_) == 0) {
1037 V::add(out.v_, x.v_, y.v_);
1038 out.isNeg_ = x.isNeg_;
1041 int r = V::compare(x.v_, y.v_);
1043 V::sub(out.v_, x.v_, y.v_);
1044 out.isNeg_ = x.isNeg_;
1046 V::sub(out.v_, y.v_, x.v_);
1047 out.isNeg_ = y.isNeg_;
1052 if (x.isNeg_ ^ y.isNeg_) {
1054 V::add(out.v_, x.v_, y.v_);
1055 out.isNeg_ = x.isNeg_;
1059 int r = V::compare(x.v_, y.v_);
1061 V::sub(out.v_, x.v_, y.v_);
1062 out.isNeg_ = x.isNeg_;
1064 V::sub(out.v_, y.v_, x.v_);
1065 out.isNeg_ = !y.isNeg_;
1070 V::mul(out.v_, x.v_, y.v_);
1071 out.isNeg_ = x.isNeg_ ^ y.isNeg_;
1081 bool ret = V::div(q ? &(q->v_) : 0,
r.v_, x.v_, y.v_);
1082 if (!
ret)
return false;
1083 bool qsign = x.isNeg_ ^ y.isNeg_;
1093 r.isNeg_ = y.isNeg_;
1095 if (q) q->isNeg_ = qsign;
1101 bool ret = V::div(q ? &(q->v_) : 0,
r.v_, x.v_, y.v_);
1102 bool qsign = x.isNeg_ ^ y.isNeg_;
1103 r.isNeg_ = x.isNeg_;
1104 if (q) q->isNeg_ = qsign;
1111 out.isNeg_ = !x.isNeg_;
1115 if (x.isNeg_)
os <<
"-";
1121 local::getDigits(is, str,
true);
1127 V::shl(out.v_, x.v_, n);
1128 out.isNeg_ = x.isNeg_;
1137 local::errExit(
"shr can't deal with negative value");
1139 V::shr(out.v_, x.v_, n);
1152 VsintT out;
shl(out, *
this, n);
return out;
1156 shl(*
this, *
this, n);
return *
this;
1168template<
class V = Vu
int,
class Tag = Vu
int>
1169class ZmZ :
public local::addsubmul<ZmZ<V, Tag>,
1170 local::comparable<ZmZ<V, Tag>,
1171 local::hasNegative<ZmZ<V, Tag>,
1172 local::inversible<ZmZ<V, Tag> > > > > {
1188 explicit ZmZ(
const std::string& str)
1205 if (x == -2147483647 - 1 || m_ < -x) {
1206 local::errExit(
"x is too small");
1212 void set(
const std::string& str)
1234 return V::compare(x.v_, y.v_);
1238 V::add(out.v_, x.v_, y.v_);
1247 V::add(out.v_, x.v_, m_);
1254 V::sub(out.v_, x.v_, y.v_);
1262 V::sub(out.v_, m_, x.v_);
1268 const size_t xn = x.
size();
1269 const size_t yn = y.size();
1272 t->forceAlloc(xn + yn);
1273 V::mul(&(*t)[0], &x[0], xn, &y[0], yn);
1275 V::div(0, out.v_, *t, m_);
1278 V::mul(out.v_, x.v_, y.v_);
1288 const V&
get()
const {
return v_; }
1303 V::div(&q.v_, t, m_, x.v_);
1304 assert(!t.isZero());
1309 V::div(&q.v_,
s,
s, t);
1316 V::div(&q.v_, t, t,
s);
1326 return v_.toString(base);
1330 size_t size()
const {
return v_.size(); }
1388template<
class T,
class S>
1392 typedef typename Tag::value_type value_type;
1395 for (
size_t i = 0, n = Tag::getBlockSize(y); i < n; i++) {
1396 value_type v = Tag::getBlock(y, i);
1397 int m = (int)
sizeof(value_type) * 8;
1400 while (m > 0 && (v & (value_type(1) << (m - 1))) == 0) {
1404 for (
int j = 0;
j < m;
j++) {
1405 if (v & (value_type(1) <<
j)) {
1414template<
class V,
class Tag>
friend std::istream & operator>>(std::istream &is, VsintT &x)
static void absolute(V &out, const VsintT &in)
void fromStr(const std::string &str, int base=10)
void set(const std::string &str, int base=10)
void set(const uint64_t *ptr, size_t size)
static void shr(VsintT &out, const VsintT &x, size_t n)
static void shl(VsintT &out, const VsintT &x, size_t n)
VsintT(const std::string &str)
static int compare(const VsintT &x, const VsintT &y)
std::string toString(int base=10) const
friend std::ostream & operator<<(std::ostream &os, const VsintT &x)
VsintT & operator<<=(size_t n)
static void sub(VsintT &out, const VsintT &x, const VsintT &y)
VsintT operator<<(size_t n) const
static void add(VsintT &out, const VsintT &x, const VsintT &y)
std::string toStr(int base=10)
static bool div(VsintT *q, VsintT &r, const VsintT &x, const VsintT &y)
static void neg(VsintT &out, const VsintT &x)
static void mul(VsintT &out, const VsintT &x, const VsintT &y)
static void add(ZmZ &out, const ZmZ &x, const ZmZ &y)
void set(const std::string &str)
value_type & operator[](size_t i)
friend std::ostream & operator<<(std::ostream &os, const ZmZ &x)
static void setModulo(const V &m)
void set(const uint64_t *x, size_t size)
static void mul(ZmZ &out, const ZmZ &x, const ZmZ &y)
void set(const uint32_t *x, size_t size)
static void sub(ZmZ &out, const ZmZ &x, const ZmZ &y)
std::string toString(int base=10) const
static int compare(const ZmZ &x, const ZmZ &y)
const value_type & operator[](size_t i) const
ZmZ(const std::string &str)
static void inv(ZmZ &out, const ZmZ &x)
static void neg(ZmZ &out, const ZmZ &x)
static const V & getModulo()
void verify(size_t n) const
FixedBuffer(const FixedBuffer &rhs)
FixedBuffer & operator=(const FixedBuffer &rhs)
void forceAlloc(size_t n)
const T & operator[](size_t n) const
void moveFrom(const FixedBuffer &rhs)
const T & operator[](size_t n) const
void moveFrom(VariableBuffer &rhs)
static const Reg16 di(Operand::DI)
std::istream & getDigits(std::istream &is, std::string &str, bool allowNegative=false)
T power(const T &x, const S &y)
VuintT< local::FixedBuffer< mie::Unit, MIE_ZM_VUINT_BIT_LEN > > Vuint
void swap(picojson::value &x, picojson::value &y)
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
#define T(meth, val, expected)
unsigned __int64 uint64_t
VuintT(const uint64_t *x, size_t size)
static void shrUnit(VuintT &out, const VuintT &x, size_t n)
void set(const uint64_t *x, size_t size)
local::PrimitiveFunction F
static T div1(VuintT *q, const VuintT &x, T y)
static void add(VuintT &out, const VuintT &x, const VuintT &y)
friend std::ostream & operator<<(std::ostream &os, const VuintT &x)
void set(const std::string &str, int base=0)
static void div(T *q, T *x, size_t xn, const T *y, size_t yn)
static void shlUnit(VuintT &out, const VuintT &x, size_t n)
static void mul(T *out, const T *x, size_t xn, const T *y, size_t yn)
VuintT(const uint32_t *x, size_t size)
static void shlBit(VuintT &out, const VuintT &x, size_t n)
static void add(VuintT &out, const VuintT &x, uint32_t y)
static bool sub_in(VuintT &out, const VuintT &x, const VuintT &y)
static void shl(VuintT &out, const VuintT &x, size_t n)
static void shr(VuintT &out, const VuintT &x, size_t n)
static bool add_in(VuintT &out, const VuintT &x, const VuintT &y)
static int compare(const VuintT &x, const VuintT &y)
static void mul1(VuintT &out, const VuintT &x, T y)
static void shrBit(VuintT &out, const VuintT &x, size_t n)
std::string toString(int base=10) const
std::string toStr(int base=10) const
T getAtWithCheck(size_t i) const
static void mul(VuintT &out, const VuintT &x, const VuintT &y)
void fromStr(const std::string &str, int base=10)
static void sub(VuintT &out, const VuintT &x, const VuintT &y)
void set(const uint32_t *x, size_t size)
bool testBit(size_t i) const
friend std::istream & operator>>(std::istream &is, VuintT &x)
static bool div(VuintT *q, VuintT &r, const VuintT &x, const VuintT &y)
VuintT(const std::string &str)
static Unit(* div1)(Unit *q, const Unit *x, size_t n, Unit y)
static bool(* sub1)(Unit *out, const Unit *x, size_t n, Unit y)
static int compare(const Unit *x, size_t xn, const Unit *y, size_t yn)
static bool(* add1)(Unit *out, const Unit *x, size_t n, Unit y)
static void(* mul1)(Unit *out, const Unit *x, size_t n, Unit y)
static Unit(* mod1)(const Unit *x, size_t n, Unit y)
static bool(* subN)(Unit *out, const Unit *x, const Unit *y, size_t n)
static bool(* addN)(Unit *out, const Unit *x, const Unit *y, size_t n)
MIE_FORCE_INLINE friend T operator-(const T &a, const T &b)
MIE_FORCE_INLINE T & operator*=(const T &rhs)
MIE_FORCE_INLINE T & operator+=(const N &rhs)
MIE_FORCE_INLINE friend T operator*(const T &a, const T &b)
MIE_FORCE_INLINE friend T operator+(const T &a, const T &b)
MIE_FORCE_INLINE T & operator-=(const T &rhs)
MIE_FORCE_INLINE friend bool operator>(const T &x, const T &y)
MIE_FORCE_INLINE friend bool operator!=(const T &x, const T &y)
MIE_FORCE_INLINE friend bool operator==(const T &x, const T &y)
MIE_FORCE_INLINE friend bool operator<=(const T &x, const T &y)
MIE_FORCE_INLINE friend bool operator<(const T &x, const T &y)
MIE_FORCE_INLINE friend bool operator>=(const T &x, const T &y)
MIE_FORCE_INLINE friend T operator/(const T &a, const T &b)
MIE_FORCE_INLINE T & operator/=(const T &rhs)
MIE_FORCE_INLINE friend T operator%(const T &a, const T &b)
MIE_FORCE_INLINE T & operator%=(const T &rhs)
MIE_FORCE_INLINE T operator-() const
MIE_FORCE_INLINE void inverse()
MIE_FORCE_INLINE T & operator/=(const T &x)
MIE_FORCE_INLINE friend T operator/(const T &x, const T &y)
MIE_FORCE_INLINE T operator<<(size_t n) const
MIE_FORCE_INLINE T & operator>>=(size_t n)
MIE_FORCE_INLINE T operator>>(size_t n) const
MIE_FORCE_INLINE T & operator<<=(size_t n)
static value_type getBlock(const int &x, size_t)
static size_t getBlockSize(const int &)
static value_type getBlock(const size_t &x, size_t)
static size_t getBlockSize(const size_t &)
static size_t getBlockSize(const T &x)
static value_type getBlock(const T &x, size_t i)
void cmp(const Operand &op, uint32 imm)