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 +

 
8 +
#ifndef BOOST_JSON_DETAIL_DRAGONBOX_EMULATED128_HPP
 
9 +
#define BOOST_JSON_DETAIL_DRAGONBOX_EMULATED128_HPP
 
10 +

 
11 +
#include <boost/json/detail/config.hpp>
 
12 +
#include <boost/json/detail/charconv/detail/config.hpp>
 
13 +
#include <boost/endian/conversion.hpp>
 
14 +
#include <boost/core/bit.hpp>
 
15 +
#include <limits>
 
16 +
#include <cstdint>
 
17 +
#include <cassert>
 
18 +
#include <cmath>
 
19 +

 
20 +
namespace boost {
 
21 +
namespace json {
 
22 +
namespace detail {
 
23 +

 
24 +
// Compilers might support built-in 128-bit integer types. However, it seems that
 
25 +
// emulating them with a pair of 64-bit integers actually produces a better code,
 
26 +
// so we avoid using those built-ins. That said, they are still useful for
 
27 +
// implementing 64-bit x 64-bit -> 128-bit multiplication.
 
28 +

 
29 +
// Memcpy-able temp class for uint128
 
30 +
template <boost::endian::order Order = boost::endian::order::little>
 
31 +
struct trivial_uint128_impl
 
32 +
{
 
33 +
    std::uint64_t low;
 
34 +
    std::uint64_t high;
 
35 +
};
 
36 +

 
37 +
template <>
 
38 +
struct trivial_uint128_impl<boost::endian::order::big>
 
39 +
{
 
40 +
    std::uint64_t high;
 
41 +
    std::uint64_t low;
 
42 +
};
 
43 +

 
44 +
using trivial_uint128 = trivial_uint128_impl<boost::endian::order::native>;
 
45 +

 
46 +
// Macro replacement lists can not be enclosed in parentheses
 
47 +
struct uint128
 
48 +
{
 
49 +
    std::uint64_t high;
 
50 +
    std::uint64_t low;
 
51 +

 
52 +
    // Constructors
 
53 +
    constexpr uint128() noexcept : high {}, low {} {}
 
54 +

 
55 +
    constexpr uint128(const uint128& v) noexcept = default;
 
56 +

 
57 +
    constexpr uint128(uint128&& v) noexcept = default;
 
58 +

 
59 +
    constexpr uint128(std::uint64_t high_, std::uint64_t low_) noexcept : high {high_}, low {low_} {}
 
60 +

 
61 +
    constexpr uint128(const trivial_uint128& v) noexcept : high {v.high}, low {v.low} {} // NOLINT
 
62 +

 
63 +
    constexpr uint128(trivial_uint128&& v) noexcept : high {v.high}, low {v.low} {} // NOLINT
 
64 +

 
65 +
    #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
 
66 +
    #define UNSIGNED_CONSTRUCTOR(expr) constexpr uint128(expr v) noexcept : high {}, low {static_cast<std::uint64_t>(v)} {} // NOLINT
 
67 +

 
68 +
    SIGNED_CONSTRUCTOR(char)                    // NOLINT
 
69 +
    SIGNED_CONSTRUCTOR(signed char)             // NOLINT
 
70 +
    SIGNED_CONSTRUCTOR(short)                   // NOLINT
 
71 +
    SIGNED_CONSTRUCTOR(int)                     // NOLINT
 
72 +
    SIGNED_CONSTRUCTOR(long)                    // NOLINT
 
73 +
    SIGNED_CONSTRUCTOR(long long)               // NOLINT
 
74 +

 
75 +
    UNSIGNED_CONSTRUCTOR(unsigned char)         // NOLINT
 
76 +
    UNSIGNED_CONSTRUCTOR(unsigned short)        // NOLINT
 
77 +
    UNSIGNED_CONSTRUCTOR(unsigned)              // NOLINT
 
78 +
    UNSIGNED_CONSTRUCTOR(unsigned long)         // NOLINT
 
79 +
    UNSIGNED_CONSTRUCTOR(unsigned long long)    // NOLINT
 
80 +

 
81 +
    #ifdef BOOST_HAS_INT128
 
82 +
    constexpr uint128(boost::int128_type v) noexcept :  // NOLINT : Allow implicit conversions
 
83 +
        high {static_cast<std::uint64_t>(v >> 64)},
 
84 +
         low {static_cast<std::uint64_t>(static_cast<boost::uint128_type>(v) & ~UINT64_C(0))} {}
 
85 +

 
86 +
    constexpr uint128(boost::uint128_type v) noexcept : // NOLINT : Allow implicit conversions
 
87 +
        high {static_cast<std::uint64_t>(v >> 64)},
 
88 +
         low {static_cast<std::uint64_t>(v & ~UINT64_C(0))} {}
 
89 +
    #endif
 
90 +

 
91 +
    #undef SIGNED_CONSTRUCTOR
 
92 +
    #undef UNSIGNED_CONSTRUCTOR
 
93 +

 
94 +
    // Assignment Operators
 
95 +
    #define SIGNED_ASSIGNMENT_OPERATOR(expr) BOOST_JSON_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
 
96 +
    #define UNSIGNED_ASSIGNMENT_OPERATOR(expr) BOOST_JSON_CXX14_CONSTEXPR uint128 &operator=(const expr& v) noexcept { high = 0U; low = static_cast<std::uint64_t>(v); return *this; } // NOLINT
 
97 +

 
98 +
    SIGNED_ASSIGNMENT_OPERATOR(char)                    // NOLINT
 
99 +
    SIGNED_ASSIGNMENT_OPERATOR(signed char)             // NOLINT
 
100 +
    SIGNED_ASSIGNMENT_OPERATOR(short)                   // NOLINT
 
101 +
    SIGNED_ASSIGNMENT_OPERATOR(int)                     // NOLINT
 
102 +
    SIGNED_ASSIGNMENT_OPERATOR(long)                    // NOLINT
 
103 +
    SIGNED_ASSIGNMENT_OPERATOR(long long)               // NOLINT
 
104 +

 
105 +
    UNSIGNED_ASSIGNMENT_OPERATOR(unsigned char)         // NOLINT
 
106 +
    UNSIGNED_ASSIGNMENT_OPERATOR(unsigned short)        // NOLINT
 
107 +
    UNSIGNED_ASSIGNMENT_OPERATOR(unsigned)              // NOLINT
 
108 +
    UNSIGNED_ASSIGNMENT_OPERATOR(unsigned long)         // NOLINT
 
109 +
    UNSIGNED_ASSIGNMENT_OPERATOR(unsigned long long)    // NOLINT
 
110 +

 
111 +
    #ifdef BOOST_HAS_INT128
 
112 +
    BOOST_JSON_CXX14_CONSTEXPR uint128 &operator=(const boost::int128_type&  v) noexcept { *this = uint128(v); return *this; }
 
113 +
    BOOST_JSON_CXX14_CONSTEXPR uint128 &operator=(const boost::uint128_type& v) noexcept { *this = uint128(v); return *this; }
 
114 +
    #endif
 
115 +

 
116 +
    BOOST_JSON_CXX14_CONSTEXPR uint128 &operator=(const trivial_uint128& v) noexcept { this->low = v.low; this->high = v.high; return *this; }
 
117 +

 
118 +
    BOOST_JSON_CXX14_CONSTEXPR uint128 &operator=(const uint128&) noexcept;
 
119 +

 
120 +
    #undef SIGNED_ASSIGNMENT_OPERATOR
 
121 +
    #undef UNSIGNED_ASSIGNMENT_OPERATOR
 
122 +

 
123 +
    // Conversion Operators
 
124 +
    #define INTEGER_CONVERSION_OPERATOR(expr) explicit constexpr operator expr() const noexcept { return static_cast<expr>(low); } // NOLINT
 
125 +
    #define FLOAT_CONVERSION_OPERATOR(expr) explicit operator expr() const noexcept { return std::ldexp(static_cast<expr>(high), 64) + static_cast<expr>(low); } // NOLINT
 
126 +

 
127 +
    INTEGER_CONVERSION_OPERATOR(char)                   // NOLINT
 
128 +
    INTEGER_CONVERSION_OPERATOR(signed char)            // NOLINT
 
129 +
    INTEGER_CONVERSION_OPERATOR(short)                  // NOLINT
 
130 +
    INTEGER_CONVERSION_OPERATOR(int)                    // NOLINT
 
131 +
    INTEGER_CONVERSION_OPERATOR(long)                   // NOLINT
 
132 +
    INTEGER_CONVERSION_OPERATOR(long long)              // NOLINT
 
133 +
    INTEGER_CONVERSION_OPERATOR(unsigned char)          // NOLINT
 
134 +
    INTEGER_CONVERSION_OPERATOR(unsigned short)         // NOLINT
 
135 +
    INTEGER_CONVERSION_OPERATOR(unsigned)               // NOLINT
 
136 +
    INTEGER_CONVERSION_OPERATOR(unsigned long)          // NOLINT
 
137 +
    INTEGER_CONVERSION_OPERATOR(unsigned long long)     // NOLINT
 
138 +

 
139 +
    explicit constexpr operator bool() const noexcept { return high || low; }
 
140 +

 
141 +
    #ifdef BOOST_HAS_INT128
 
142 +
    explicit constexpr operator boost::int128_type()  const noexcept { return (static_cast<boost::int128_type>(high) << 64) + low; }
 
143 +
    explicit constexpr operator boost::uint128_type() const noexcept { return (static_cast<boost::uint128_type>(high) << 64) + low; }
 
144 +
    #endif
 
145 +

 
146 +
    FLOAT_CONVERSION_OPERATOR(float)        // NOLINT
 
147 +
    FLOAT_CONVERSION_OPERATOR(double)       // NOLINT
 
148 +
    FLOAT_CONVERSION_OPERATOR(long double)  // NOLINT
 
149 +

 
150 +
    #undef INTEGER_CONVERSION_OPERATOR
 
151 +
    #undef FLOAT_CONVERSION_OPERATOR
 
152 +

 
153 +
    // Unary Operators
 
154 +
    constexpr friend uint128 operator-(uint128 val) noexcept;
 
155 +
    constexpr friend uint128 operator+(uint128 val) noexcept;
 
156 +

 
157 +
    // Comparison Operators
 
158 +

 
159 +
    // Equality
 
160 +
    #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
 
161 +
    #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
 
162 +

 
163 +
    INTEGER_OPERATOR_EQUAL(char)                        // NOLINT
 
164 +
    INTEGER_OPERATOR_EQUAL(signed char)                 // NOLINT
 
165 +
    INTEGER_OPERATOR_EQUAL(short)                       // NOLINT
 
166 +
    INTEGER_OPERATOR_EQUAL(int)                         // NOLINT
 
167 +
    INTEGER_OPERATOR_EQUAL(long)                        // NOLINT
 
168 +
    INTEGER_OPERATOR_EQUAL(long long)                   // NOLINT
 
169 +
    UNSIGNED_INTEGER_OPERATOR_EQUAL(unsigned char)      // NOLINT
 
170 +
    UNSIGNED_INTEGER_OPERATOR_EQUAL(unsigned short)     // NOLINT
 
171 +
    UNSIGNED_INTEGER_OPERATOR_EQUAL(unsigned)           // NOLINT
 
172 +
    UNSIGNED_INTEGER_OPERATOR_EQUAL(unsigned long)      // NOLINT
 
173 +
    UNSIGNED_INTEGER_OPERATOR_EQUAL(unsigned long long) // NOLINT
 
174 +

 
175 +
    #ifdef BOOST_HAS_INT128
 
176 +
    constexpr friend bool operator==(uint128 lhs, boost::int128_type  rhs) noexcept { return lhs == uint128(rhs); }
 
177 +
    constexpr friend bool operator==(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs == uint128(rhs); }
 
178 +
    #endif
 
179 +

 
180 +
    constexpr friend bool operator==(uint128 lhs, uint128 rhs) noexcept;
 
181 +

 
182 +
    #undef INTEGER_OPERATOR_EQUAL
 
183 +
    #undef UNSIGNED_INTEGER_OPERATOR_EQUAL
 
184 +

 
185 +
    // Inequality
 
186 +
    #define INTEGER_OPERATOR_NOTEQUAL(expr) constexpr friend bool operator!=(uint128 lhs, expr rhs) noexcept { return !(lhs == rhs); } // NOLINT
 
187 +

 
188 +
    INTEGER_OPERATOR_NOTEQUAL(char)                 // NOLINT
 
189 +
    INTEGER_OPERATOR_NOTEQUAL(signed char)          // NOLINT
 
190 +
    INTEGER_OPERATOR_NOTEQUAL(short)                // NOLINT
 
191 +
    INTEGER_OPERATOR_NOTEQUAL(int)                  // NOLINT
 
192 +
    INTEGER_OPERATOR_NOTEQUAL(long)                 // NOLINT
 
193 +
    INTEGER_OPERATOR_NOTEQUAL(long long)            // NOLINT
 
194 +
    INTEGER_OPERATOR_NOTEQUAL(unsigned char)        // NOLINT
 
195 +
    INTEGER_OPERATOR_NOTEQUAL(unsigned short)       // NOLINT
 
196 +
    INTEGER_OPERATOR_NOTEQUAL(unsigned)             // NOLINT
 
197 +
    INTEGER_OPERATOR_NOTEQUAL(unsigned long)        // NOLINT
 
198 +
    INTEGER_OPERATOR_NOTEQUAL(unsigned long long)   // NOLINT
 
199 +

 
200 +
    #ifdef BOOST_HAS_INT128
 
201 +
    constexpr friend bool operator!=(uint128 lhs, boost::int128_type  rhs) noexcept { return !(lhs == rhs); }
 
202 +
    constexpr friend bool operator!=(uint128 lhs, boost::uint128_type rhs) noexcept { return !(lhs == rhs); }
 
203 +
    #endif
 
204 +

 
205 +
    constexpr friend bool operator!=(uint128 lhs, uint128 rhs) noexcept;
 
206 +

 
207 +
    #undef INTEGER_OPERATOR_NOTEQUAL
 
208 +

 
209 +
    // Less than
 
210 +
    #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
 
211 +
    #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
 
212 +

 
213 +
    INTEGER_OPERATOR_LESS_THAN(char)                            // NOLINT
 
214 +
    INTEGER_OPERATOR_LESS_THAN(signed char)                     // NOLINT
 
215 +
    INTEGER_OPERATOR_LESS_THAN(short)                           // NOLINT
 
216 +
    INTEGER_OPERATOR_LESS_THAN(int)                             // NOLINT
 
217 +
    INTEGER_OPERATOR_LESS_THAN(long)                            // NOLINT
 
218 +
    INTEGER_OPERATOR_LESS_THAN(long long)                       // NOLINT
 
219 +
    UNSIGNED_INTEGER_OPERATOR_LESS_THAN(unsigned char)          // NOLINT
 
220 +
    UNSIGNED_INTEGER_OPERATOR_LESS_THAN(unsigned short)         // NOLINT
 
221 +
    UNSIGNED_INTEGER_OPERATOR_LESS_THAN(unsigned)               // NOLINT
 
222 +
    UNSIGNED_INTEGER_OPERATOR_LESS_THAN(unsigned long)          // NOLINT
 
223 +
    UNSIGNED_INTEGER_OPERATOR_LESS_THAN(unsigned long long)     // NOLINT
 
224 +

 
225 +
    #ifdef BOOST_HAS_INT128
 
226 +
    BOOST_JSON_CXX14_CONSTEXPR friend bool operator<(uint128 lhs, boost::int128_type  rhs) noexcept { return lhs < uint128(rhs); }
 
227 +
    BOOST_JSON_CXX14_CONSTEXPR friend bool operator<(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs < uint128(rhs); }
 
228 +
    #endif
 
229 +

 
230 +
    BOOST_JSON_CXX14_CONSTEXPR friend bool operator<(uint128 lhs, uint128 rhs) noexcept;
 
231 +

 
232 +
    #undef INTEGER_OPERATOR_LESS_THAN
 
233 +
    #undef UNSIGNED_INTEGER_OPERATOR_LESS_THAN
 
234 +

 
235 +
    // Less than or equal to
 
236 +
    #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
 
237 +
    #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
 
238 +

 
239 +
    INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(char)                            // NOLINT
 
240 +
    INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(signed char)                     // NOLINT
 
241 +
    INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(short)                           // NOLINT
 
242 +
    INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(int)                             // NOLINT
 
243 +
    INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(long)                            // NOLINT
 
244 +
    INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(long long)                       // NOLINT
 
245 +
    UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(unsigned char)          // NOLINT
 
246 +
    UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(unsigned short)         // NOLINT
 
247 +
    UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(unsigned)               // NOLINT
 
248 +
    UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(unsigned long)          // NOLINT
 
249 +
    UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(unsigned long long)     // NOLINT
 
250 +

 
251 +
    #ifdef BOOST_HAS_INT128
 
252 +
    BOOST_JSON_CXX14_CONSTEXPR friend bool operator<=(uint128 lhs, boost::int128_type  rhs) noexcept { return lhs <= uint128(rhs); }
 
253 +
    BOOST_JSON_CXX14_CONSTEXPR friend bool operator<=(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs <= uint128(rhs); }
 
254 +
    #endif
 
255 +

 
256 +
    BOOST_JSON_CXX14_CONSTEXPR friend bool operator<=(uint128 lhs, uint128 rhs) noexcept;
 
257 +

 
258 +
    #undef INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO
 
259 +
    #undef UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO
 
260 +

 
261 +
    // Greater than
 
262 +
    #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
 
263 +
    #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
 
264 +

 
265 +
    INTEGER_OPERATOR_GREATER_THAN(char)                             // NOLINT
 
266 +
    INTEGER_OPERATOR_GREATER_THAN(signed char)                      // NOLINT
 
267 +
    INTEGER_OPERATOR_GREATER_THAN(short)                            // NOLINT
 
268 +
    INTEGER_OPERATOR_GREATER_THAN(int)                              // NOLINT
 
269 +
    INTEGER_OPERATOR_GREATER_THAN(long)                             // NOLINT
 
270 +
    INTEGER_OPERATOR_GREATER_THAN(long long)                        // NOLINT
 
271 +
    UNSIGNED_INTEGER_OPERATOR_GREATER_THAN(unsigned char)           // NOLINT
 
272 +
    UNSIGNED_INTEGER_OPERATOR_GREATER_THAN(unsigned short)          // NOLINT
 
273 +
    UNSIGNED_INTEGER_OPERATOR_GREATER_THAN(unsigned)                // NOLINT
 
274 +
    UNSIGNED_INTEGER_OPERATOR_GREATER_THAN(unsigned long)           // NOLINT
 
275 +
    UNSIGNED_INTEGER_OPERATOR_GREATER_THAN(unsigned long long)      // NOLINT
 
276 +

 
277 +
    #ifdef BOOST_HAS_INT128
 
278 +
    BOOST_JSON_CXX14_CONSTEXPR friend bool operator>(uint128 lhs, boost::int128_type  rhs) noexcept { return lhs > uint128(rhs); }
 
279 +
    BOOST_JSON_CXX14_CONSTEXPR friend bool operator>(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs > uint128(rhs); }
 
280 +
    #endif
 
281 +

 
282 +
    BOOST_JSON_CXX14_CONSTEXPR friend bool operator>(uint128 lhs, uint128 rhs) noexcept;
 
283 +

 
284 +
    #undef INTEGER_OPERATOR_GREATER_THAN
 
285 +
    #undef UNSIGNED_INTEGER_OPERATOR_GREATER_THAN
 
286 +

 
287 +
    // Greater than or equal to
 
288 +
    #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
 
289 +
    #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
 
290 +

 
291 +
    INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(char)                             // NOLINT
 
292 +
    INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(signed char)                      // NOLINT
 
293 +
    INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(short)                            // NOLINT
 
294 +
    INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(int)                              // NOLINT
 
295 +
    INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(long)                             // NOLINT
 
296 +
    INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(long long)                        // NOLINT
 
297 +
    UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(unsigned char)           // NOLINT
 
298 +
    UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(unsigned short)          // NOLINT
 
299 +
    UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(unsigned)                // NOLINT
 
300 +
    UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(unsigned long)           // NOLINT
 
301 +
    UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(unsigned long long)      // NOLINT
 
302 +

 
303 +
    #ifdef BOOST_HAS_INT128
 
304 +
    BOOST_JSON_CXX14_CONSTEXPR friend bool operator>=(uint128 lhs, boost::int128_type  rhs) noexcept { return lhs >= uint128(rhs); }
 
305 +
    BOOST_JSON_CXX14_CONSTEXPR friend bool operator>=(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs >= uint128(rhs); }
 
306 +
    #endif
 
307 +

 
308 +
    BOOST_JSON_CXX14_CONSTEXPR friend bool operator>=(uint128 lhs, uint128 rhs) noexcept;
 
309 +

 
310 +
    #undef INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO
 
311 +
    #undef UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO
 
312 +

 
313 +
    // Binary Operators
 
314 +

 
315 +
    // Not
 
316 +
    constexpr friend uint128 operator~(uint128 v) noexcept;
 
317 +

 
318 +
    // Or
 
319 +
    #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
 
320 +

 
321 +
    INTEGER_BINARY_OPERATOR_OR(char)                // NOLINT
 
322 +
    INTEGER_BINARY_OPERATOR_OR(signed char)         // NOLINT
 
323 +
    INTEGER_BINARY_OPERATOR_OR(short)               // NOLINT
 
324 +
    INTEGER_BINARY_OPERATOR_OR(int)                 // NOLINT
 
325 +
    INTEGER_BINARY_OPERATOR_OR(long)                // NOLINT
 
326 +
    INTEGER_BINARY_OPERATOR_OR(long long)           // NOLINT
 
327 +
    INTEGER_BINARY_OPERATOR_OR(unsigned char)       // NOLINT
 
328 +
    INTEGER_BINARY_OPERATOR_OR(unsigned short)      // NOLINT
 
329 +
    INTEGER_BINARY_OPERATOR_OR(unsigned)            // NOLINT
 
330 +
    INTEGER_BINARY_OPERATOR_OR(unsigned long)       // NOLINT
 
331 +
    INTEGER_BINARY_OPERATOR_OR(unsigned long long)  // NOLINT
 
332 +

 
333 +
    #ifdef BOOST_HAS_INT128
 
334 +
    constexpr friend uint128 operator|(uint128 lhs, boost::int128_type  rhs) noexcept { return lhs | uint128(rhs); }
 
335 +
    constexpr friend uint128 operator|(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs | uint128(rhs); }
 
336 +
    #endif
 
337 +

 
338 +
    constexpr friend uint128 operator|(uint128 lhs, uint128 rhs) noexcept;
 
339 +

 
340 +
    BOOST_JSON_CXX14_CONSTEXPR uint128 &operator|=(uint128 v) noexcept;
 
341 +

 
342 +
    #undef INTEGER_BINARY_OPERATOR_OR
 
343 +

 
344 +
    // And
 
345 +
    #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
 
346 +

 
347 +
    INTEGER_BINARY_OPERATOR_AND(char)                   // NOLINT
 
348 +
    INTEGER_BINARY_OPERATOR_AND(signed char)            // NOLINT
 
349 +
    INTEGER_BINARY_OPERATOR_AND(short)                  // NOLINT
 
350 +
    INTEGER_BINARY_OPERATOR_AND(int)                    // NOLINT
 
351 +
    INTEGER_BINARY_OPERATOR_AND(long)                   // NOLINT
 
352 +
    INTEGER_BINARY_OPERATOR_AND(long long)              // NOLINT
 
353 +
    INTEGER_BINARY_OPERATOR_AND(unsigned char)          // NOLINT
 
354 +
    INTEGER_BINARY_OPERATOR_AND(unsigned short)         // NOLINT
 
355 +
    INTEGER_BINARY_OPERATOR_AND(unsigned)               // NOLINT
 
356 +
    INTEGER_BINARY_OPERATOR_AND(unsigned long)          // NOLINT
 
357 +
    INTEGER_BINARY_OPERATOR_AND(unsigned long long)     // NOLINT
 
358 +

 
359 +
    #ifdef BOOST_HAS_INT128
 
360 +
    constexpr friend uint128 operator&(uint128 lhs, boost::int128_type  rhs) noexcept { return lhs & uint128(rhs); }
 
361 +
    constexpr friend uint128 operator&(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs & uint128(rhs); }
 
362 +
    #endif
 
363 +

 
364 +
    constexpr friend uint128 operator&(uint128 lhs, uint128 rhs) noexcept;
 
365 +

 
366 +
    BOOST_JSON_CXX14_CONSTEXPR uint128 &operator&=(uint128 v) noexcept;
 
367 +

 
368 +
    #undef INTEGER_BINARY_OPERATOR_AND
 
369 +

 
370 +
    // Xor
 
371 +
    #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
 
372 +

 
373 +
    INTEGER_BINARY_OPERATOR_XOR(char)                   // NOLINT
 
374 +
    INTEGER_BINARY_OPERATOR_XOR(signed char)            // NOLINT
 
375 +
    INTEGER_BINARY_OPERATOR_XOR(short)                  // NOLINT
 
376 +
    INTEGER_BINARY_OPERATOR_XOR(int)                    // NOLINT
 
377 +
    INTEGER_BINARY_OPERATOR_XOR(long)                   // NOLINT
 
378 +
    INTEGER_BINARY_OPERATOR_XOR(long long)              // NOLINT
 
379 +
    INTEGER_BINARY_OPERATOR_XOR(unsigned char)          // NOLINT
 
380 +
    INTEGER_BINARY_OPERATOR_XOR(unsigned short)         // NOLINT
 
381 +
    INTEGER_BINARY_OPERATOR_XOR(unsigned)               // NOLINT
 
382 +
    INTEGER_BINARY_OPERATOR_XOR(unsigned long)          // NOLINT
 
383 +
    INTEGER_BINARY_OPERATOR_XOR(unsigned long long)     // NOLINT
 
384 +

 
385 +
    #ifdef BOOST_HAS_INT128
 
386 +
    constexpr friend uint128 operator^(uint128 lhs, boost::int128_type  rhs) noexcept { return lhs ^ uint128(rhs); }
 
387 +
    constexpr friend uint128 operator^(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs ^ uint128(rhs); }
 
388 +
    #endif
 
389 +

 
390 +
    constexpr friend uint128 operator^(uint128 lhs, uint128 rhs) noexcept;
 
391 +

 
392 +
    BOOST_JSON_CXX14_CONSTEXPR uint128 &operator^=(uint128 v) noexcept;
 
393 +

 
394 +
    #undef INTEGER_BINARY_OPERATOR_XOR
 
395 +

 
396 +
    // Left shift
 
397 +
    #define INTEGER_BINARY_OPERATOR_LEFT_SHIFT(expr)                                            \
 
398 +
    BOOST_CXX14_CONSTEXPR friend uint128 operator<<(uint128 lhs, expr rhs) noexcept             \
 
399 +
    {                                                                                           \
 
400 +
        if (rhs >= 64)                                                                          \
 
401 +
        {                                                                                       \
 
402 +
            return {lhs.low << (rhs - 64), 0};                                                  \
 
403 +
        }                                                                                       \
 
404 +
        else if (rhs == 0)                                                                      \
 
405 +
        {                                                                                       \
 
406 +
            return lhs;                                                                         \
 
407 +
        }                                                                                       \
 
408 +
                                                                                                \
 
409 +
        return {(lhs.high << rhs) | (lhs.low >> (64 - rhs)), lhs.low << rhs};                   \
 
410 +
    } // NOLINT
 
411 +

 
412 +
    INTEGER_BINARY_OPERATOR_LEFT_SHIFT(char)                    // NOLINT
 
413 +
    INTEGER_BINARY_OPERATOR_LEFT_SHIFT(signed char)             // NOLINT
 
414 +
    INTEGER_BINARY_OPERATOR_LEFT_SHIFT(short)                   // NOLINT
 
415 +
    INTEGER_BINARY_OPERATOR_LEFT_SHIFT(int)                     // NOLINT
 
416 +
    INTEGER_BINARY_OPERATOR_LEFT_SHIFT(long)                    // NOLINT
 
417 +
    INTEGER_BINARY_OPERATOR_LEFT_SHIFT(long long)               // NOLINT
 
418 +
    INTEGER_BINARY_OPERATOR_LEFT_SHIFT(unsigned char)           // NOLINT
 
419 +
    INTEGER_BINARY_OPERATOR_LEFT_SHIFT(unsigned short)          // NOLINT
 
420 +
    INTEGER_BINARY_OPERATOR_LEFT_SHIFT(unsigned)                // NOLINT
 
421 +
    INTEGER_BINARY_OPERATOR_LEFT_SHIFT(unsigned long)           // NOLINT
 
422 +
    INTEGER_BINARY_OPERATOR_LEFT_SHIFT(unsigned long long)      // NOLINT
 
423 +

 
424 +
    #define INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(expr)                     \
 
425 +
    BOOST_CXX14_CONSTEXPR uint128 &operator<<=(expr amount) noexcept            \
 
426 +
    {                                                                           \
 
427 +
        *this = *this << amount;                                                \
 
428 +
        return *this;                                                           \
 
429 +
    } // NOLINT
 
430 +

 
431 +
    INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(char)                     // NOLINT
 
432 +
    INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(signed char)              // NOLINT
 
433 +
    INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(short)                    // NOLINT
 
434 +
    INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(int)                      // NOLINT
 
435 +
    INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(long)                     // NOLINT
 
436 +
    INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(long long)                // NOLINT
 
437 +
    INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(unsigned char)            // NOLINT
 
438 +
    INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(unsigned short)           // NOLINT
 
439 +
    INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(unsigned)                 // NOLINT
 
440 +
    INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(unsigned long)            // NOLINT
 
441 +
    INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(unsigned long long)       // NOLINT
 
442 +

 
443 +
    #undef INTEGER_BINARY_OPERATOR_LEFT_SHIFT
 
444 +
    #undef INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT
 
445 +

 
446 +
    // Right Shift
 
447 +
    #define INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(expr)                                               \
 
448 +
    BOOST_CXX14_CONSTEXPR friend uint128 operator>>(uint128 lhs, expr amount) noexcept              \
 
449 +
    {                                                                                               \
 
450 +
        if (amount >= 64)                                                                           \
 
451 +
        {                                                                                           \
 
452 +
            return {0, lhs.high >> (amount - 64)};                                                  \
 
453 +
        }                                                                                           \
 
454 +
        else if (amount == 0)                                                                       \
 
455 +
        {                                                                                           \
 
456 +
            return lhs;                                                                             \
 
457 +
        }                                                                                           \
 
458 +
                                                                                                    \
 
459 +
        return {lhs.high >> amount, (lhs.low >> amount) | (lhs.high << (64 - amount))};             \
 
460 +
    } // NOLINT
 
461 +

 
462 +
    INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(char)                   // NOLINT
 
463 +
    INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(signed char)            // NOLINT
 
464 +
    INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(short)                  // NOLINT
 
465 +
    INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(int)                    // NOLINT
 
466 +
    INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(long)                   // NOLINT
 
467 +
    INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(long long)              // NOLINT
 
468 +
    INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(unsigned char)          // NOLINT
 
469 +
    INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(unsigned short)         // NOLINT
 
470 +
    INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(unsigned)               // NOLINT
 
471 +
    INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(unsigned long)          // NOLINT
 
472 +
    INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(unsigned long long)     // NOLINT
 
473 +

 
474 +
    #define INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(expr)                        \
 
475 +
    BOOST_JSON_CXX14_CONSTEXPR uint128 &operator>>=(expr amount) noexcept           \
 
476 +
    {                                                                               \
 
477 +
        *this = *this >> amount;                                                    \
 
478 +
        return *this;                                                               \
 
479 +
    } // NOLINT
 
480 +

 
481 +
    INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(char)                    // NOLINT
 
482 +
    INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(signed char)             // NOLINT
 
483 +
    INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(short)                   // NOLINT
 
484 +
    INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(int)                     // NOLINT
 
485 +
    INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(long)                    // NOLINT
 
486 +
    INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(long long)               // NOLINT
 
487 +
    INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(unsigned char)           // NOLINT
 
488 +
    INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(unsigned short)          // NOLINT
 
489 +
    INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(unsigned)                // NOLINT
 
490 +
    INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(unsigned long)           // NOLINT
 
491 +
    INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(unsigned long long)      // NOLINT
 
492 +

 
493 +
    #undef INTEGER_BINARY_OPERATOR_RIGHT_SHIFT
 
494 +
    #undef INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT
 
495 +

 
496 +
    // Arithmetic operators (Add, sub, mul, div, mod)
 
497 +
    inline uint128 &operator+=(std::uint64_t n) noexcept;
 
498 +

 
499 +
    BOOST_JSON_CXX14_CONSTEXPR friend uint128 operator+(uint128 lhs, uint128 rhs) noexcept;
 
500 +

 
501 +
    BOOST_JSON_CXX14_CONSTEXPR uint128 &operator+=(uint128 v) noexcept;
 
502 +

 
503 +
    BOOST_JSON_CXX14_CONSTEXPR uint128 &operator++() noexcept;
 
504 +

 
505 +
    BOOST_JSON_CXX14_CONSTEXPR const uint128 operator++(int) noexcept;
 
506 +

 
507 +
    BOOST_JSON_CXX14_CONSTEXPR friend uint128 operator-(uint128 lhs, uint128 rhs) noexcept;
 
508 +

 
509 +
    BOOST_JSON_CXX14_CONSTEXPR uint128 &operator-=(uint128 v) noexcept;
 
510 +

 
511 +
    BOOST_JSON_CXX14_CONSTEXPR uint128 &operator--() noexcept;
 
512 +

 
513 +
    BOOST_JSON_CXX14_CONSTEXPR const uint128 operator--(int) noexcept;
 
514 +

 
515 +
    BOOST_JSON_CXX14_CONSTEXPR friend uint128 operator*(uint128 lhs, uint128 rhs) noexcept;
 
516 +

 
517 +
    BOOST_JSON_CXX14_CONSTEXPR uint128 &operator*=(uint128 v) noexcept;
 
518 +

 
519 +
    BOOST_JSON_CXX14_CONSTEXPR friend uint128 operator/(uint128 lhs, uint128 rhs) noexcept;
 
520 +

 
521 +
    BOOST_JSON_CXX14_CONSTEXPR uint128 &operator/=(uint128 v) noexcept;
 
522 +

 
523 +
    BOOST_JSON_CXX14_CONSTEXPR friend uint128 operator%(uint128 lhs, uint128 rhs) noexcept;
 
524 +

 
525 +
    BOOST_JSON_CXX14_CONSTEXPR uint128 &operator%=(uint128 v) noexcept;
 
526 +

 
527 +
private:
 
528 +
    BOOST_JSON_CXX14_CONSTEXPR friend int high_bit(uint128 v) noexcept;
 
529 +

 
530 +
    BOOST_JSON_CXX14_CONSTEXPR friend void
 
531 +
    div_impl(uint128 lhs, uint128 rhs, uint128 &quotient, uint128 &remainder) noexcept;
 
532 +
};
 
533 +

 
534 +
constexpr uint128 operator-(uint128 val) noexcept
 
535 +
{
 
536 +
    return {~val.high + static_cast<std::uint64_t>(val.low == 0), ~val.low + 1};
 
537 +
}
 
538 +

 
539 +
constexpr uint128 operator+(uint128 val) noexcept
 
540 +
{
 
541 +
    return val;
 
542 +
}
 
543 +

 
544 +
BOOST_JSON_CXX14_CONSTEXPR uint128 &uint128::operator=(const uint128& v) noexcept // NOLINT : User defined for older compilers
 
545 +
{
 
546 +
    low = v.low;
 
547 +
    high = v.high;
 
548 +
    return *this;
 
549 +
}
 
550 +

 
551 +
constexpr bool operator==(uint128 lhs, uint128 rhs) noexcept
 
552 +
{
 
553 +
    return lhs.high == rhs.high && lhs.low == rhs.low;
 
554 +
}
 
555 +

 
556 +
constexpr bool operator!=(uint128 lhs, uint128 rhs) noexcept
 
557 +
{
 
558 +
    return !(lhs == rhs);
 
559 +
}
 
560 +

 
561 +
BOOST_JSON_CXX14_CONSTEXPR bool operator<(uint128 lhs, uint128 rhs) noexcept
 
562 +
{
 
563 +
    if (lhs.high == rhs.high)
 
564 +
    {
 
565 +
        return lhs.low < rhs.low;
 
566 +
    }
 
567 +

 
568 +
    return lhs.high < rhs.high;
 
569 +
}
 
570 +

 
571 +
BOOST_JSON_CXX14_CONSTEXPR bool operator<=(uint128 lhs, uint128 rhs) noexcept
 
572 +
{
 
573 +
    return !(rhs < lhs);
 
574 +
}
 
575 +

 
576 +
BOOST_JSON_CXX14_CONSTEXPR bool operator>(uint128 lhs, uint128 rhs) noexcept
 
577 +
{
 
578 +
    return rhs < lhs;
 
579 +
}
 
580 +

 
581 +
BOOST_JSON_CXX14_CONSTEXPR bool operator>=(uint128 lhs, uint128 rhs) noexcept
 
582 +
{
 
583 +
    return !(lhs < rhs);
 
584 +
}
 
585 +

 
586 +
constexpr uint128 operator~(uint128 v) noexcept
 
587 +
{
 
588 +
    return {~v.high, ~v.low};
 
589 +
}
 
590 +

 
591 +
constexpr uint128 operator|(uint128 lhs, uint128 rhs) noexcept
 
592 +
{
 
593 +
    return {lhs.high | rhs.high, lhs.low | rhs.low};
 
594 +
}
 
595 +

 
596 +
BOOST_JSON_CXX14_CONSTEXPR uint128 &uint128::operator|=(uint128 v) noexcept
 
597 +
{
 
598 +
    *this = *this | v;
 
599 +
    return *this;
 
600 +
}
 
601 +

 
602 +
constexpr uint128 operator&(uint128 lhs, uint128 rhs) noexcept
 
603 +
{
 
604 +
    return {lhs.high & rhs.high, lhs.low & rhs.low};
 
605 +
}
 
606 +

 
607 +
BOOST_JSON_CXX14_CONSTEXPR uint128 &uint128::operator&=(uint128 v) noexcept
 
608 +
{
 
609 +
    *this = *this & v;
 
610 +
    return *this;
 
611 +
}
 
612 +

 
613 +
constexpr uint128 operator^(uint128 lhs, uint128 rhs) noexcept
 
614 +
{
 
615 +
    return {lhs.high ^ rhs.high, lhs.low ^ rhs.low};
 
616 +
}
 
617 +

 
618 +
BOOST_JSON_CXX14_CONSTEXPR uint128 &uint128::operator^=(uint128 v) noexcept
 
619 +
{
 
620 +
    *this = *this ^ v;
 
621 +
    return *this;
 
622 +
}
 
623 +

 
624 +
inline uint128 &uint128::operator+=(std::uint64_t n) noexcept
 
625 +
{
 
626 +
    #if BOOST_JSON_HAS_BUILTIN(__builtin_addcll)
 
627 +

 
628 +
    unsigned long long carry {};
 
629 +
        low = __builtin_addcll(low, n, 0, &carry);
 
630 +
        high = __builtin_addcll(high, 0, carry, &carry);
 
631 +

 
632 +
    #elif BOOST_JSON_HAS_BUILTIN(__builtin_ia32_addcarryx_u64)
 
633 +

 
634 +
    unsigned long long result {};
 
635 +
        auto carry = __builtin_ia32_addcarryx_u64(0, low, n, &result);
 
636 +
        low = result;
 
637 +
        __builtin_ia32_addcarryx_u64(carry, high, 0, &result);
 
638 +
        high = result;
 
639 +

 
640 +
    #elif defined(BOOST_MSVC) && defined(_M_X64)
 
641 +

 
642 +
    auto carry = _addcarry_u64(0, low, n, &low);
 
643 +
        _addcarry_u64(carry, high, 0, &high);
 
644 +

 
645 +
    #else
 
646 +

 
647 +
    auto sum = low + n;
 
648 +
    high += (sum < low ? 1 : 0);
 
649 +
    low = sum;
 
650 +

 
651 +
    #endif
 
652 +
    return *this;
 
653 +
}
 
654 +

 
655 +
BOOST_JSON_CXX14_CONSTEXPR uint128 operator+(uint128 lhs, uint128 rhs) noexcept
 
656 +
{
 
657 +
    const uint128 temp = {lhs.high + rhs.high, lhs.low + rhs.low};
 
658 +

 
659 +
    // Need to carry a bit into rhs
 
660 +
    if (temp.low < lhs.low)
 
661 +
    {
 
662 +
        return {temp.high + 1, temp.low};
 
663 +
    }
 
664 +

 
665 +
    return temp;
 
666 +
}
 
667 +

 
668 +
BOOST_JSON_CXX14_CONSTEXPR uint128 &uint128::operator+=(uint128 v) noexcept
 
669 +
{
 
670 +
    *this = *this + v;
 
671 +
    return *this;
 
672 +
}
 
673 +

 
674 +
BOOST_JSON_CXX14_CONSTEXPR uint128 &uint128::operator++() noexcept
 
675 +
{
 
676 +
    if (this->low == UINT64_MAX)
 
677 +
    {
 
678 +
        this->low = 0;
 
679 +
        ++this->high;
 
680 +
    }
 
681 +
    else
 
682 +
    {
 
683 +
        ++this->low;
 
684 +
    }
 
685 +

 
686 +
    return *this;
 
687 +
}
 
688 +

 
689 +
BOOST_JSON_CXX14_CONSTEXPR const uint128 uint128::operator++(int) noexcept
 
690 +
{
 
691 +
    return ++(*this);
 
692 +
}
 
693 +

 
694 +
BOOST_JSON_CXX14_CONSTEXPR uint128 operator-(uint128 lhs, uint128 rhs) noexcept
 
695 +
{
 
696 +
    const uint128 temp {lhs.high - rhs.high, lhs.low - rhs.low};
 
697 +

 
698 +
    // Check for carry
 
699 +
    if (lhs.low < rhs.low)
 
700 +
    {
 
701 +
        return {temp.high - 1, temp.low};
 
702 +
    }
 
703 +

 
704 +
    return temp;
 
705 +
}
 
706 +

 
707 +
BOOST_JSON_CXX14_CONSTEXPR uint128 &uint128::operator-=(uint128 v) noexcept
 
708 +
{
 
709 +
    *this = *this - v;
 
710 +
    return *this;
 
711 +
}
 
712 +

 
713 +
BOOST_JSON_CXX14_CONSTEXPR uint128 &uint128::operator--() noexcept
 
714 +
{
 
715 +
	if (this->low == 0)
 
716 +
	{
 
717 +
        this->low = UINT64_MAX;
 
718 +
        --this->high;
 
719 +
	}
 
720 +
    else // NOLINT
 
721 +
    {
 
722 +
        --this->low;
 
723 +
    }
 
724 +

 
725 +
    return *this;
 
726 +
}
 
727 +

 
728 +
BOOST_JSON_CXX14_CONSTEXPR const uint128 uint128::operator--(int) noexcept
 
729 +
{
 
730 +
    return --(*this);
 
731 +
}
 
732 +
BOOST_JSON_CXX14_CONSTEXPR uint128 operator*(uint128 lhs, uint128 rhs) noexcept
 
733 +
{
 
734 +
    const auto a = static_cast<std::uint64_t>(lhs.low >> 32);
 
735 +
    const auto b = static_cast<std::uint64_t>(lhs.low & UINT32_MAX);
 
736 +
    const auto c = static_cast<std::uint64_t>(rhs.low >> 32);
 
737 +
    const auto d = static_cast<std::uint64_t>(rhs.low & UINT32_MAX);
 
738 +

 
739 +
    uint128 result { lhs.high * rhs.low + lhs.low * rhs.high + a * c, b * d };
 
740 +
    result += uint128(a * d) << 32;
 
741 +
    result += uint128(b * c) << 32;
 
742 +
    return result;
 
743 +
}
 
744 +

 
745 +
BOOST_JSON_CXX14_CONSTEXPR uint128 &uint128::operator*=(uint128 v) noexcept
 
746 +
{
 
747 +
    *this = *this * v;
 
748 +
    return *this;
 
749 +
}
 
750 +

 
751 +
BOOST_JSON_CXX14_CONSTEXPR int high_bit(uint128 v) noexcept
 
752 +
{
 
753 +
    if (v.high != 0)
 
754 +
    {
 
755 +
        return 127 - boost::core::countl_zero(v.high);
 
756 +
    }
 
757 +
    else if (v.low != 0)
 
758 +
    {
 
759 +
        return 63 - boost::core::countl_zero(v.low);
 
760 +
    }
 
761 +

 
762 +
    return 0;
 
763 +
}
 
764 +

 
765 +
// See: https://stackoverflow.com/questions/5386377/division-without-using
 
766 +
BOOST_JSON_CXX14_CONSTEXPR void div_impl(uint128 lhs, uint128 rhs, uint128& quotient, uint128& remainder) noexcept
 
767 +
{
 
768 +
    constexpr uint128 one {0, 1};
 
769 +

 
770 +
    if (rhs > lhs)
 
771 +
    {
 
772 +
        quotient = 0U;
 
773 +
        remainder = 0U;
 
774 +
    }
 
775 +
    else if (lhs == rhs)
 
776 +
    {
 
777 +
        quotient = 1U;
 
778 +
        remainder = 0U;
 
779 +
    }
 
780 +

 
781 +
    uint128 denom = rhs;
 
782 +
    quotient = 0U;
 
783 +

 
784 +
    std::int32_t shift = high_bit(lhs) - high_bit(rhs);
 
785 +
    if (shift < 0)
 
786 +
    {
 
787 +
        shift = 32 - shift;
 
788 +
    }
 
789 +
    denom <<= shift;
 
790 +

 
791 +
    for (int i = 0; i <= shift; ++i)
 
792 +
    {
 
793 +
        quotient <<= 1;
 
794 +
        if (lhs >= denom)
 
795 +
        {
 
796 +
            lhs -= denom;
 
797 +
            quotient |= one;
 
798 +
        }
 
799 +
        denom >>= 1;
 
800 +
    }
 
801 +

 
802 +
    remainder = lhs;
 
803 +
}
 
804 +

 
805 +
BOOST_JSON_CXX14_CONSTEXPR uint128 operator/(uint128 lhs, uint128 rhs) noexcept
 
806 +
{
 
807 +
    uint128 quotient {0, 0};
 
808 +
    uint128 remainder {0, 0};
 
809 +
    div_impl(lhs, rhs, quotient, remainder);
 
810 +

 
811 +
    return quotient;
 
812 +
}
 
813 +

 
814 +
BOOST_JSON_CXX14_CONSTEXPR uint128 &uint128::operator/=(uint128 v) noexcept
 
815 +
{
 
816 +
    *this = *this / v;
 
817 +
    return *this;
 
818 +
}
 
819 +

 
820 +
BOOST_JSON_CXX14_CONSTEXPR uint128 operator%(uint128 lhs, uint128 rhs) noexcept
 
821 +
{
 
822 +
    uint128 quotient {0, 0};
 
823 +
    uint128 remainder {0, 0};
 
824 +
    div_impl(lhs, rhs, quotient, remainder);
 
825 +

 
826 +
    return remainder;
 
827 +
}
 
828 +

 
829 +
BOOST_JSON_CXX14_CONSTEXPR uint128 &uint128::operator%=(uint128 v) noexcept
 
830 +
{
 
831 +
    *this = *this % v;
 
832 +
    return *this;
 
833 +
}
 
834 +

 
835 +
static inline std::uint64_t umul64(std::uint32_t x, std::uint32_t y) noexcept
 
836 +
{
 
837 +
    // __emulu is not available on ARM https://learn.microsoft.com/en-us/cpp/intrinsics/emul-emulu?view=msvc-170
 
838 +
    #if defined(BOOST_JSON_HAS_MSVC_32BIT_INTRINSICS) && !defined(_M_ARM)
 
839 +

 
840 +
    return __emulu(x, y);
 
841 +

 
842 +
    #else
 
843 +

 
844 +
    return x * static_cast<std::uint64_t>(y);
 
845 +

 
846 +
    #endif
 
847 +
}
 
848 +

 
849 +
// Get 128-bit result of multiplication of two 64-bit unsigned integers.
 
850 +
BOOST_JSON_SAFEBUFFERS inline uint128 umul128(std::uint64_t x, std::uint64_t y) noexcept
 
851 +
{
 
852 +
    #if defined(BOOST_HAS_INT128)
 
853 +

 
854 +
    auto result = static_cast<boost::uint128_type>(x) * static_cast<boost::uint128_type>(y);
 
855 +
    return {static_cast<std::uint64_t>(result >> 64), static_cast<std::uint64_t>(result)};
 
856 +

 
857 +
    // _umul128 is x64 only https://learn.microsoft.com/en-us/cpp/intrinsics/umul128?view=msvc-170
 
858 +
    #elif defined(BOOST_JSON_HAS_MSVC_64BIT_INTRINSICS) && !defined(_M_ARM64)
 
859 +

 
860 +
    unsigned long long high;
 
861 +
    std::uint64_t low = _umul128(x, y, &high);
 
862 +
    return {static_cast<std::uint64_t>(high), low};
 
863 +

 
864 +
    // https://developer.arm.com/documentation/dui0802/a/A64-General-Instructions/UMULH
 
865 +
    #elif defined(_M_ARM64) && !defined(__MINGW32__)
 
866 +

 
867 +
    std::uint64_t high = __umulh(x, y);
 
868 +
    std::uint64_t low = x * y;
 
869 +
    return {high, low};
 
870 +

 
871 +
    #else
 
872 +

 
873 +
    auto a = static_cast<std::uint32_t>(x >> 32);
 
874 +
    auto b = static_cast<std::uint32_t>(x);
 
875 +
    auto c = static_cast<std::uint32_t>(y >> 32);
 
876 +
    auto d = static_cast<std::uint32_t>(y);
 
877 +

 
878 +
    auto ac = umul64(a, c);
 
879 +
    auto bc = umul64(b, c);
 
880 +
    auto ad = umul64(a, d);
 
881 +
    auto bd = umul64(b, d);
 
882 +

 
883 +
    auto intermediate = (bd >> 32) + static_cast<std::uint32_t>(ad) + static_cast<std::uint32_t>(bc);
 
884 +

 
885 +
    return {ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32),
 
886 +
            (intermediate << 32) + static_cast<std::uint32_t>(bd)};
 
887 +

 
888 +
    #endif
 
889 +
}
 
890 +

 
891 +
BOOST_JSON_SAFEBUFFERS inline std::uint64_t umul128_upper64(std::uint64_t x, std::uint64_t y) noexcept
 
892 +
{
 
893 +
    #if defined(BOOST_HAS_INT128)
 
894 +

 
895 +
    auto result = static_cast<boost::uint128_type>(x) * static_cast<boost::uint128_type>(y);
 
896 +
    return static_cast<std::uint64_t>(result >> 64);
 
897 +

 
898 +
    #elif defined(BOOST_JSON_HAS_MSVC_64BIT_INTRINSICS)
 
899 +

 
900 +
    return __umulh(x, y);
 
901 +

 
902 +
    #else
 
903 +

 
904 +
    auto a = static_cast<std::uint32_t>(x >> 32);
 
905 +
    auto b = static_cast<std::uint32_t>(x);
 
906 +
    auto c = static_cast<std::uint32_t>(y >> 32);
 
907 +
    auto d = static_cast<std::uint32_t>(y);
 
908 +

 
909 +
    auto ac = umul64(a, c);
 
910 +
    auto bc = umul64(b, c);
 
911 +
    auto ad = umul64(a, d);
 
912 +
    auto bd = umul64(b, d);
 
913 +

 
914 +
    auto intermediate = (bd >> 32) + static_cast<std::uint32_t>(ad) + static_cast<std::uint32_t>(bc);
 
915 +

 
916 +
    return ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32);
 
917 +

 
918 +
    #endif
 
919 +
}
 
920 +

 
921 +
// Get upper 128-bits of multiplication of a 64-bit unsigned integer and a 128-bit
 
922 +
// unsigned integer.
 
923 +
BOOST_JSON_SAFEBUFFERS inline uint128 umul192_upper128(std::uint64_t x, uint128 y) noexcept
 
924 +
{
 
925 +
    auto r = umul128(x, y.high);
 
926 +
    r += umul128_upper64(x, y.low);
 
927 +
    return r;
 
928 +
}
 
929 +

 
930 +
// Get upper 64-bits of multiplication of a 32-bit unsigned integer and a 64-bit
 
931 +
// unsigned integer.
 
932 +
inline std::uint64_t umul96_upper64(std::uint32_t x, std::uint64_t y) noexcept
 
933 +
{
 
934 +
    #if defined(BOOST_HAS_INT128) || defined(BOOST_JSON_HAS_MSVC_64BIT_INTRINSICS)
 
935 +

 
936 +
    return umul128_upper64(static_cast<std::uint64_t>(x) << 32, y);
 
937 +

 
938 +
    #else
 
939 +

 
940 +
    auto yh = static_cast<std::uint32_t>(y >> 32);
 
941 +
    auto yl = static_cast<std::uint32_t>(y);
 
942 +

 
943 +
    auto xyh = umul64(x, yh);
 
944 +
    auto xyl = umul64(x, yl);
 
945 +

 
946 +
    return xyh + (xyl >> 32);
 
947 +

 
948 +
    #endif
 
949 +
}
 
950 +

 
951 +
// Get lower 128-bits of multiplication of a 64-bit unsigned integer and a 128-bit
 
952 +
// unsigned integer.
 
953 +
BOOST_JSON_SAFEBUFFERS inline uint128 umul192_lower128(std::uint64_t x, uint128 y) noexcept
 
954 +
{
 
955 +
    auto high = x * y.high;
 
956 +
    auto highlow = umul128(x, y.low);
 
957 +
    return {high + highlow.high, highlow.low};
 
958 +
}
 
959 +

 
960 +
// Get lower 64-bits of multiplication of a 32-bit unsigned integer and a 64-bit
 
961 +
// unsigned integer.
 
962 +
inline std::uint64_t umul96_lower64(std::uint32_t x, std::uint64_t y) noexcept
 
963 +
{
 
964 +
    return x * y;
 
965 +
}
 
966 +

 
967 +
} // namespace detail
 
968 +
} // namespace json
 
969 +
} // namespace boost
 
970 +

 
971 +
// Non-standard libraries may add specializations for library-provided types
 
972 +
namespace std {
 
973 +

 
974 +
template <>
 
975 +
struct numeric_limits<boost::json::detail::uint128>
 
976 +
{
 
977 +
    // Member constants
 
978 +
    BOOST_ATTRIBUTE_UNUSED static constexpr bool is_specialized = true;
 
979 +
    BOOST_ATTRIBUTE_UNUSED static constexpr bool is_signed = false;
 
980 +
    BOOST_ATTRIBUTE_UNUSED static constexpr bool is_integer = true;
 
981 +
    BOOST_ATTRIBUTE_UNUSED static constexpr bool is_exact = true;
 
982 +
    BOOST_ATTRIBUTE_UNUSED static constexpr bool has_infinity = false;
 
983 +
    BOOST_ATTRIBUTE_UNUSED static constexpr bool has_quiet_NaN = false;
 
984 +
    BOOST_ATTRIBUTE_UNUSED static constexpr bool has_signaling_NaN = false;
 
985 +
    BOOST_ATTRIBUTE_UNUSED static constexpr std::float_round_style round_style = std::round_toward_zero;
 
986 +
    BOOST_ATTRIBUTE_UNUSED static constexpr bool is_iec559 = false;
 
987 +
    BOOST_ATTRIBUTE_UNUSED static constexpr bool is_bounded = true;
 
988 +
    BOOST_ATTRIBUTE_UNUSED static constexpr bool is_modulo = true;
 
989 +
    BOOST_ATTRIBUTE_UNUSED static constexpr int digits = 128;
 
990 +
    BOOST_ATTRIBUTE_UNUSED static constexpr int digits10 = 38;
 
991 +
    BOOST_ATTRIBUTE_UNUSED static constexpr int max_digits10 = 0;
 
992 +
    BOOST_ATTRIBUTE_UNUSED static constexpr int radix = 2;
 
993 +
    BOOST_ATTRIBUTE_UNUSED static constexpr int min_exponent = 0;
 
994 +
    BOOST_ATTRIBUTE_UNUSED static constexpr int min_exponent10 = 0;
 
995 +
    BOOST_ATTRIBUTE_UNUSED static constexpr int max_exponent = 0;
 
996 +
    BOOST_ATTRIBUTE_UNUSED static constexpr int max_exponent10 = 0;
 
997 +
    BOOST_ATTRIBUTE_UNUSED static constexpr bool traps = std::numeric_limits<std::uint64_t>::traps;
 
998 +
    BOOST_ATTRIBUTE_UNUSED static constexpr bool tinyness_before = false;
 
999 +

 
1000 +
    // Member functions
 
1001 +
    BOOST_ATTRIBUTE_UNUSED static constexpr boost::json::detail::uint128 (min)() { return 0; }
 
1002 +
    BOOST_ATTRIBUTE_UNUSED static constexpr boost::json::detail::uint128 lowest() { return 0; }
 
1003 +
    BOOST_ATTRIBUTE_UNUSED static constexpr boost::json::detail::uint128 (max)() { return {UINT64_MAX, UINT64_MAX}; }
 
1004 +
    BOOST_ATTRIBUTE_UNUSED static constexpr boost::json::detail::uint128 epsilon() { return 0; }
 
1005 +
    BOOST_ATTRIBUTE_UNUSED static constexpr boost::json::detail::uint128 round_error() { return 0; }
 
1006 +
    BOOST_ATTRIBUTE_UNUSED static constexpr boost::json::detail::uint128 infinity() { return 0; }
 
1007 +
    BOOST_ATTRIBUTE_UNUSED static constexpr boost::json::detail::uint128 quiet_NaN() { return 0; }
 
1008 +
    BOOST_ATTRIBUTE_UNUSED static constexpr boost::json::detail::uint128 signaling_NaN() { return 0; }
 
1009 +
    BOOST_ATTRIBUTE_UNUSED static constexpr boost::json::detail::uint128 (denorm_min)() { return 0; }
 
1010 +
};
 
1011 +

 
1012 +
} // Namespace std
 
1013 +

 
1014 +
#endif // BOOST_JSON_DETAIL_DRAGONBOX_EMULATED128_HPP