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)
35typedef __uint128_t uint128_t;
38#if defined(HAS_64_BIT_INTRINSICS)
42static inline uint64_t umul128(
const uint64_t a,
const uint64_t b, uint64_t*
const productHi) {
43 return _umul128(a, b, productHi);
46static inline uint64_t shiftright128(
const uint64_t lo,
const uint64_t hi,
const uint32_t dist) {
56 return __shiftright128(lo, hi, (
unsigned char) dist);
61static 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;
91static 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));
106#if defined(RYU_32_BIT_PLATFORM)
109static inline uint64_t umulh(
const uint64_t a,
const uint64_t b) {
133static inline uint64_t div5(
const uint64_t x) {
134 return umulh(x, 0xCCCCCCCCCCCCCCCDu) >> 2;
137static inline uint64_t div10(
const uint64_t x) {
138 return umulh(x, 0xCCCCCCCCCCCCCCCDu) >> 3;
141static inline uint64_t div100(
const uint64_t x) {
142 return umulh(x >> 2, 0x28F5C28F5C28F5C3u) >> 2;
145static inline uint64_t div1e8(
const uint64_t x) {
146 return umulh(x, 0xABCC77118461CEFDu) >> 26;
149static inline uint64_t div1e9(
const uint64_t x) {
150 return umulh(x >> 9, 0x44B82FA09B5A53u) >> 11;
153static inline uint32_t mod1e9(
const uint64_t x) {
163 return ((uint32_t) x) - 1000000000 * ((uint32_t) div1e9(x));
168static inline uint64_t div5(
const uint64_t x) {
172static inline uint64_t div10(
const uint64_t x) {
176static inline uint64_t div100(
const uint64_t x) {
180static inline uint64_t div1e8(
const uint64_t x) {
181 return x / 100000000;
184static inline uint64_t div1e9(
const uint64_t x) {
185 return x / 1000000000;
188static inline uint32_t mod1e9(
const uint64_t x) {
189 return (uint32_t) (x - 1000000000 * div1e9(x));
194static 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);
210static inline bool multipleOfPowerOf5(
const uint64_t value,
const uint32_t p) {
212 return pow5Factor(value) >= p;
216static inline bool multipleOfPowerOf2(
const uint64_t value,
const uint32_t p) {
219 return (value & ((1ull << p) - 1)) == 0;