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