17 #ifndef RYU_D2S_INTRINSICS_H 18 #define RYU_D2S_INTRINSICS_H 24 #include "ryu/common.h" 28 #if defined(__SIZEOF_INT128__) && !defined(_MSC_VER) && !defined(RYU_ONLY_64_BIT_OPS) 30 #elif defined(_MSC_VER) && !defined(RYU_ONLY_64_BIT_OPS) && defined(_M_X64) 31 #define HAS_64_BIT_INTRINSICS 34 #if defined(HAS_UINT128) 35 typedef __uint128_t uint128_t;
38 #if defined(HAS_64_BIT_INTRINSICS) 42 static inline uint64_t umul128(
const uint64_t a,
const uint64_t b, uint64_t*
const productHi) {
43 return _umul128(a, b, productHi);
46 static inline uint64_t shiftright128(
const uint64_t lo,
const uint64_t hi,
const uint32_t dist) {
56 return __shiftright128(lo, hi, (
unsigned char) dist);
59 #else // defined(HAS_64_BIT_INTRINSICS) 61 static inline uint64_t umul128(
const uint64_t a,
const uint64_t b, uint64_t*
const productHi) {
63 const uint32_t aLo = (uint32_t)a;
64 const uint32_t aHi = (uint32_t)(a >> 32);
65 const uint32_t bLo = (uint32_t)b;
66 const uint32_t bHi = (uint32_t)(b >> 32);
68 const uint64_t b00 = (uint64_t)aLo * bLo;
69 const uint64_t b01 = (uint64_t)aLo * bHi;
70 const uint64_t b10 = (uint64_t)aHi * bLo;
71 const uint64_t b11 = (uint64_t)aHi * bHi;
73 const uint32_t b00Lo = (uint32_t)b00;
74 const uint32_t b00Hi = (uint32_t)(b00 >> 32);
76 const uint64_t mid1 = b10 + b00Hi;
77 const uint32_t mid1Lo = (uint32_t)(mid1);
78 const uint32_t mid1Hi = (uint32_t)(mid1 >> 32);
80 const uint64_t mid2 = b01 + mid1Lo;
81 const uint32_t mid2Lo = (uint32_t)(mid2);
82 const uint32_t mid2Hi = (uint32_t)(mid2 >> 32);
84 const uint64_t pHi = b11 + mid1Hi + mid2Hi;
85 const uint64_t pLo = ((uint64_t)mid2Lo << 32) | b00Lo;
91 static inline uint64_t shiftright128(
const uint64_t lo,
const uint64_t hi,
const uint32_t dist) {
94 #if defined(RYU_OPTIMIZE_SIZE) || !defined(RYU_32_BIT_PLATFORM) 96 return (hi << (64 - dist)) | (lo >> dist);
100 return (hi << (64 - dist)) | ((uint32_t)(lo >> 32) >> (dist - 32));
104 #endif // defined(HAS_64_BIT_INTRINSICS) 106 #if defined(RYU_32_BIT_PLATFORM) 109 static inline uint64_t umulh(
const uint64_t a,
const uint64_t b) {
133 static inline uint64_t div5(
const uint64_t x) {
134 return umulh(x, 0xCCCCCCCCCCCCCCCDu) >> 2;
137 static inline uint64_t div10(
const uint64_t x) {
138 return umulh(x, 0xCCCCCCCCCCCCCCCDu) >> 3;
141 static inline uint64_t div100(
const uint64_t x) {
142 return umulh(x >> 2, 0x28F5C28F5C28F5C3u) >> 2;
145 static inline uint64_t div1e8(
const uint64_t x) {
146 return umulh(x, 0xABCC77118461CEFDu) >> 26;
149 static inline uint64_t div1e9(
const uint64_t x) {
150 return umulh(x >> 9, 0x44B82FA09B5A53u) >> 11;
153 static inline uint32_t mod1e9(
const uint64_t x) {
163 return ((uint32_t) x) - 1000000000 * ((uint32_t) div1e9(x));
166 #else // defined(RYU_32_BIT_PLATFORM) 168 static inline uint64_t div5(
const uint64_t x) {
172 static inline uint64_t div10(
const uint64_t x) {
176 static inline uint64_t div100(
const uint64_t x) {
180 static inline uint64_t div1e8(
const uint64_t x) {
181 return x / 100000000;
184 static inline uint64_t div1e9(
const uint64_t x) {
185 return x / 1000000000;
188 static inline uint32_t mod1e9(
const uint64_t x) {
189 return (uint32_t) (x - 1000000000 * div1e9(x));
192 #endif // defined(RYU_32_BIT_PLATFORM) 194 static inline uint32_t pow5Factor(uint64_t value) {
198 const uint64_t q = div5(value);
199 const uint32_t r = ((uint32_t) value) - 5 * ((uint32_t) q);
210 static inline bool multipleOfPowerOf5(
const uint64_t value,
const uint32_t p) {
212 return pow5Factor(value) >= p;
216 static inline bool multipleOfPowerOf2(
const uint64_t value,
const uint32_t p) {
219 return (value & ((1ull << p) - 1)) == 0;
222 #endif // RYU_D2S_INTRINSICS_H