1 // A relatively minimal unsigned 128-bit integer class type, used by the
2 // floating-point std::to_chars implementation on targets that lack __int128.
4 // Copyright (C) 2021-2024 Free Software Foundation, Inc.
6 // This file is part of the GNU ISO C++ Library. This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 3, or (at your option)
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // Under Section 7 of GPL version 3, you are granted additional
18 // permissions described in the GCC Runtime Library Exception, version
19 // 3.1, as published by the Free Software Foundation.
21 // You should have received a copy of the GNU General Public License and
22 // a copy of the GCC Runtime Library Exception along with this program;
23 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 // <http://www.gnu.org/licenses/>.
28 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
34 uint128_t() = default;
37 uint128_t(uint64_t lo
, uint64_t hi
= 0)
38 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
47 { return *this != 0; }
49 template<typename T
, typename
= std::enable_if_t
<std::is_integral_v
<T
>>>
53 static_assert(sizeof(T
) <= sizeof(uint64_t));
54 return static_cast<T
>(lo
);
57 friend constexpr uint128_t
58 operator&(uint128_t x
, const uint128_t y
)
65 friend constexpr uint128_t
66 operator|(uint128_t x
, const uint128_t y
)
73 friend constexpr uint128_t
74 operator<<(uint128_t x
, const uint128_t y
)
76 __glibcxx_assert(y
< 128);
77 // TODO: Convince GCC to use shldq on x86 here.
80 x
.hi
= x
.lo
<< (y
.lo
- 64);
86 x
.hi
|= x
.lo
>> (64 - y
.lo
);
92 friend constexpr uint128_t
93 operator>>(uint128_t x
, const uint128_t y
)
95 __glibcxx_assert(y
< 128);
96 // TODO: Convince GCC to use shrdq on x86 here.
99 x
.lo
= x
.hi
>> (y
.lo
- 64);
105 x
.lo
|= x
.hi
<< (64 - y
.lo
);
113 { return {~lo
, ~hi
}; }
117 { return operator~() + 1; }
119 friend constexpr uint128_t
120 operator+(uint128_t x
, const uint128_t y
)
122 x
.hi
+= __builtin_add_overflow(x
.lo
, y
.lo
, &x
.lo
);
127 friend constexpr uint128_t
128 operator-(uint128_t x
, const uint128_t y
)
130 x
.hi
-= __builtin_sub_overflow(x
.lo
, y
.lo
, &x
.lo
);
135 static constexpr uint128_t
136 umul64_64_128(const uint64_t x
, const uint64_t y
)
138 const uint64_t xl
= x
& 0xffffffff;
139 const uint64_t xh
= x
>> 32;
140 const uint64_t yl
= y
& 0xffffffff;
141 const uint64_t yh
= y
>> 32;
142 const uint64_t ll
= xl
* yl
;
143 const uint64_t lh
= xl
* yh
;
144 const uint64_t hl
= xh
* yl
;
145 const uint64_t hh
= xh
* yh
;
146 const uint64_t m
= (ll
>> 32) + lh
+ (hl
& 0xffffffff);
147 const uint64_t l
= (ll
& 0xffffffff ) | (m
<< 32);
148 const uint64_t h
= (m
>> 32) + (hl
>> 32) + hh
;
152 friend constexpr uint128_t
153 operator*(const uint128_t x
, const uint128_t y
)
155 uint128_t z
= umul64_64_128(x
.lo
, y
.lo
);
156 z
.hi
+= x
.lo
* y
.hi
+ x
.hi
* y
.lo
;
160 friend constexpr uint128_t
161 operator/(const uint128_t x
, const uint128_t y
)
163 // Ryu performs 128-bit division only by 5 and 10, so that's what we
164 // implement. The strategy here is to relate division of x with that of
165 // x.hi and x.lo separately.
166 __glibcxx_assert(y
== 5 || y
== 10);
167 // The following implements division by 5 and 10. In either case, we
168 // first compute division by 5:
169 // x/5 = (x.hi*2^64 + x.lo)/5
170 // = (x.hi*(2^64-1) + x.hi + x.lo)/5
171 // = x.hi*((2^64-1)/5) + (x.hi + x.lo)/5 since CST=(2^64-1)/5 is exact
172 // = x.hi*CST + x.hi/5 + x.lo/5 + ((x.lo%5) + (x.hi%5) >= 5)
173 // We go a step further and replace the last adjustment term with a
174 // lookup table, which we encode as a binary literal. This seems to
175 // yield smaller code on x86 at least.
176 constexpr auto cst
= ~uint64_t(0) / 5;
177 uint128_t q
= uint128_t
{x
.hi
}*cst
+ uint128_t
{x
.hi
/5 + x
.lo
/5};
178 constexpr auto lookup
= 0b111100000u
;
179 q
+= (lookup
>> ((x
.hi
% 5) + (x
.lo
% 5))) & 1;
185 friend constexpr uint128_t
186 operator%(const uint128_t x
, const uint128_t y
)
188 // Ryu performs 128-bit modulus only by 2, 5 and 10, so that's what we
189 // implement. The strategy here is to relate modulus of x with that of
190 // x.hi and x.lo separately.
193 __glibcxx_assert(y
== 5 || y
== 10);
194 // The following implements modulus by 5 and 10. In either case,
195 // we first compute modulus by 5:
196 // x (mod 5) = x.hi*2^64 + x.lo (mod 5)
197 // = x.hi + x.lo (mod 5) since 2^64 ≡ 1 (mod 5)
198 // So the straightforward implementation would be
199 // ((x.hi % 5) + (x.lo % 5)) % 5
200 // But we go a step further and replace the outermost % with a
202 // = {0,1,2,3,4,0,1,2,3}[(x.hi % 5) + (x.lo % 5)] (mod 5)
203 // which we encode as an octal literal.
204 constexpr auto lookup
= 0321043210u;
205 auto r
= (lookup
>> 3*((x
.hi
% 5) + (x
.lo
% 5))) & 7;
207 // x % 10 = (x % 5) if x / 5 is even
208 // (x % 5) + 5 if x / 5 is odd
209 // The compiler should be able to CSE the below computation of x/5 and
210 // the above modulus operations with a nearby inlined computation of x/10.
211 r
+= 5 * ((x
/5).lo
& 1);
215 friend constexpr bool
216 operator==(const uint128_t x
, const uint128_t y
)
217 { return x
.hi
== y
.hi
&& x
.lo
== y
.lo
; }
219 friend constexpr bool
220 operator<(const uint128_t x
, const uint128_t y
)
221 { return x
.hi
< y
.hi
|| (x
.hi
== y
.hi
&& x
.lo
< y
.lo
); }
223 friend constexpr auto
224 __bit_width(const uint128_t x
)
226 if (auto w
= std::__bit_width(x
.hi
))
229 return std::__bit_width(x
.lo
);
232 friend constexpr auto
233 __countr_zero(const uint128_t x
)
235 auto c
= std::__countr_zero(x
.lo
);
237 return 64 + std::__countr_zero(x
.hi
);
244 { return *this -= 1; }
248 { return *this += 1; }
251 operator+=(const uint128_t y
)
252 { return *this = *this + y
; }
255 operator-=(const uint128_t y
)
256 { return *this = *this - y
; }
259 operator*=(const uint128_t y
)
260 { return *this = *this * y
; }
263 operator<<=(const uint128_t y
)
264 { return *this = *this << y
; }
267 operator>>=(const uint128_t y
)
268 { return *this = *this >> y
; }
271 operator|=(const uint128_t y
)
272 { return *this = *this | y
; }
275 operator&=(const uint128_t y
)
276 { return *this = *this & y
; }
279 operator%=(const uint128_t y
)
280 { return *this = *this % y
; }
283 operator/=(const uint128_t y
)
284 { return *this = *this / y
; }
286 friend constexpr bool
287 operator!=(const uint128_t x
, const uint128_t y
)
288 { return !(x
== y
); }
290 friend constexpr bool
291 operator>(const uint128_t x
, const uint128_t y
)
294 friend constexpr bool
295 operator>=(const uint128_t x
, const uint128_t y
)