16#ifndef __LAMMP_LONGLONG_H__
17#define __LAMMP_LONGLONG_H__
22#elif defined(USE_ASM) && (defined(__x86_64__)) && (defined(__GNUC__) || defined(__clang__))
28#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
32#define ctz_shr_u64(r, x, cnt) \
34 unsigned long long _x_ = (x); \
35 unsigned long _bits_ = 0; \
36 _BitScanForward64(&_bits_, _x_); \
43#define clz_shl_u64(r, x, cnt) \
45 unsigned long long _x_ = (x); \
46 unsigned long _idx_; \
47 _BitScanReverse64(&_idx_, _x_); \
48 (cnt) = 63 - (int)_idx_; \
49 (r) = (unsigned long long)(_x_ << (cnt)); \
51#elif defined(__GNUC__) || defined(__clang__)
55#define ctz_shr_u64(r, x, cnt) \
57 unsigned long long _x_ = (x); \
58 (cnt) = __builtin_ctzll(_x_); \
64#define clz_shl_u64(r, x, cnt) \
66 unsigned long long _x_ = (x); \
67 (cnt) = __builtin_clzll(_x_); \
68 (r) = (unsigned long long)(_x_ << (cnt)); \
74#define ctz_shr_u64(r, x, cnt) \
78 while ((_x_ & 1) == 0) { \
88#define clz_shl_u64(r, x, cnt) \
92 while ((_x_ & 0x8000000000000000ULL) == 0) { \
105#define ctz_shr_u32(r, x, cnt) \
107 unsigned long _x_ = (x); \
108 unsigned long _bits_ = 0; \
109 _BitScanForward(&_bits_, _x_); \
111 (r) = _x_ >> (cnt); \
116#define clz_shl_u32(r, x, cnt) \
118 unsigned long _x_ = (x); \
119 unsigned long _idx_; \
120 _BitScanReverse(&_idx_, _x_); \
121 (cnt) = 31 - (int)_idx_; \
122 (r) = _x_ << (cnt); \
124#elif defined(__GNUC__) || defined(__clang__)
128#define ctz_shr_u32(r, x, cnt) \
130 unsigned int _x_ = (x); \
131 (cnt) = __builtin_ctz(_x_); \
132 (r) = _x_ >> (cnt); \
137#define clz_shl_u32(r, x, cnt) \
139 unsigned int _x_ = (x); \
140 (cnt) = __builtin_clz(_x_); \
141 (r) = _x_ << (cnt); \
147#define ctz_shr_u32(r, x, cnt) \
149 uint32_t _x_ = (x); \
151 while ((_x_ & 1U) == 0) { \
161#define clz_shl_u32(r, x, cnt) \
163 uint32_t _x_ = (x); \
165 while ((_x_ & 0x80000000U) == 0) { \
174static inline void _umul64to128_(uint64_t a, uint64_t b, uint64_t *low, uint64_t *high) {
175#if (defined(__GNUC__) || defined(__clang__))
176 __uint128_t prod = (__uint128_t)a * b;
177 *low = (uint64_t)prod;
178 *high = (uint64_t)(prod >> 64);
179#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
180 *low = _umul128(a, b, high);
182 uint64_t ah = a >> 32, bh = b >> 32;
183 a = (uint32_t)a, b = (uint32_t)b;
184 uint64_t
r0 = a * b,
r1 = a * bh,
r2 = ah * b,
r3 = ah * bh;
185 r3 += (
r1 >> 32) + (
r2 >> 32);
186 r1 = (uint32_t)
r1,
r2 = (uint32_t)
r2;
189 *high =
r3 + (
r1 >> 32);
190 *low = (
r1 << 32) | (uint32_t)
r0;
195#if (defined(__GNUC__) || defined(__clang__)) && defined(__SIZEOF_INT128__)
196 __uint128_t
t = (__uint128_t)a * (__uint128_t)b;
197 return (uint64_t)(
t >> 64);
198#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
199 return __umulh(a, b);
201 uint64_t ah = a >> 32, bh = b >> 32;
202 a = (uint32_t)a, b = (uint32_t)b;
203 uint64_t
r0 = a * b,
r1 = a * bh,
r2 = ah * b,
r3 = ah * bh;
204 r3 += (
r1 >> 32) + (
r2 >> 32);
205 r1 = (uint32_t)
r1,
r2 = (uint32_t)
r2;
208 return r3 + (
r1 >> 32);
212static inline void _umul128to256_(uint64_t a_high, uint64_t a_low, uint64_t b_high, uint64_t b_low, uint64_t rr[4]) {
213 uint64_t p1_low, p1_high;
214 uint64_t p2_low, p2_high;
227 uint64_t carry = (rr[1] < p1_low) ? 1 : 0;
229 carry += (rr[1] < p2_low) ? 1 : 0;
232 carry = (rr[2] < carry) ? 1 : 0;
234 carry += (rr[2] < p1_high) ? 1 : 0;
236 carry += (rr[2] < p2_high) ? 1 : 0;
241static inline void _usqr128to256_(uint64_t a_high, uint64_t a_low, uint64_t rr[4]) {
242 uint64_t p1_low, p1_high;
253 rr[3] += p1_high >> 63;
254 p1_high = (p1_high << 1) | (p1_low >> 63);
257 uint64_t carry = (rr[1] < p1_low) ? 1 : 0;
260 carry = (rr[2] < carry) ? 1 : 0;
262 carry += (rr[2] < p1_high) ? 1 : 0;
267static inline void _umul128to128_(uint64_t a_high, uint64_t a_low, uint64_t b_high, uint64_t b_low, uint64_t rr[2]) {
269 rr[1] += a_low * b_high;
270 rr[1] += a_high * b_low;
273static inline uint64_t
_udiv128by64to64_(uint64_t numhi, uint64_t numlo, uint64_t den, uint64_t* r) {
274#if (defined(__GNUC__) || defined(__clang__)) && defined(USE_ASM)
276 __asm__(
"div %[v]" :
"=a"(result),
"=d"(*r) : [v]
"r"(den),
"a"(numlo),
"d"(numhi));
278#elif defined(__GNUC__)
279 __uint128_t num = (__uint128_t)numhi << 64 | numlo;
280 uint64_t result = num / den;
283#elif defined(_MSC_VER) && (defined(_M_X64)) && (!defined(__clang__))
284 return _udiv128(numhi, numlo, den, r);
286 const uint64_t b = ((uint64_t)1 << 32);
295 uint64_t den10 = den;
296 uint64_t num10 = numlo;
319 numhi |= (numlo >> (-shift & 63)) & (uint64_t)(-(int64_t)shift >> 63);
322 num1 = (uint32_t)(numlo >> 32);
323 num0 = (uint32_t)(numlo & 0xFFFFFFFFu);
324 den1 = (uint32_t)(den >> 32);
325 den0 = (uint32_t)(den & 0xFFFFFFFFu);
330 c2 = rhat * b + num1;
332 qhat -= (
c1 - c2 > den) ? 2 : 1;
335 rem = numhi * b + num1 - q1 * den;
340 c2 = rhat * b + num0;
342 qhat -= (
c1 - c2 > den) ? 2 : 1;
345 q = ((uint64_t)q1 << 32) | q0;
348 *r = num10 - q * den10;
356#define _u128lshl(x, y, n) \
358 (*((x) + 1)) = ((*(y)) >> (64 - (n))) | ((*((y) + 1)) << (n)); \
359 (*(x)) = (*(y)) << (n); \
362#define _u128lshr(x, y, n) \
364 (*(x)) = ((*(y)) >> (n)) | ((*((y) + 1)) << (64 - (n))); \
365 (*((x) + 1)) = (*((y) + 1)) >> (n); \
368#define _u128high(x) (*((x) + 1))
370#define _u128low(x) (*(x))
372#define _u128add(r, x, y) \
374 (*(r)) = *(x) + *(y); \
375 (*((r) + 1)) = (*((x) + 1)) + (*((y) + 1)) + ((*(r)) < (*(y)) ? 1 : 0); \
378#define _u128add64(r, x, _i64) \
380 (*(r)) = *(x) + (_i64); \
381 (*((r) + 1)) = (*((x) + 1)) + (((*(r)) < (_i64)) ? 1 : 0); \
384#define _u128sub64(r, x, _i64) \
386 uint64_t _c_ = (x)[0] < (_i64); \
387 (r)[0] = (x)[0] - (_i64); \
388 (r)[1] = (x)[1] - _c_; \
392#define _u128cmp(x, y) ((x)[1] < (y)[1] || ((x)[1] == (y)[1] && (x)[0] < (y)[0]))
394#define _u128sub(r, x, y) \
396 uint64_t _c_ = (x)[0] < (y)[0]; \
397 (r)[0] = (x)[0] - (y)[0]; \
398 (r)[1] = (x)[1] - (y)[1] - _c_; \
401#define _u128mul(r, x, y) _umul64to128_((x), (y), (r), (((r) + 1)))
403#define _u192add(i192, j192) \
405 (i192)[0] += (j192)[0]; \
406 uint64_t _c_ = ((i192)[0] < (j192)[0]) ? 1 : 0; \
408 _c_ = ((i192)[1] < _c_) ? 1 : 0; \
409 (i192)[1] += (j192)[1]; \
410 _c_ += ((i192)[1] < (j192)[1]) ? 1 : 0; \
411 (i192)[2] += _c_ + (j192)[2]; \
414#define _u192sub(i192, j192) \
416 uint64_t _b_ = ((i192)[0] < (j192)[0]) ? 1 : 0; \
417 (i192)[0] -= (j192)[0]; \
418 uint64_t _b1_ = ((i192)[1] < (j192)[1]) ? 1 : 0; \
419 (i192)[1] -= (j192)[1]; \
420 _b1_ += ((i192)[1] < _b_) ? 1 : 0; \
422 (i192)[2] = (i192)[2] - ((j192)[2] + _b1_); \
425#define _add_ssaaaa(sh, sl, ah, al, bh, bl) \
429 (sh) = (ah) + (bh) + (_x_ < (al)); \
433#define _sub_ddmmss(sh, sl, ah, al, bh, bl) \
437 (sh) = (ah) - (bh) - ((al) < (bl)); \
443#define _udiv_qrnnd_preinv(q, r, nh, nl, d, di) \
445 uint64_t _qh_, _ql_, _r_, _mask_; \
446 _umul64to128_((nh), (di), &_ql_, &_qh_); \
447 _add_ssaaaa(_qh_, _ql_, _qh_, _ql_, (nh) + 1, (nl)); \
448 _r_ = (nl) - _qh_ * (d); \
449 _mask_ = -(mp_limb_t)(_r_ > _ql_); \
451 _r_ += _mask_ & (d); \
462#define _udiv_qr_3by2(q, r1, r0, n2, n1, n0, d1, d0, dinv) \
464 mp_limb_t _q0_, _t1_, _t0_, _mask_; \
465 _umul64to128_((n2), (dinv), &_q0_, &(q)); \
466 _add_ssaaaa((q), _q0_, (q), _q0_, (n2), (n1)); \
468 (r1) = (n1) - (d1) * (q); \
469 _sub_ddmmss((r1), (r0), (r1), (n0), (d1), (d0)); \
470 _umul64to128_((d0), (q), &_t0_, &_t1_); \
471 _sub_ddmmss((r1), (r0), (r1), (r0), _t1_, _t0_); \
474 _mask_ = -(uint64_t)((r1) >= _q0_); \
476 _add_ssaaaa((r1), (r0), (r1), (r0), _mask_ & (d1), _mask_ & (d0)); \
477 if ((r1) >= (d1)) { \
478 if ((r1) > (d1) || (r0) >= (d0)) { \
480 _sub_ddmmss((r1), (r0), (r1), (r0), (d1), (d0)); \
487#define _udiv32by32_q_preinv(q, n0, dinv) \
489 uint64_t _hi_, _lo_; \
490 _umul64to128_((n0), (dinv), &_lo_, &_hi_); \
498#define _U64_SHIFT_MASK 0x3F
499#define _ADD_MARKER 0x40
513 uint32_t floor_log_2_d = 63 - shift;
516 if ((d & (d - 1)) == 0) {
522 result.
more = (uint8_t)(floor_log_2_d - (branchfree != 0));
524 uint64_t proposed_m, rem;
529 const uint64_t e = d - rem;
532 if (!branchfree && e < ((uint64_t)1 << floor_log_2_d)) {
534 more = (uint8_t)floor_log_2_d;
541 proposed_m += proposed_m;
542 const uint64_t twice_rem = rem + rem;
543 if (twice_rem >= d || twice_rem < rem)
547 result.
magic = 1 + proposed_m;
568 uint64_t
t = ((numer - q) >> 1) + q;
569 return t >> denom->
more;
static uint64_t _umul64to64hi_(uint64_t a, uint64_t b)
#define _U64_SHIFT_MASK
from https://libdivide.com/
static _udiv64_t _udiv64_gen_internal_(uint64_t d, int branchfree)
static void _umul64to128_(uint64_t a, uint64_t b, uint64_t *low, uint64_t *high)
static void _umul128to256_(uint64_t a_high, uint64_t a_low, uint64_t b_high, uint64_t b_low, uint64_t rr[4])
static _udiv64_t _udiv64_gen(uint64_t d)
static void _umul128to128_(uint64_t a_high, uint64_t a_low, uint64_t b_high, uint64_t b_low, uint64_t rr[2])
static uint64_t _udiv64by64_q_preinv(uint64_t numer, const _udiv64_t *denom)
static uint64_t _udiv128by64to64_(uint64_t numhi, uint64_t numlo, uint64_t den, uint64_t *r)
#define clz_shl_u64(r, x, cnt)
static void _usqr128to256_(uint64_t a_high, uint64_t a_low, uint64_t rr[4])