emulated128.hpp 43 KB

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