emulated128.hpp 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009
  1. // Copyright 2020-2023 Daniel Lemire
  2. // Copyright 2023 Matt Borland
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // https://www.boost.org/LICENSE_1_0.txt
  5. //
  6. // If the architecture (e.g. Apple ARM) does not have __int128 we need to emulate it
  7. #ifndef BOOST_CHARCONV_DETAIL_EMULATED128_HPP
  8. #define BOOST_CHARCONV_DETAIL_EMULATED128_HPP
  9. #include <boost/charconv/detail/config.hpp>
  10. #include <boost/charconv/config.hpp>
  11. #include <boost/core/bit.hpp>
  12. #include <type_traits>
  13. #include <limits>
  14. #include <cstdint>
  15. #include <cassert>
  16. #include <cmath>
  17. namespace boost { namespace charconv { namespace detail {
  18. // Compilers might support built-in 128-bit integer types. However, it seems that
  19. // emulating them with a pair of 64-bit integers actually produces a better code,
  20. // so we avoid using those built-ins. That said, they are still useful for
  21. // implementing 64-bit x 64-bit -> 128-bit multiplication.
  22. // Memcpy-able temp class for uint128
  23. struct trivial_uint128
  24. {
  25. #if BOOST_CHARCONV_ENDIAN_LITTLE_BYTE
  26. std::uint64_t low;
  27. std::uint64_t high;
  28. #else
  29. std::uint64_t high;
  30. std::uint64_t low;
  31. #endif
  32. };
  33. // Macro replacement lists can not be enclosed in parentheses
  34. struct uint128
  35. {
  36. std::uint64_t high;
  37. std::uint64_t low;
  38. // Constructors
  39. constexpr uint128() noexcept : high {}, low {} {}
  40. constexpr uint128(const uint128& v) noexcept = default;
  41. constexpr uint128(uint128&& v) noexcept = default;
  42. constexpr uint128(std::uint64_t high_, std::uint64_t low_) noexcept : high {high_}, low {low_} {}
  43. constexpr uint128(const trivial_uint128& v) noexcept : high {v.high}, low {v.low} {} // NOLINT
  44. constexpr uint128(trivial_uint128&& v) noexcept : high {v.high}, low {v.low} {} // NOLINT
  45. #define SIGNED_CONSTRUCTOR(expr) constexpr uint128(expr v) noexcept : high {v < 0 ? UINT64_MAX : UINT64_C(0)}, low {static_cast<std::uint64_t>(v)} {} // NOLINT
  46. #define UNSIGNED_CONSTRUCTOR(expr) constexpr uint128(expr v) noexcept : high {}, low {static_cast<std::uint64_t>(v)} {} // NOLINT
  47. SIGNED_CONSTRUCTOR(char) // NOLINT
  48. SIGNED_CONSTRUCTOR(signed char) // NOLINT
  49. SIGNED_CONSTRUCTOR(short) // NOLINT
  50. SIGNED_CONSTRUCTOR(int) // NOLINT
  51. SIGNED_CONSTRUCTOR(long) // NOLINT
  52. SIGNED_CONSTRUCTOR(long long) // NOLINT
  53. UNSIGNED_CONSTRUCTOR(unsigned char) // NOLINT
  54. UNSIGNED_CONSTRUCTOR(unsigned short) // NOLINT
  55. UNSIGNED_CONSTRUCTOR(unsigned) // NOLINT
  56. UNSIGNED_CONSTRUCTOR(unsigned long) // NOLINT
  57. UNSIGNED_CONSTRUCTOR(unsigned long long) // NOLINT
  58. #ifdef BOOST_CHARCONV_HAS_INT128
  59. constexpr uint128(boost::int128_type v) noexcept : // NOLINT : Allow implicit conversions
  60. high {static_cast<std::uint64_t>(v >> 64)},
  61. low {static_cast<std::uint64_t>(static_cast<boost::uint128_type>(v) & ~UINT64_C(0))} {}
  62. constexpr uint128(boost::uint128_type v) noexcept : // NOLINT : Allow implicit conversions
  63. high {static_cast<std::uint64_t>(v >> 64)},
  64. low {static_cast<std::uint64_t>(v & ~UINT64_C(0))} {}
  65. #endif
  66. #undef SIGNED_CONSTRUCTOR
  67. #undef UNSIGNED_CONSTRUCTOR
  68. // Assignment Operators
  69. #define SIGNED_ASSIGNMENT_OPERATOR(expr) BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator=(const expr& v) noexcept { high = v < 0 ? UINT64_MAX : UINT64_C(0); low = static_cast<std::uint64_t>(v); return *this; } // NOLINT
  70. #define UNSIGNED_ASSIGNMENT_OPERATOR(expr) BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator=(const expr& v) noexcept { high = 0U; low = static_cast<std::uint64_t>(v); return *this; } // NOLINT
  71. SIGNED_ASSIGNMENT_OPERATOR(char) // NOLINT
  72. SIGNED_ASSIGNMENT_OPERATOR(signed char) // NOLINT
  73. SIGNED_ASSIGNMENT_OPERATOR(short) // NOLINT
  74. SIGNED_ASSIGNMENT_OPERATOR(int) // NOLINT
  75. SIGNED_ASSIGNMENT_OPERATOR(long) // NOLINT
  76. SIGNED_ASSIGNMENT_OPERATOR(long long) // NOLINT
  77. UNSIGNED_ASSIGNMENT_OPERATOR(unsigned char) // NOLINT
  78. UNSIGNED_ASSIGNMENT_OPERATOR(unsigned short) // NOLINT
  79. UNSIGNED_ASSIGNMENT_OPERATOR(unsigned) // NOLINT
  80. UNSIGNED_ASSIGNMENT_OPERATOR(unsigned long) // NOLINT
  81. UNSIGNED_ASSIGNMENT_OPERATOR(unsigned long long) // NOLINT
  82. #ifdef BOOST_CHARCONV_HAS_INT128
  83. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator=(const boost::int128_type& v) noexcept { *this = uint128(v); return *this; }
  84. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator=(const boost::uint128_type& v) noexcept { *this = uint128(v); return *this; }
  85. #endif
  86. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator=(const trivial_uint128& v) noexcept { this->low = v.low; this->high = v.high; return *this; }
  87. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator=(const uint128&) noexcept;
  88. #undef SIGNED_ASSIGNMENT_OPERATOR
  89. #undef UNSIGNED_ASSIGNMENT_OPERATOR
  90. // Conversion Operators
  91. #define INTEGER_CONVERSION_OPERATOR(expr) explicit constexpr operator expr() const noexcept { return static_cast<expr>(low); } // NOLINT
  92. #define FLOAT_CONVERSION_OPERATOR(expr) explicit operator expr() const noexcept { return std::ldexp(static_cast<expr>(high), 64) + static_cast<expr>(low); } // NOLINT
  93. INTEGER_CONVERSION_OPERATOR(char) // NOLINT
  94. INTEGER_CONVERSION_OPERATOR(signed char) // NOLINT
  95. INTEGER_CONVERSION_OPERATOR(short) // NOLINT
  96. INTEGER_CONVERSION_OPERATOR(int) // NOLINT
  97. INTEGER_CONVERSION_OPERATOR(long) // NOLINT
  98. INTEGER_CONVERSION_OPERATOR(long long) // NOLINT
  99. INTEGER_CONVERSION_OPERATOR(unsigned char) // NOLINT
  100. INTEGER_CONVERSION_OPERATOR(unsigned short) // NOLINT
  101. INTEGER_CONVERSION_OPERATOR(unsigned) // NOLINT
  102. INTEGER_CONVERSION_OPERATOR(unsigned long) // NOLINT
  103. INTEGER_CONVERSION_OPERATOR(unsigned long long) // NOLINT
  104. explicit constexpr operator bool() const noexcept { return high || low; }
  105. #ifdef BOOST_CHARCONV_HAS_INT128
  106. explicit constexpr operator boost::int128_type() const noexcept { return (static_cast<boost::int128_type>(high) << 64) + low; }
  107. explicit constexpr operator boost::uint128_type() const noexcept { return (static_cast<boost::uint128_type>(high) << 64) + low; }
  108. #endif
  109. #ifdef BOOST_CHARCONV_HAS_FLOAT128
  110. explicit operator __float128() const noexcept { return ldexpq(static_cast<__float128>(high), 64) + static_cast<__float128>(low); }
  111. #endif
  112. FLOAT_CONVERSION_OPERATOR(float) // NOLINT
  113. FLOAT_CONVERSION_OPERATOR(double) // NOLINT
  114. FLOAT_CONVERSION_OPERATOR(long double) // NOLINT
  115. #undef INTEGER_CONVERSION_OPERATOR
  116. #undef FLOAT_CONVERSION_OPERATOR
  117. // Unary Operators
  118. constexpr friend uint128 operator-(uint128 val) noexcept;
  119. constexpr friend uint128 operator+(uint128 val) noexcept;
  120. // Comparison Operators
  121. // Equality
  122. #define INTEGER_OPERATOR_EQUAL(expr) constexpr friend bool operator==(uint128 lhs, expr rhs) noexcept { return lhs.high == 0 && rhs >= 0 && lhs.low == static_cast<std::uint64_t>(rhs); } // NOLINT
  123. #define UNSIGNED_INTEGER_OPERATOR_EQUAL(expr) constexpr friend bool operator==(uint128 lhs, expr rhs) noexcept { return lhs.high == 0 && lhs.low == static_cast<std::uint64_t>(rhs); } // NOLINT
  124. INTEGER_OPERATOR_EQUAL(char) // NOLINT
  125. INTEGER_OPERATOR_EQUAL(signed char) // NOLINT
  126. INTEGER_OPERATOR_EQUAL(short) // NOLINT
  127. INTEGER_OPERATOR_EQUAL(int) // NOLINT
  128. INTEGER_OPERATOR_EQUAL(long) // NOLINT
  129. INTEGER_OPERATOR_EQUAL(long long) // NOLINT
  130. UNSIGNED_INTEGER_OPERATOR_EQUAL(unsigned char) // NOLINT
  131. UNSIGNED_INTEGER_OPERATOR_EQUAL(unsigned short) // NOLINT
  132. UNSIGNED_INTEGER_OPERATOR_EQUAL(unsigned) // NOLINT
  133. UNSIGNED_INTEGER_OPERATOR_EQUAL(unsigned long) // NOLINT
  134. UNSIGNED_INTEGER_OPERATOR_EQUAL(unsigned long long) // NOLINT
  135. #ifdef BOOST_CHARCONV_HAS_INT128
  136. constexpr friend bool operator==(uint128 lhs, boost::int128_type rhs) noexcept { return lhs == uint128(rhs); }
  137. constexpr friend bool operator==(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs == uint128(rhs); }
  138. #endif
  139. constexpr friend bool operator==(uint128 lhs, uint128 rhs) noexcept;
  140. #undef INTEGER_OPERATOR_EQUAL
  141. #undef UNSIGNED_INTEGER_OPERATOR_EQUAL
  142. // Inequality
  143. #define INTEGER_OPERATOR_NOTEQUAL(expr) constexpr friend bool operator!=(uint128 lhs, expr rhs) noexcept { return !(lhs == rhs); } // NOLINT
  144. INTEGER_OPERATOR_NOTEQUAL(char) // NOLINT
  145. INTEGER_OPERATOR_NOTEQUAL(signed char) // NOLINT
  146. INTEGER_OPERATOR_NOTEQUAL(short) // NOLINT
  147. INTEGER_OPERATOR_NOTEQUAL(int) // NOLINT
  148. INTEGER_OPERATOR_NOTEQUAL(long) // NOLINT
  149. INTEGER_OPERATOR_NOTEQUAL(long long) // NOLINT
  150. INTEGER_OPERATOR_NOTEQUAL(unsigned char) // NOLINT
  151. INTEGER_OPERATOR_NOTEQUAL(unsigned short) // NOLINT
  152. INTEGER_OPERATOR_NOTEQUAL(unsigned) // NOLINT
  153. INTEGER_OPERATOR_NOTEQUAL(unsigned long) // NOLINT
  154. INTEGER_OPERATOR_NOTEQUAL(unsigned long long) // NOLINT
  155. #ifdef BOOST_CHARCONV_HAS_INT128
  156. constexpr friend bool operator!=(uint128 lhs, boost::int128_type rhs) noexcept { return !(lhs == rhs); }
  157. constexpr friend bool operator!=(uint128 lhs, boost::uint128_type rhs) noexcept { return !(lhs == rhs); }
  158. #endif
  159. constexpr friend bool operator!=(uint128 lhs, uint128 rhs) noexcept;
  160. #undef INTEGER_OPERATOR_NOTEQUAL
  161. // Less than
  162. #define INTEGER_OPERATOR_LESS_THAN(expr) constexpr friend bool operator<(uint128 lhs, expr rhs) noexcept { return lhs.high == 0U && rhs > 0 && lhs.low < static_cast<std::uint64_t>(rhs); } // NOLINT
  163. #define UNSIGNED_INTEGER_OPERATOR_LESS_THAN(expr) constexpr friend bool operator<(uint128 lhs, expr rhs) noexcept { return lhs.high == 0U && lhs.low < static_cast<std::uint64_t>(rhs); } // NOLINT
  164. INTEGER_OPERATOR_LESS_THAN(char) // NOLINT
  165. INTEGER_OPERATOR_LESS_THAN(signed char) // NOLINT
  166. INTEGER_OPERATOR_LESS_THAN(short) // NOLINT
  167. INTEGER_OPERATOR_LESS_THAN(int) // NOLINT
  168. INTEGER_OPERATOR_LESS_THAN(long) // NOLINT
  169. INTEGER_OPERATOR_LESS_THAN(long long) // NOLINT
  170. UNSIGNED_INTEGER_OPERATOR_LESS_THAN(unsigned char) // NOLINT
  171. UNSIGNED_INTEGER_OPERATOR_LESS_THAN(unsigned short) // NOLINT
  172. UNSIGNED_INTEGER_OPERATOR_LESS_THAN(unsigned) // NOLINT
  173. UNSIGNED_INTEGER_OPERATOR_LESS_THAN(unsigned long) // NOLINT
  174. UNSIGNED_INTEGER_OPERATOR_LESS_THAN(unsigned long long) // NOLINT
  175. #ifdef BOOST_CHARCONV_HAS_INT128
  176. BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator<(uint128 lhs, boost::int128_type rhs) noexcept { return lhs < uint128(rhs); }
  177. BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator<(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs < uint128(rhs); }
  178. #endif
  179. BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator<(uint128 lhs, uint128 rhs) noexcept;
  180. #undef INTEGER_OPERATOR_LESS_THAN
  181. #undef UNSIGNED_INTEGER_OPERATOR_LESS_THAN
  182. // Less than or equal to
  183. #define INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(expr) constexpr friend bool operator<=(uint128 lhs, expr rhs) noexcept { return lhs.high == 0U && rhs >= 0 && lhs.low <= static_cast<std::uint64_t>(rhs); } // NOLINT
  184. #define UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(expr) constexpr friend bool operator<=(uint128 lhs, expr rhs) noexcept { return lhs.high == 0U && lhs.low <= static_cast<std::uint64_t>(rhs); } // NOLINT
  185. INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(char) // NOLINT
  186. INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(signed char) // NOLINT
  187. INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(short) // NOLINT
  188. INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(int) // NOLINT
  189. INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(long) // NOLINT
  190. INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(long long) // NOLINT
  191. UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(unsigned char) // NOLINT
  192. UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(unsigned short) // NOLINT
  193. UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(unsigned) // NOLINT
  194. UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(unsigned long) // NOLINT
  195. UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(unsigned long long) // NOLINT
  196. #ifdef BOOST_CHARCONV_HAS_INT128
  197. BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator<=(uint128 lhs, boost::int128_type rhs) noexcept { return lhs <= uint128(rhs); }
  198. BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator<=(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs <= uint128(rhs); }
  199. #endif
  200. BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator<=(uint128 lhs, uint128 rhs) noexcept;
  201. #undef INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO
  202. #undef UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO
  203. // Greater than
  204. #define INTEGER_OPERATOR_GREATER_THAN(expr) constexpr friend bool operator>(uint128 lhs, expr rhs) noexcept { return lhs.high > 0U || rhs < 0 || lhs.low > static_cast<std::uint64_t>(rhs); } // NOLINT
  205. #define UNSIGNED_INTEGER_OPERATOR_GREATER_THAN(expr) constexpr friend bool operator>(uint128 lhs, expr rhs) noexcept { return lhs.high > 0U || lhs.low > static_cast<std::uint64_t>(rhs); } // NOLINT
  206. INTEGER_OPERATOR_GREATER_THAN(char) // NOLINT
  207. INTEGER_OPERATOR_GREATER_THAN(signed char) // NOLINT
  208. INTEGER_OPERATOR_GREATER_THAN(short) // NOLINT
  209. INTEGER_OPERATOR_GREATER_THAN(int) // NOLINT
  210. INTEGER_OPERATOR_GREATER_THAN(long) // NOLINT
  211. INTEGER_OPERATOR_GREATER_THAN(long long) // NOLINT
  212. UNSIGNED_INTEGER_OPERATOR_GREATER_THAN(unsigned char) // NOLINT
  213. UNSIGNED_INTEGER_OPERATOR_GREATER_THAN(unsigned short) // NOLINT
  214. UNSIGNED_INTEGER_OPERATOR_GREATER_THAN(unsigned) // NOLINT
  215. UNSIGNED_INTEGER_OPERATOR_GREATER_THAN(unsigned long) // NOLINT
  216. UNSIGNED_INTEGER_OPERATOR_GREATER_THAN(unsigned long long) // NOLINT
  217. #ifdef BOOST_CHARCONV_HAS_INT128
  218. BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator>(uint128 lhs, boost::int128_type rhs) noexcept { return lhs > uint128(rhs); }
  219. BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator>(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs > uint128(rhs); }
  220. #endif
  221. BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator>(uint128 lhs, uint128 rhs) noexcept;
  222. #undef INTEGER_OPERATOR_GREATER_THAN
  223. #undef UNSIGNED_INTEGER_OPERATOR_GREATER_THAN
  224. // Greater than or equal to
  225. #define INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(expr) constexpr friend bool operator>=(uint128 lhs, expr rhs) noexcept { return lhs.high > 0U || rhs < 0 || lhs.low >= static_cast<std::uint64_t>(rhs); } // NOLINT
  226. #define UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(expr) constexpr friend bool operator>=(uint128 lhs, expr rhs) noexcept { return lhs.high > 0U || lhs.low >= static_cast<std::uint64_t>(rhs); } // NOLINT
  227. INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(char) // NOLINT
  228. INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(signed char) // NOLINT
  229. INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(short) // NOLINT
  230. INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(int) // NOLINT
  231. INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(long) // NOLINT
  232. INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(long long) // NOLINT
  233. UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(unsigned char) // NOLINT
  234. UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(unsigned short) // NOLINT
  235. UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(unsigned) // NOLINT
  236. UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(unsigned long) // NOLINT
  237. UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(unsigned long long) // NOLINT
  238. #ifdef BOOST_CHARCONV_HAS_INT128
  239. BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator>=(uint128 lhs, boost::int128_type rhs) noexcept { return lhs >= uint128(rhs); }
  240. BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator>=(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs >= uint128(rhs); }
  241. #endif
  242. BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator>=(uint128 lhs, uint128 rhs) noexcept;
  243. #undef INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO
  244. #undef UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO
  245. // Binary Operators
  246. // Not
  247. constexpr friend uint128 operator~(uint128 v) noexcept;
  248. // Or
  249. #define INTEGER_BINARY_OPERATOR_OR(expr) constexpr friend uint128 operator|(uint128 lhs, expr rhs) noexcept { return {lhs.high, lhs.low | static_cast<std::uint64_t>(rhs)}; } // NOLINT
  250. INTEGER_BINARY_OPERATOR_OR(char) // NOLINT
  251. INTEGER_BINARY_OPERATOR_OR(signed char) // NOLINT
  252. INTEGER_BINARY_OPERATOR_OR(short) // NOLINT
  253. INTEGER_BINARY_OPERATOR_OR(int) // NOLINT
  254. INTEGER_BINARY_OPERATOR_OR(long) // NOLINT
  255. INTEGER_BINARY_OPERATOR_OR(long long) // NOLINT
  256. INTEGER_BINARY_OPERATOR_OR(unsigned char) // NOLINT
  257. INTEGER_BINARY_OPERATOR_OR(unsigned short) // NOLINT
  258. INTEGER_BINARY_OPERATOR_OR(unsigned) // NOLINT
  259. INTEGER_BINARY_OPERATOR_OR(unsigned long) // NOLINT
  260. INTEGER_BINARY_OPERATOR_OR(unsigned long long) // NOLINT
  261. #ifdef BOOST_CHARCONV_HAS_INT128
  262. constexpr friend uint128 operator|(uint128 lhs, boost::int128_type rhs) noexcept { return lhs | uint128(rhs); }
  263. constexpr friend uint128 operator|(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs | uint128(rhs); }
  264. #endif
  265. constexpr friend uint128 operator|(uint128 lhs, uint128 rhs) noexcept;
  266. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator|=(uint128 v) noexcept;
  267. #undef INTEGER_BINARY_OPERATOR_OR
  268. // And
  269. #define INTEGER_BINARY_OPERATOR_AND(expr) constexpr friend uint128 operator&(uint128 lhs, expr rhs) noexcept { return {lhs.high, lhs.low & static_cast<std::uint64_t>(rhs)}; } // NOLINT
  270. INTEGER_BINARY_OPERATOR_AND(char) // NOLINT
  271. INTEGER_BINARY_OPERATOR_AND(signed char) // NOLINT
  272. INTEGER_BINARY_OPERATOR_AND(short) // NOLINT
  273. INTEGER_BINARY_OPERATOR_AND(int) // NOLINT
  274. INTEGER_BINARY_OPERATOR_AND(long) // NOLINT
  275. INTEGER_BINARY_OPERATOR_AND(long long) // NOLINT
  276. INTEGER_BINARY_OPERATOR_AND(unsigned char) // NOLINT
  277. INTEGER_BINARY_OPERATOR_AND(unsigned short) // NOLINT
  278. INTEGER_BINARY_OPERATOR_AND(unsigned) // NOLINT
  279. INTEGER_BINARY_OPERATOR_AND(unsigned long) // NOLINT
  280. INTEGER_BINARY_OPERATOR_AND(unsigned long long) // NOLINT
  281. #ifdef BOOST_CHARCONV_HAS_INT128
  282. constexpr friend uint128 operator&(uint128 lhs, boost::int128_type rhs) noexcept { return lhs & uint128(rhs); }
  283. constexpr friend uint128 operator&(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs & uint128(rhs); }
  284. #endif
  285. constexpr friend uint128 operator&(uint128 lhs, uint128 rhs) noexcept;
  286. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator&=(uint128 v) noexcept;
  287. #undef INTEGER_BINARY_OPERATOR_AND
  288. // Xor
  289. #define INTEGER_BINARY_OPERATOR_XOR(expr) constexpr friend uint128 operator^(uint128 lhs, expr rhs) noexcept { return {lhs.high, lhs.low ^ static_cast<std::uint64_t>(rhs)}; } // NOLINT
  290. INTEGER_BINARY_OPERATOR_XOR(char) // NOLINT
  291. INTEGER_BINARY_OPERATOR_XOR(signed char) // NOLINT
  292. INTEGER_BINARY_OPERATOR_XOR(short) // NOLINT
  293. INTEGER_BINARY_OPERATOR_XOR(int) // NOLINT
  294. INTEGER_BINARY_OPERATOR_XOR(long) // NOLINT
  295. INTEGER_BINARY_OPERATOR_XOR(long long) // NOLINT
  296. INTEGER_BINARY_OPERATOR_XOR(unsigned char) // NOLINT
  297. INTEGER_BINARY_OPERATOR_XOR(unsigned short) // NOLINT
  298. INTEGER_BINARY_OPERATOR_XOR(unsigned) // NOLINT
  299. INTEGER_BINARY_OPERATOR_XOR(unsigned long) // NOLINT
  300. INTEGER_BINARY_OPERATOR_XOR(unsigned long long) // NOLINT
  301. #ifdef BOOST_CHARCONV_HAS_INT128
  302. constexpr friend uint128 operator^(uint128 lhs, boost::int128_type rhs) noexcept { return lhs ^ uint128(rhs); }
  303. constexpr friend uint128 operator^(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs ^ uint128(rhs); }
  304. #endif
  305. constexpr friend uint128 operator^(uint128 lhs, uint128 rhs) noexcept;
  306. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator^=(uint128 v) noexcept;
  307. #undef INTEGER_BINARY_OPERATOR_XOR
  308. // Left shift
  309. #define INTEGER_BINARY_OPERATOR_LEFT_SHIFT(expr) \
  310. BOOST_CHARCONV_CXX14_CONSTEXPR friend uint128 operator<<(uint128 lhs, expr rhs) noexcept \
  311. { \
  312. if (rhs >= 64) \
  313. { \
  314. return {lhs.low << (rhs - 64), 0}; \
  315. } \
  316. else if (rhs == 0) \
  317. { \
  318. return lhs; \
  319. } \
  320. \
  321. return {(lhs.high << rhs) | (lhs.low >> (64 - rhs)), lhs.low << rhs}; \
  322. } // NOLINT
  323. INTEGER_BINARY_OPERATOR_LEFT_SHIFT(char) // NOLINT
  324. INTEGER_BINARY_OPERATOR_LEFT_SHIFT(signed char) // NOLINT
  325. INTEGER_BINARY_OPERATOR_LEFT_SHIFT(short) // NOLINT
  326. INTEGER_BINARY_OPERATOR_LEFT_SHIFT(int) // NOLINT
  327. INTEGER_BINARY_OPERATOR_LEFT_SHIFT(long) // NOLINT
  328. INTEGER_BINARY_OPERATOR_LEFT_SHIFT(long long) // NOLINT
  329. INTEGER_BINARY_OPERATOR_LEFT_SHIFT(unsigned char) // NOLINT
  330. INTEGER_BINARY_OPERATOR_LEFT_SHIFT(unsigned short) // NOLINT
  331. INTEGER_BINARY_OPERATOR_LEFT_SHIFT(unsigned) // NOLINT
  332. INTEGER_BINARY_OPERATOR_LEFT_SHIFT(unsigned long) // NOLINT
  333. INTEGER_BINARY_OPERATOR_LEFT_SHIFT(unsigned long long) // NOLINT
  334. #define INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(expr) \
  335. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator<<=(expr amount) noexcept \
  336. { \
  337. *this = *this << amount; \
  338. return *this; \
  339. } // NOLINT
  340. INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(char) // NOLINT
  341. INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(signed char) // NOLINT
  342. INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(short) // NOLINT
  343. INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(int) // NOLINT
  344. INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(long) // NOLINT
  345. INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(long long) // NOLINT
  346. INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(unsigned char) // NOLINT
  347. INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(unsigned short) // NOLINT
  348. INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(unsigned) // NOLINT
  349. INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(unsigned long) // NOLINT
  350. INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(unsigned long long) // NOLINT
  351. #undef INTEGER_BINARY_OPERATOR_LEFT_SHIFT
  352. #undef INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT
  353. // Right Shift
  354. #define INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(expr) \
  355. BOOST_CHARCONV_CXX14_CONSTEXPR friend uint128 operator>>(uint128 lhs, expr amount) noexcept \
  356. { \
  357. if (amount >= 64) \
  358. { \
  359. return {0, lhs.high >> (amount - 64)}; \
  360. } \
  361. else if (amount == 0) \
  362. { \
  363. return lhs; \
  364. } \
  365. \
  366. return {lhs.high >> amount, (lhs.low >> amount) | (lhs.high << (64 - amount))}; \
  367. } // NOLINT
  368. INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(char) // NOLINT
  369. INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(signed char) // NOLINT
  370. INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(short) // NOLINT
  371. INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(int) // NOLINT
  372. INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(long) // NOLINT
  373. INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(long long) // NOLINT
  374. INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(unsigned char) // NOLINT
  375. INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(unsigned short) // NOLINT
  376. INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(unsigned) // NOLINT
  377. INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(unsigned long) // NOLINT
  378. INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(unsigned long long) // NOLINT
  379. #define INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(expr) \
  380. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator>>=(expr amount) noexcept \
  381. { \
  382. *this = *this >> amount; \
  383. return *this; \
  384. } // NOLINT
  385. INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(char) // NOLINT
  386. INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(signed char) // NOLINT
  387. INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(short) // NOLINT
  388. INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(int) // NOLINT
  389. INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(long) // NOLINT
  390. INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(long long) // NOLINT
  391. INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(unsigned char) // NOLINT
  392. INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(unsigned short) // NOLINT
  393. INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(unsigned) // NOLINT
  394. INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(unsigned long) // NOLINT
  395. INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(unsigned long long) // NOLINT
  396. #undef INTEGER_BINARY_OPERATOR_RIGHT_SHIFT
  397. #undef INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT
  398. // Arithmetic operators (Add, sub, mul, div, mod)
  399. inline uint128 &operator+=(std::uint64_t n) noexcept;
  400. BOOST_CHARCONV_CXX14_CONSTEXPR friend uint128 operator+(uint128 lhs, uint128 rhs) noexcept;
  401. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator+=(uint128 v) noexcept;
  402. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator++() noexcept;
  403. BOOST_CHARCONV_CXX14_CONSTEXPR const uint128 operator++(int) noexcept;
  404. BOOST_CHARCONV_CXX14_CONSTEXPR friend uint128 operator-(uint128 lhs, uint128 rhs) noexcept;
  405. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator-=(uint128 v) noexcept;
  406. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator--() noexcept;
  407. BOOST_CHARCONV_CXX14_CONSTEXPR const uint128 operator--(int) noexcept;
  408. BOOST_CHARCONV_CXX14_CONSTEXPR friend uint128 operator*(uint128 lhs, uint128 rhs) noexcept;
  409. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator*=(uint128 v) noexcept;
  410. BOOST_CHARCONV_CXX14_CONSTEXPR friend uint128 operator/(uint128 lhs, uint128 rhs) noexcept;
  411. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator/=(uint128 v) noexcept;
  412. BOOST_CHARCONV_CXX14_CONSTEXPR friend uint128 operator%(uint128 lhs, uint128 rhs) noexcept;
  413. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator%=(uint128 v) noexcept;
  414. private:
  415. BOOST_CHARCONV_CXX14_CONSTEXPR friend int high_bit(uint128 v) noexcept;
  416. BOOST_CHARCONV_CXX14_CONSTEXPR friend void
  417. div_impl(uint128 lhs, uint128 rhs, uint128 &quotient, uint128 &remainder) noexcept;
  418. };
  419. constexpr uint128 operator-(uint128 val) noexcept
  420. {
  421. return {~val.high + static_cast<std::uint64_t>(val.low == 0), ~val.low + 1};
  422. }
  423. constexpr uint128 operator+(uint128 val) noexcept
  424. {
  425. return val;
  426. }
  427. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator=(const uint128& v) noexcept // NOLINT : User defined for older compilers
  428. {
  429. low = v.low;
  430. high = v.high;
  431. return *this;
  432. }
  433. constexpr bool operator==(uint128 lhs, uint128 rhs) noexcept
  434. {
  435. return lhs.high == rhs.high && lhs.low == rhs.low;
  436. }
  437. constexpr bool operator!=(uint128 lhs, uint128 rhs) noexcept
  438. {
  439. return !(lhs == rhs);
  440. }
  441. BOOST_CHARCONV_CXX14_CONSTEXPR bool operator<(uint128 lhs, uint128 rhs) noexcept
  442. {
  443. if (lhs.high == rhs.high)
  444. {
  445. return lhs.low < rhs.low;
  446. }
  447. return lhs.high < rhs.high;
  448. }
  449. BOOST_CHARCONV_CXX14_CONSTEXPR bool operator<=(uint128 lhs, uint128 rhs) noexcept
  450. {
  451. return !(rhs < lhs);
  452. }
  453. BOOST_CHARCONV_CXX14_CONSTEXPR bool operator>(uint128 lhs, uint128 rhs) noexcept
  454. {
  455. return rhs < lhs;
  456. }
  457. BOOST_CHARCONV_CXX14_CONSTEXPR bool operator>=(uint128 lhs, uint128 rhs) noexcept
  458. {
  459. return !(lhs < rhs);
  460. }
  461. constexpr uint128 operator~(uint128 v) noexcept
  462. {
  463. return {~v.high, ~v.low};
  464. }
  465. constexpr uint128 operator|(uint128 lhs, uint128 rhs) noexcept
  466. {
  467. return {lhs.high | rhs.high, lhs.low | rhs.low};
  468. }
  469. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator|=(uint128 v) noexcept
  470. {
  471. *this = *this | v;
  472. return *this;
  473. }
  474. constexpr uint128 operator&(uint128 lhs, uint128 rhs) noexcept
  475. {
  476. return {lhs.high & rhs.high, lhs.low & rhs.low};
  477. }
  478. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator&=(uint128 v) noexcept
  479. {
  480. *this = *this & v;
  481. return *this;
  482. }
  483. constexpr uint128 operator^(uint128 lhs, uint128 rhs) noexcept
  484. {
  485. return {lhs.high ^ rhs.high, lhs.low ^ rhs.low};
  486. }
  487. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator^=(uint128 v) noexcept
  488. {
  489. *this = *this ^ v;
  490. return *this;
  491. }
  492. inline uint128 &uint128::operator+=(std::uint64_t n) noexcept
  493. {
  494. #if BOOST_CHARCONV_HAS_BUILTIN(__builtin_addcll)
  495. unsigned long long carry {};
  496. low = __builtin_addcll(low, n, 0, &carry);
  497. high = __builtin_addcll(high, 0, carry, &carry);
  498. #elif BOOST_CHARCONV_HAS_BUILTIN(__builtin_ia32_addcarryx_u64)
  499. unsigned long long result {};
  500. auto carry = __builtin_ia32_addcarryx_u64(0, low, n, &result);
  501. low = result;
  502. __builtin_ia32_addcarryx_u64(carry, high, 0, &result);
  503. high = result;
  504. #elif defined(BOOST_MSVC) && defined(_M_X64)
  505. auto carry = _addcarry_u64(0, low, n, &low);
  506. _addcarry_u64(carry, high, 0, &high);
  507. #else
  508. auto sum = low + n;
  509. high += (sum < low ? 1 : 0);
  510. low = sum;
  511. #endif
  512. return *this;
  513. }
  514. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 operator+(uint128 lhs, uint128 rhs) noexcept
  515. {
  516. const uint128 temp = {lhs.high + rhs.high, lhs.low + rhs.low};
  517. // Need to carry a bit into rhs
  518. if (temp.low < lhs.low)
  519. {
  520. return {temp.high + 1, temp.low};
  521. }
  522. return temp;
  523. }
  524. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator+=(uint128 v) noexcept
  525. {
  526. *this = *this + v;
  527. return *this;
  528. }
  529. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator++() noexcept
  530. {
  531. if (this->low == UINT64_MAX)
  532. {
  533. this->low = 0;
  534. ++this->high;
  535. }
  536. else
  537. {
  538. ++this->low;
  539. }
  540. return *this;
  541. }
  542. BOOST_CHARCONV_CXX14_CONSTEXPR const uint128 uint128::operator++(int) noexcept
  543. {
  544. return ++(*this);
  545. }
  546. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 operator-(uint128 lhs, uint128 rhs) noexcept
  547. {
  548. const uint128 temp {lhs.high - rhs.high, lhs.low - rhs.low};
  549. // Check for carry
  550. if (lhs.low < rhs.low)
  551. {
  552. return {temp.high - 1, temp.low};
  553. }
  554. return temp;
  555. }
  556. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator-=(uint128 v) noexcept
  557. {
  558. *this = *this - v;
  559. return *this;
  560. }
  561. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator--() noexcept
  562. {
  563. if (this->low == 0)
  564. {
  565. this->low = UINT64_MAX;
  566. --this->high;
  567. }
  568. else // NOLINT
  569. {
  570. --this->low;
  571. }
  572. return *this;
  573. }
  574. BOOST_CHARCONV_CXX14_CONSTEXPR const uint128 uint128::operator--(int) noexcept
  575. {
  576. return --(*this);
  577. }
  578. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 operator*(uint128 lhs, uint128 rhs) noexcept
  579. {
  580. const auto a = static_cast<std::uint64_t>(lhs.low >> 32);
  581. const auto b = static_cast<std::uint64_t>(lhs.low & UINT32_MAX);
  582. const auto c = static_cast<std::uint64_t>(rhs.low >> 32);
  583. const auto d = static_cast<std::uint64_t>(rhs.low & UINT32_MAX);
  584. uint128 result { lhs.high * rhs.low + lhs.low * rhs.high + a * c, b * d };
  585. result += uint128(a * d) << 32;
  586. result += uint128(b * c) << 32;
  587. return result;
  588. }
  589. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator*=(uint128 v) noexcept
  590. {
  591. *this = *this * v;
  592. return *this;
  593. }
  594. BOOST_CHARCONV_CXX14_CONSTEXPR int high_bit(uint128 v) noexcept
  595. {
  596. if (v.high != 0)
  597. {
  598. return 127 - boost::core::countl_zero(v.high);
  599. }
  600. else if (v.low != 0)
  601. {
  602. return 63 - boost::core::countl_zero(v.low);
  603. }
  604. return 0;
  605. }
  606. // See: https://stackoverflow.com/questions/5386377/division-without-using
  607. BOOST_CHARCONV_CXX14_CONSTEXPR void div_impl(uint128 lhs, uint128 rhs, uint128& quotient, uint128& remainder) noexcept
  608. {
  609. constexpr uint128 one {0, 1};
  610. if (rhs > lhs)
  611. {
  612. quotient = 0U;
  613. remainder = 0U;
  614. }
  615. else if (lhs == rhs)
  616. {
  617. quotient = 1U;
  618. remainder = 0U;
  619. }
  620. uint128 denom = rhs;
  621. quotient = 0U;
  622. std::int32_t shift = high_bit(lhs) - high_bit(rhs);
  623. if (shift < 0)
  624. {
  625. shift = 32 - shift;
  626. }
  627. denom <<= shift;
  628. for (int i = 0; i <= shift; ++i)
  629. {
  630. quotient <<= 1;
  631. if (lhs >= denom)
  632. {
  633. lhs -= denom;
  634. quotient |= one;
  635. }
  636. denom >>= 1;
  637. }
  638. remainder = lhs;
  639. }
  640. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 operator/(uint128 lhs, uint128 rhs) noexcept
  641. {
  642. uint128 quotient {0, 0};
  643. uint128 remainder {0, 0};
  644. div_impl(lhs, rhs, quotient, remainder);
  645. return quotient;
  646. }
  647. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator/=(uint128 v) noexcept
  648. {
  649. *this = *this / v;
  650. return *this;
  651. }
  652. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 operator%(uint128 lhs, uint128 rhs) noexcept
  653. {
  654. uint128 quotient {0, 0};
  655. uint128 remainder {0, 0};
  656. div_impl(lhs, rhs, quotient, remainder);
  657. return remainder;
  658. }
  659. BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator%=(uint128 v) noexcept
  660. {
  661. *this = *this % v;
  662. return *this;
  663. }
  664. static inline std::uint64_t umul64(std::uint32_t x, std::uint32_t y) noexcept
  665. {
  666. // __emulu is not available on ARM https://learn.microsoft.com/en-us/cpp/intrinsics/emul-emulu?view=msvc-170
  667. #if defined(BOOST_CHARCONV_HAS_MSVC_32BIT_INTRINSICS) && !defined(_M_ARM)
  668. return __emulu(x, y);
  669. #else
  670. return x * static_cast<std::uint64_t>(y);
  671. #endif
  672. }
  673. // Get 128-bit result of multiplication of two 64-bit unsigned integers.
  674. BOOST_CHARCONV_SAFEBUFFERS inline uint128 umul128(std::uint64_t x, std::uint64_t y) noexcept
  675. {
  676. #if defined(BOOST_CHARCONV_HAS_INT128)
  677. auto result = static_cast<boost::uint128_type>(x) * static_cast<boost::uint128_type>(y);
  678. return {static_cast<std::uint64_t>(result >> 64), static_cast<std::uint64_t>(result)};
  679. // _umul128 is x64 only https://learn.microsoft.com/en-us/cpp/intrinsics/umul128?view=msvc-170
  680. #elif defined(BOOST_CHARCONV_HAS_MSVC_64BIT_INTRINSICS) && !defined(_M_ARM64)
  681. unsigned long long high;
  682. std::uint64_t low = _umul128(x, y, &high);
  683. return {static_cast<std::uint64_t>(high), low};
  684. // https://developer.arm.com/documentation/dui0802/a/A64-General-Instructions/UMULH
  685. #elif defined(_M_ARM64) && !defined(__MINGW32__)
  686. std::uint64_t high = __umulh(x, y);
  687. std::uint64_t low = x * y;
  688. return {high, low};
  689. #else
  690. auto a = static_cast<std::uint32_t>(x >> 32);
  691. auto b = static_cast<std::uint32_t>(x);
  692. auto c = static_cast<std::uint32_t>(y >> 32);
  693. auto d = static_cast<std::uint32_t>(y);
  694. auto ac = umul64(a, c);
  695. auto bc = umul64(b, c);
  696. auto ad = umul64(a, d);
  697. auto bd = umul64(b, d);
  698. auto intermediate = (bd >> 32) + static_cast<std::uint32_t>(ad) + static_cast<std::uint32_t>(bc);
  699. return {ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32),
  700. (intermediate << 32) + static_cast<std::uint32_t>(bd)};
  701. #endif
  702. }
  703. BOOST_CHARCONV_SAFEBUFFERS inline std::uint64_t umul128_upper64(std::uint64_t x, std::uint64_t y) noexcept
  704. {
  705. #if defined(BOOST_CHARCONV_HAS_INT128)
  706. auto result = static_cast<boost::uint128_type>(x) * static_cast<boost::uint128_type>(y);
  707. return static_cast<std::uint64_t>(result >> 64);
  708. #elif defined(BOOST_CHARCONV_HAS_MSVC_64BIT_INTRINSICS)
  709. return __umulh(x, y);
  710. #else
  711. auto a = static_cast<std::uint32_t>(x >> 32);
  712. auto b = static_cast<std::uint32_t>(x);
  713. auto c = static_cast<std::uint32_t>(y >> 32);
  714. auto d = static_cast<std::uint32_t>(y);
  715. auto ac = umul64(a, c);
  716. auto bc = umul64(b, c);
  717. auto ad = umul64(a, d);
  718. auto bd = umul64(b, d);
  719. auto intermediate = (bd >> 32) + static_cast<std::uint32_t>(ad) + static_cast<std::uint32_t>(bc);
  720. return ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32);
  721. #endif
  722. }
  723. // Get upper 128-bits of multiplication of a 64-bit unsigned integer and a 128-bit
  724. // unsigned integer.
  725. BOOST_CHARCONV_SAFEBUFFERS inline uint128 umul192_upper128(std::uint64_t x, uint128 y) noexcept
  726. {
  727. auto r = umul128(x, y.high);
  728. r += umul128_upper64(x, y.low);
  729. return r;
  730. }
  731. // Get upper 64-bits of multiplication of a 32-bit unsigned integer and a 64-bit
  732. // unsigned integer.
  733. inline std::uint64_t umul96_upper64(std::uint32_t x, std::uint64_t y) noexcept
  734. {
  735. #if defined(BOOST_CHARCONV_HAS_INT128) || defined(BOOST_CHARCONV_HAS_MSVC_64BIT_INTRINSICS)
  736. return umul128_upper64(static_cast<std::uint64_t>(x) << 32, y);
  737. #else
  738. auto yh = static_cast<std::uint32_t>(y >> 32);
  739. auto yl = static_cast<std::uint32_t>(y);
  740. auto xyh = umul64(x, yh);
  741. auto xyl = umul64(x, yl);
  742. return xyh + (xyl >> 32);
  743. #endif
  744. }
  745. // Get lower 128-bits of multiplication of a 64-bit unsigned integer and a 128-bit
  746. // unsigned integer.
  747. BOOST_CHARCONV_SAFEBUFFERS inline uint128 umul192_lower128(std::uint64_t x, uint128 y) noexcept
  748. {
  749. auto high = x * y.high;
  750. auto highlow = umul128(x, y.low);
  751. return {high + highlow.high, highlow.low};
  752. }
  753. // Get lower 64-bits of multiplication of a 32-bit unsigned integer and a 64-bit
  754. // unsigned integer.
  755. inline std::uint64_t umul96_lower64(std::uint32_t x, std::uint64_t y) noexcept
  756. {
  757. return x * y;
  758. }
  759. }}} // Namespaces
  760. // Non-standard libraries may add specializations for library-provided types
  761. namespace std {
  762. template <>
  763. struct numeric_limits<boost::charconv::detail::uint128>
  764. {
  765. // Member constants
  766. BOOST_ATTRIBUTE_UNUSED static constexpr bool is_specialized = true;
  767. BOOST_ATTRIBUTE_UNUSED static constexpr bool is_signed = false;
  768. BOOST_ATTRIBUTE_UNUSED static constexpr bool is_integer = true;
  769. BOOST_ATTRIBUTE_UNUSED static constexpr bool is_exact = true;
  770. BOOST_ATTRIBUTE_UNUSED static constexpr bool has_infinity = false;
  771. BOOST_ATTRIBUTE_UNUSED static constexpr bool has_quiet_NaN = false;
  772. BOOST_ATTRIBUTE_UNUSED static constexpr bool has_signaling_NaN = false;
  773. BOOST_ATTRIBUTE_UNUSED static constexpr std::float_round_style round_style = std::round_toward_zero;
  774. BOOST_ATTRIBUTE_UNUSED static constexpr bool is_iec559 = false;
  775. BOOST_ATTRIBUTE_UNUSED static constexpr bool is_bounded = true;
  776. BOOST_ATTRIBUTE_UNUSED static constexpr bool is_modulo = true;
  777. BOOST_ATTRIBUTE_UNUSED static constexpr int digits = 128;
  778. BOOST_ATTRIBUTE_UNUSED static constexpr int digits10 = 38;
  779. BOOST_ATTRIBUTE_UNUSED static constexpr int max_digits10 = 0;
  780. BOOST_ATTRIBUTE_UNUSED static constexpr int radix = 2;
  781. BOOST_ATTRIBUTE_UNUSED static constexpr int min_exponent = 0;
  782. BOOST_ATTRIBUTE_UNUSED static constexpr int min_exponent10 = 0;
  783. BOOST_ATTRIBUTE_UNUSED static constexpr int max_exponent = 0;
  784. BOOST_ATTRIBUTE_UNUSED static constexpr int max_exponent10 = 0;
  785. BOOST_ATTRIBUTE_UNUSED static constexpr bool traps = std::numeric_limits<std::uint64_t>::traps;
  786. BOOST_ATTRIBUTE_UNUSED static constexpr bool tinyness_before = false;
  787. // Member functions
  788. BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 (min)() { return 0; }
  789. BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 lowest() { return 0; }
  790. BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 (max)() { return {UINT64_MAX, UINT64_MAX}; }
  791. BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 epsilon() { return 0; }
  792. BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 round_error() { return 0; }
  793. BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 infinity() { return 0; }
  794. BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 quiet_NaN() { return 0; }
  795. BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 signaling_NaN() { return 0; }
  796. BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 denorm_min() { return 0; }
  797. };
  798. } // Namespace std
  799. #endif // BOOST_CHARCONV_DETAIL_EMULATED128_HPP