7 #define OUTPUT_SIGN(sa,sb,ua,ub) \
11 ua = negA ? -sa : sa; \
12 ub = negB ? -sb : sb; \
13 (negA && !negB) || (!negA && negB); })
16 #define MASK_LO ((((int128_t)1)<<64)-1)
17 #define MASK_HI (~MASK_LO)
20 int64x64_t::Mul (int64x64_t
const &o)
25 int128_t result = Umul (a, b);
27 result = negResult ? -result : result;
32 int64x64_t::Umul (uint128_t a, uint128_t b)
36 uint128_t aH = (a >> 64) & MASK_LO;
37 uint128_t bH = (b >> 64) & MASK_LO;
40 uint128_t hiPart,loPart,midPart;
48 midPart = aL * bH + aH * bL;
50 result = (loPart >> 64) + (midPart & MASK_LO);
57 "High precision 128 bits multiplication error: multiplication overflow.");
61 int64x64_t::Div (int64x64_t
const &o)
66 int128_t result = Divu (a, b);
67 result = negResult ? -result : result;
72 int64x64_t::Divu (uint128_t a, uint128_t b)
74 uint128_t quo = a / b;
75 uint128_t rem = (a % b);
76 uint128_t result = quo << 64;
78 uint128_t tmp = rem >> 64;
90 result = result + quo;
95 int64x64_t::MulByInvert (
const int64x64_t &o)
97 bool negResult = _v < 0;
98 uint128_t a = negResult ? -_v : _v;
99 uint128_t result = UmulByInvert (a, o._v);
101 _v = negResult ? -result : result;
104 int64x64_t::UmulByInvert (uint128_t a, uint128_t b)
106 uint128_t result, ah, bh, al, bl;
113 mid = ah * bl + al * bh;
119 int64x64_t::Invert (uint64_t v)
126 result._v = Divu (a, v);
127 int64x64_t tmp = int64x64_t (v,
false);
128 tmp.MulByInvert (result);
129 if (tmp.GetHigh () != 1)