#ifndef LONGLONG_MSC_H
#define LONGLONG_MSC_H
#include <stdlib.h>
#include <intrin.h>
#include <immintrin.h>
#if defined(_M_IX86) || FLINT_BITS == 32
# define flint_clz _lzcnt_u32
# define flint_ctz _tzcnt_u32
# define _FLINT_ADC _addcarry_u32
# define _FLINT_SBB _subborrow_u32
# define umul_ppmm(r1, r0, u, v) \
do \
{ \
unsigned __int64 _tmp = __emulu(u, v); \
(r0) = _tmp; \
(r1) = _tmp >> 32; \
} while (0)
# define smul_ppmm(r1, r0, u, v) \
do \
{ \
__int64 _tmp = __emul(u, v); \
(r0) = _tmp; \
(r1) = _tmp >> 32; \
} while (0)
# define _FLINT_DIV(_n1, _n0, _dx, _rp) _udiv64((unsigned __int64) (_n1) | (unsigned __int64) (_n0), _dx, _rp)
# define _FLINT_IDIV(_n1, _n0, _dx, _rp) _div64((__int64) (_n1) | (__int64) (_n0), _dx, _rp)
#else
# define flint_clz _lzcnt_u64
# define flint_ctz _tzcnt_u64
# define _FLINT_ADC _addcarry_u64
# define _FLINT_SBB _subborrow_u64
#define umul_ppmm(r1, r0, u, v) do { (r0) = _umul128(u, v, (unsigned __int64 *) &(r1)); } while (0)
#define smul_ppmm(r1, r0, u, v) do { (r0) = _mul128(u, v, (__int64 *) &(r1)); } while (0)
# define _FLINT_DIV _udiv128
# define _FLINT_IDIV _div128
#endif
#define add_ssaaaa(s1, s0, a1, a0, b1, b0) \
do \
{ \
unsigned char _carry; \
_carry = _FLINT_ADC(0, a0, b0, &(s0)); \
_FLINT_ADC(_carry, a1, b1, &(s1)); \
} while (0)
#define add_sssaaaaaa(s2, s1, s0, a2, a1, a0, b2, b1, b0) \
do \
{ \
unsigned char _carry; \
_carry = _FLINT_ADC(0, a0, b0, &(s0)); \
_carry = _FLINT_ADC(_carry, a1, b1, &(s1)); \
_FLINT_ADC(_carry, a2, b2, &(s2)); \
} while (0)
#define add_ssssaaaaaaaa(s3, s2, s1, s0, a3, a2, a1, a0, b3, b2, b1, b0) \
do \
{ \
unsigned char _carry; \
_carry = _FLINT_ADC(0, a0, b0, &(s0)); \
_carry = _FLINT_ADC(_carry, a1, b1, &(s1)); \
_carry = _FLINT_ADC(_carry, a2, b2, &(s2)); \
_FLINT_ADC(_carry, a3, b3, &(s3)); \
} while (0)
#define add_sssssaaaaaaaaaa(s4, s3, s2, s1, s0, a4, a3, a2, a1, a0, b4, b3, b2, b1, b0) \
do \
{ \
unsigned char _carry; \
_carry = _FLINT_ADC(0, a0, b0, &(s0)); \
_carry = _FLINT_ADC(_carry, a1, b1, &(s1)); \
_carry = _FLINT_ADC(_carry, a2, b2, &(s2)); \
_carry = _FLINT_ADC(_carry, a3, b3, &(s3)); \
_FLINT_ADC(_carry, a4, b4, &(s4)); \
} while (0)
#define add_ssssssaaaaaaaaaaaa(s5, s4, s3, s2, s1, s0, a5, a4, a3, a2, a1, a0, b5, b4, b3, b2, b1, b0) \
do \
{ \
unsigned char _carry; \
_carry = _FLINT_ADC(0, a0, b0, &(s0)); \
_carry = _FLINT_ADC(_carry, a1, b1, &(s1)); \
_carry = _FLINT_ADC(_carry, a2, b2, &(s2)); \
_carry = _FLINT_ADC(_carry, a3, b3, &(s3)); \
_carry = _FLINT_ADC(_carry, a4, b4, &(s4)); \
_FLINT_ADC(_carry, a5, b5, &(s5)); \
} while (0)
#define add_sssssssaaaaaaaaaaaaaa(s6, s5, s4, s3, s2, s1, s0, a6, a5, a4, a3, a2, a1, a0, b6, b5, b4, b3, b2, b1, b0) \
do \
{ \
unsigned char _carry; \
_carry = _FLINT_ADC(0, a0, b0, &(s0)); \
_carry = _FLINT_ADC(_carry, a1, b1, &(s1)); \
_carry = _FLINT_ADC(_carry, a2, b2, &(s2)); \
_carry = _FLINT_ADC(_carry, a3, b3, &(s3)); \
_carry = _FLINT_ADC(_carry, a4, b4, &(s4)); \
_carry = _FLINT_ADC(_carry, a5, b5, &(s5)); \
_FLINT_ADC(_carry, a6, b6, &(s6)); \
} while (0)
#define add_ssssssssaaaaaaaaaaaaaaaa(s7, s6, s5, s4, s3, s2, s1, s0, a7, a6, a5, a4, a3, a2, a1, a0, b7, b6, b5, b4, b3, b2, b1, b0) \
do \
{ \
unsigned char _carry; \
_carry = _FLINT_ADC(0, a0, b0, &(s0)); \
_carry = _FLINT_ADC(_carry, a1, b1, &(s1)); \
_carry = _FLINT_ADC(_carry, a2, b2, &(s2)); \
_carry = _FLINT_ADC(_carry, a3, b3, &(s3)); \
_carry = _FLINT_ADC(_carry, a4, b4, &(s4)); \
_carry = _FLINT_ADC(_carry, a5, b5, &(s5)); \
_carry = _FLINT_ADC(_carry, a6, b6, &(s6)); \
_FLINT_ADC(_carry, a7, b7, &(s7)); \
} while (0)
#define sub_ddmmss(s1, s0, a1, a0, b1, b0) \
do \
{ \
unsigned char _carry; \
_carry = _FLINT_SBB(0, a0, b0, &(s0)); \
_FLINT_SBB(_carry, a1, b1, &(s1)); \
} while (0)
#define sub_dddmmmsss(s2, s1, s0, a2, a1, a0, b2, b1, b0) \
do \
{ \
unsigned char _carry; \
_carry = _FLINT_SBB(0, a0, b0, &(s0)); \
_carry = _FLINT_SBB(_carry, a1, b1, &(s1)); \
_FLINT_SBB(_carry, a2, b2, &(s2)); \
} while (0)
#define sub_ddddmmmmssss(s3, s2, s1, s0, a3, a2, a1, a0, b3, b2, b1, b0) \
do \
{ \
unsigned char _carry; \
_carry = _FLINT_SBB(0, a0, b0, &(s0)); \
_carry = _FLINT_SBB(_carry, a1, b1, &(s1)); \
_carry = _FLINT_SBB(_carry, a2, b2, &(s2)); \
_FLINT_SBB(_carry, a3, b3, &(s3)); \
} while (0)
#define sub_dddddmmmmmsssss(s4, s3, s2, s1, s0, a4, a3, a2, a1, a0, b4, b3, b2, b1, b0) \
do \
{ \
unsigned char _carry; \
_carry = _FLINT_SBB(0, a0, b0, &(s0)); \
_carry = _FLINT_SBB(_carry, a1, b1, &(s1)); \
_carry = _FLINT_SBB(_carry, a2, b2, &(s2)); \
_carry = _FLINT_SBB(_carry, a3, b3, &(s3)); \
_FLINT_SBB(_carry, a4, b4, &(s4)); \
} while (0)
#define sub_ddddddmmmmmmssssss(s5, s4, s3, s2, s1, s0, a5, a4, a3, a2, a1, a0, b5, b4, b3, b2, b1, b0) \
do \
{ \
unsigned char _carry; \
_carry = _FLINT_SBB(0, a0, b0, &(s0)); \
_carry = _FLINT_SBB(_carry, a1, b1, &(s1)); \
_carry = _FLINT_SBB(_carry, a2, b2, &(s2)); \
_carry = _FLINT_SBB(_carry, a3, b3, &(s3)); \
_carry = _FLINT_SBB(_carry, a4, b4, &(s4)); \
_FLINT_SBB(_carry, a5, b5, &(s5)); \
} while (0)
#define sub_dddddddmmmmmmmsssssss(s6, s5, s4, s3, s2, s1, s0, a6, a5, a4, a3, a2, a1, a0, b6, b5, b4, b3, b2, b1, b0) \
do \
{ \
unsigned char _carry; \
_carry = _FLINT_SBB(0, a0, b0, &(s0)); \
_carry = _FLINT_SBB(_carry, a1, b1, &(s1)); \
_carry = _FLINT_SBB(_carry, a2, b2, &(s2)); \
_carry = _FLINT_SBB(_carry, a3, b3, &(s3)); \
_carry = _FLINT_SBB(_carry, a4, b4, &(s4)); \
_carry = _FLINT_SBB(_carry, a5, b5, &(s5)); \
_FLINT_SBB(_carry, a6, b6, &(s6)); \
} while (0)
#define sub_ddddddddmmmmmmmmssssssss(s7, s6, s5, s4, s3, s2, s1, s0, a7, a6, a5, a4, a3, a2, a1, a0, b7, b6, b5, b4, b3, b2, b1, b0) \
do \
{ \
unsigned char _carry; \
_carry = _FLINT_SBB(0, a0, b0, &(s0)); \
_carry = _FLINT_SBB(_carry, a1, b1, &(s1)); \
_carry = _FLINT_SBB(_carry, a2, b2, &(s2)); \
_carry = _FLINT_SBB(_carry, a3, b3, &(s3)); \
_carry = _FLINT_SBB(_carry, a4, b4, &(s4)); \
_carry = _FLINT_SBB(_carry, a5, b5, &(s5)); \
_carry = _FLINT_SBB(_carry, a6, b6, &(s6)); \
_FLINT_SBB(_carry, a7, b7, &(s7)); \
} while (0)
#define udiv_qrnnd(q, r, n1, n0, dx) do { (q) = _FLINT_DIV(n1, n0, dx, &(r)); } while (0)
#define sdiv_qrnnd(q, r, n1, n0, dx) do { (q) = _FLINT_IDIV(n1, n0, dx, &(r)); } while (0)
#endif