1*da0073e9SAndroid Build Coastguard Worker // This file is based on the uint128 implementation of protobuf at
2*da0073e9SAndroid Build Coastguard Worker // https://github.com/protocolbuffers/protobuf/blob/1e88936fce10cf773cb72b44c6a7f48b38c7578b/src/google/protobuf/stubs/int128.h
3*da0073e9SAndroid Build Coastguard Worker //
4*da0073e9SAndroid Build Coastguard Worker // Protocol Buffers - Google's data interchange format
5*da0073e9SAndroid Build Coastguard Worker // Copyright 2008 Google Inc. All rights reserved.
6*da0073e9SAndroid Build Coastguard Worker // https://developers.google.com/protocol-buffers/
7*da0073e9SAndroid Build Coastguard Worker //
8*da0073e9SAndroid Build Coastguard Worker // Redistribution and use in source and binary forms, with or without
9*da0073e9SAndroid Build Coastguard Worker // modification, are permitted provided that the following conditions are
10*da0073e9SAndroid Build Coastguard Worker // met:
11*da0073e9SAndroid Build Coastguard Worker //
12*da0073e9SAndroid Build Coastguard Worker // * Redistributions of source code must retain the above copyright
13*da0073e9SAndroid Build Coastguard Worker // notice, this list of conditions and the following disclaimer.
14*da0073e9SAndroid Build Coastguard Worker // * Redistributions in binary form must reproduce the above
15*da0073e9SAndroid Build Coastguard Worker // copyright notice, this list of conditions and the following disclaimer
16*da0073e9SAndroid Build Coastguard Worker // in the documentation and/or other materials provided with the
17*da0073e9SAndroid Build Coastguard Worker // distribution.
18*da0073e9SAndroid Build Coastguard Worker // * Neither the name of Google Inc. nor the names of its
19*da0073e9SAndroid Build Coastguard Worker // contributors may be used to endorse or promote products derived from
20*da0073e9SAndroid Build Coastguard Worker // this software without specific prior written permission.
21*da0073e9SAndroid Build Coastguard Worker //
22*da0073e9SAndroid Build Coastguard Worker // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23*da0073e9SAndroid Build Coastguard Worker // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24*da0073e9SAndroid Build Coastguard Worker // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25*da0073e9SAndroid Build Coastguard Worker // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26*da0073e9SAndroid Build Coastguard Worker // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27*da0073e9SAndroid Build Coastguard Worker // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28*da0073e9SAndroid Build Coastguard Worker // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29*da0073e9SAndroid Build Coastguard Worker // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30*da0073e9SAndroid Build Coastguard Worker // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31*da0073e9SAndroid Build Coastguard Worker // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32*da0073e9SAndroid Build Coastguard Worker // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33*da0073e9SAndroid Build Coastguard Worker #pragma once
34*da0073e9SAndroid Build Coastguard Worker
35*da0073e9SAndroid Build Coastguard Worker #include <c10/macros/Export.h>
36*da0073e9SAndroid Build Coastguard Worker #include <cstdint>
37*da0073e9SAndroid Build Coastguard Worker #include <iosfwd>
38*da0073e9SAndroid Build Coastguard Worker
39*da0073e9SAndroid Build Coastguard Worker namespace c10 {
40*da0073e9SAndroid Build Coastguard Worker
41*da0073e9SAndroid Build Coastguard Worker struct uint128_pod;
42*da0073e9SAndroid Build Coastguard Worker
43*da0073e9SAndroid Build Coastguard Worker // TODO(xiaofeng): Define GOOGLE_PROTOBUF_HAS_CONSTEXPR when constexpr is
44*da0073e9SAndroid Build Coastguard Worker // available.
45*da0073e9SAndroid Build Coastguard Worker #ifdef GOOGLE_PROTOBUF_HAS_CONSTEXPR
46*da0073e9SAndroid Build Coastguard Worker #define UINT128_CONSTEXPR constexpr
47*da0073e9SAndroid Build Coastguard Worker #else
48*da0073e9SAndroid Build Coastguard Worker #define UINT128_CONSTEXPR
49*da0073e9SAndroid Build Coastguard Worker #endif
50*da0073e9SAndroid Build Coastguard Worker
51*da0073e9SAndroid Build Coastguard Worker class uint128;
52*da0073e9SAndroid Build Coastguard Worker inline uint128& operator<<=(uint128& self, int amount);
53*da0073e9SAndroid Build Coastguard Worker
54*da0073e9SAndroid Build Coastguard Worker // An unsigned 128-bit integer type. Thread-compatible.
55*da0073e9SAndroid Build Coastguard Worker class C10_API uint128 {
56*da0073e9SAndroid Build Coastguard Worker public:
57*da0073e9SAndroid Build Coastguard Worker UINT128_CONSTEXPR uint128(); // Sets to 0, but don't trust on this behavior.
58*da0073e9SAndroid Build Coastguard Worker UINT128_CONSTEXPR uint128(uint64_t top, uint64_t bottom);
59*da0073e9SAndroid Build Coastguard Worker #ifndef SWIG
60*da0073e9SAndroid Build Coastguard Worker UINT128_CONSTEXPR uint128(int bottom);
61*da0073e9SAndroid Build Coastguard Worker UINT128_CONSTEXPR uint128(uint32_t bottom); // Top 96 bits = 0
62*da0073e9SAndroid Build Coastguard Worker #endif
63*da0073e9SAndroid Build Coastguard Worker UINT128_CONSTEXPR uint128(uint64_t bottom); // hi_ = 0
64*da0073e9SAndroid Build Coastguard Worker UINT128_CONSTEXPR uint128(const uint128_pod& val);
65*da0073e9SAndroid Build Coastguard Worker
66*da0073e9SAndroid Build Coastguard Worker // Trivial copy constructor, assignment operator and destructor.
67*da0073e9SAndroid Build Coastguard Worker
68*da0073e9SAndroid Build Coastguard Worker void Initialize(uint64_t top, uint64_t bottom);
69*da0073e9SAndroid Build Coastguard Worker
70*da0073e9SAndroid Build Coastguard Worker // Arithmetic operators.
71*da0073e9SAndroid Build Coastguard Worker uint128& operator+=(const uint128& b);
72*da0073e9SAndroid Build Coastguard Worker uint128& operator-=(const uint128& b);
73*da0073e9SAndroid Build Coastguard Worker uint128& operator*=(const uint128& b);
74*da0073e9SAndroid Build Coastguard Worker // Long division/modulo for uint128.
75*da0073e9SAndroid Build Coastguard Worker uint128& operator/=(const uint128& b);
76*da0073e9SAndroid Build Coastguard Worker uint128& operator%=(const uint128& b);
77*da0073e9SAndroid Build Coastguard Worker uint128 operator++(int);
78*da0073e9SAndroid Build Coastguard Worker uint128 operator--(int);
79*da0073e9SAndroid Build Coastguard Worker // Make msvc happy with using operator<<= from DivModImpl
80*da0073e9SAndroid Build Coastguard Worker // which is a static function, and linker complained about missing
81*da0073e9SAndroid Build Coastguard Worker // static version of this overload
82*da0073e9SAndroid Build Coastguard Worker friend uint128& operator<<=(uint128&, int);
83*da0073e9SAndroid Build Coastguard Worker uint128& operator>>=(int);
84*da0073e9SAndroid Build Coastguard Worker uint128& operator&=(const uint128& b);
85*da0073e9SAndroid Build Coastguard Worker uint128& operator|=(const uint128& b);
86*da0073e9SAndroid Build Coastguard Worker uint128& operator^=(const uint128& b);
87*da0073e9SAndroid Build Coastguard Worker uint128& operator++();
88*da0073e9SAndroid Build Coastguard Worker uint128& operator--();
89*da0073e9SAndroid Build Coastguard Worker
90*da0073e9SAndroid Build Coastguard Worker friend uint64_t Uint128Low64(const uint128& v);
91*da0073e9SAndroid Build Coastguard Worker friend uint64_t Uint128High64(const uint128& v);
92*da0073e9SAndroid Build Coastguard Worker
93*da0073e9SAndroid Build Coastguard Worker // We add "std::" to avoid including all of port.h.
94*da0073e9SAndroid Build Coastguard Worker C10_API friend std::ostream& operator<<(std::ostream& o, const uint128& b);
95*da0073e9SAndroid Build Coastguard Worker
96*da0073e9SAndroid Build Coastguard Worker private:
97*da0073e9SAndroid Build Coastguard Worker static void DivModImpl(
98*da0073e9SAndroid Build Coastguard Worker uint128 dividend,
99*da0073e9SAndroid Build Coastguard Worker uint128 divisor,
100*da0073e9SAndroid Build Coastguard Worker uint128* quotient_ret,
101*da0073e9SAndroid Build Coastguard Worker uint128* remainder_ret);
102*da0073e9SAndroid Build Coastguard Worker
103*da0073e9SAndroid Build Coastguard Worker // Little-endian memory order optimizations can benefit from
104*da0073e9SAndroid Build Coastguard Worker // having lo_ first, hi_ last.
105*da0073e9SAndroid Build Coastguard Worker // See util/endian/endian.h and Load128/Store128 for storing a uint128.
106*da0073e9SAndroid Build Coastguard Worker uint64_t lo_;
107*da0073e9SAndroid Build Coastguard Worker uint64_t hi_;
108*da0073e9SAndroid Build Coastguard Worker
109*da0073e9SAndroid Build Coastguard Worker // Not implemented, just declared for catching automatic type conversions.
110*da0073e9SAndroid Build Coastguard Worker uint128(uint8_t);
111*da0073e9SAndroid Build Coastguard Worker uint128(uint16_t);
112*da0073e9SAndroid Build Coastguard Worker uint128(float v);
113*da0073e9SAndroid Build Coastguard Worker uint128(double v);
114*da0073e9SAndroid Build Coastguard Worker };
115*da0073e9SAndroid Build Coastguard Worker
116*da0073e9SAndroid Build Coastguard Worker // This is a POD form of uint128 which can be used for static variables which
117*da0073e9SAndroid Build Coastguard Worker // need to be operated on as uint128.
118*da0073e9SAndroid Build Coastguard Worker struct uint128_pod {
119*da0073e9SAndroid Build Coastguard Worker // Note: The ordering of fields is different than 'class uint128' but the
120*da0073e9SAndroid Build Coastguard Worker // same as its 2-arg constructor. This enables more obvious initialization
121*da0073e9SAndroid Build Coastguard Worker // of static instances, which is the primary reason for this struct in the
122*da0073e9SAndroid Build Coastguard Worker // first place. This does not seem to defeat any optimizations wrt
123*da0073e9SAndroid Build Coastguard Worker // operations involving this struct.
124*da0073e9SAndroid Build Coastguard Worker uint64_t hi;
125*da0073e9SAndroid Build Coastguard Worker uint64_t lo;
126*da0073e9SAndroid Build Coastguard Worker };
127*da0073e9SAndroid Build Coastguard Worker
128*da0073e9SAndroid Build Coastguard Worker C10_API extern const uint128_pod kuint128max;
129*da0073e9SAndroid Build Coastguard Worker
130*da0073e9SAndroid Build Coastguard Worker // allow uint128 to be logged
131*da0073e9SAndroid Build Coastguard Worker C10_API extern std::ostream& operator<<(std::ostream& o, const uint128& b);
132*da0073e9SAndroid Build Coastguard Worker
133*da0073e9SAndroid Build Coastguard Worker // Methods to access low and high pieces of 128-bit value.
134*da0073e9SAndroid Build Coastguard Worker // Defined externally from uint128 to facilitate conversion
135*da0073e9SAndroid Build Coastguard Worker // to native 128-bit types when compilers support them.
Uint128Low64(const uint128 & v)136*da0073e9SAndroid Build Coastguard Worker inline uint64_t Uint128Low64(const uint128& v) {
137*da0073e9SAndroid Build Coastguard Worker return v.lo_;
138*da0073e9SAndroid Build Coastguard Worker }
Uint128High64(const uint128 & v)139*da0073e9SAndroid Build Coastguard Worker inline uint64_t Uint128High64(const uint128& v) {
140*da0073e9SAndroid Build Coastguard Worker return v.hi_;
141*da0073e9SAndroid Build Coastguard Worker }
142*da0073e9SAndroid Build Coastguard Worker
143*da0073e9SAndroid Build Coastguard Worker // TODO: perhaps it would be nice to have int128, a signed 128-bit type?
144*da0073e9SAndroid Build Coastguard Worker
145*da0073e9SAndroid Build Coastguard Worker // --------------------------------------------------------------------------
146*da0073e9SAndroid Build Coastguard Worker // Implementation details follow
147*da0073e9SAndroid Build Coastguard Worker // --------------------------------------------------------------------------
148*da0073e9SAndroid Build Coastguard Worker inline bool operator==(const uint128& lhs, const uint128& rhs) {
149*da0073e9SAndroid Build Coastguard Worker return (
150*da0073e9SAndroid Build Coastguard Worker Uint128Low64(lhs) == Uint128Low64(rhs) &&
151*da0073e9SAndroid Build Coastguard Worker Uint128High64(lhs) == Uint128High64(rhs));
152*da0073e9SAndroid Build Coastguard Worker }
153*da0073e9SAndroid Build Coastguard Worker inline bool operator!=(const uint128& lhs, const uint128& rhs) {
154*da0073e9SAndroid Build Coastguard Worker return !(lhs == rhs);
155*da0073e9SAndroid Build Coastguard Worker }
156*da0073e9SAndroid Build Coastguard Worker
uint128()157*da0073e9SAndroid Build Coastguard Worker C10_API inline UINT128_CONSTEXPR uint128::uint128() : lo_(0), hi_(0) {}
uint128(uint64_t top,uint64_t bottom)158*da0073e9SAndroid Build Coastguard Worker C10_API inline UINT128_CONSTEXPR uint128::uint128(uint64_t top, uint64_t bottom)
159*da0073e9SAndroid Build Coastguard Worker : lo_(bottom), hi_(top) {}
uint128(const uint128_pod & v)160*da0073e9SAndroid Build Coastguard Worker C10_API inline UINT128_CONSTEXPR uint128::uint128(const uint128_pod& v)
161*da0073e9SAndroid Build Coastguard Worker : lo_(v.lo), hi_(v.hi) {}
uint128(uint64_t bottom)162*da0073e9SAndroid Build Coastguard Worker C10_API inline UINT128_CONSTEXPR uint128::uint128(uint64_t bottom)
163*da0073e9SAndroid Build Coastguard Worker : lo_(bottom), hi_(0) {}
164*da0073e9SAndroid Build Coastguard Worker #ifndef SWIG
uint128(uint32_t bottom)165*da0073e9SAndroid Build Coastguard Worker C10_API inline UINT128_CONSTEXPR uint128::uint128(uint32_t bottom)
166*da0073e9SAndroid Build Coastguard Worker : lo_(bottom), hi_(0) {}
uint128(int bottom)167*da0073e9SAndroid Build Coastguard Worker C10_API inline UINT128_CONSTEXPR uint128::uint128(int bottom)
168*da0073e9SAndroid Build Coastguard Worker : lo_(bottom), hi_(static_cast<int64_t>((bottom < 0) ? -1 : 0)) {}
169*da0073e9SAndroid Build Coastguard Worker #endif
170*da0073e9SAndroid Build Coastguard Worker
171*da0073e9SAndroid Build Coastguard Worker #undef UINT128_CONSTEXPR
172*da0073e9SAndroid Build Coastguard Worker
Initialize(uint64_t top,uint64_t bottom)173*da0073e9SAndroid Build Coastguard Worker C10_API inline void uint128::Initialize(uint64_t top, uint64_t bottom) {
174*da0073e9SAndroid Build Coastguard Worker hi_ = top;
175*da0073e9SAndroid Build Coastguard Worker lo_ = bottom;
176*da0073e9SAndroid Build Coastguard Worker }
177*da0073e9SAndroid Build Coastguard Worker
178*da0073e9SAndroid Build Coastguard Worker // Comparison operators.
179*da0073e9SAndroid Build Coastguard Worker
180*da0073e9SAndroid Build Coastguard Worker #define CMP128(op) \
181*da0073e9SAndroid Build Coastguard Worker inline bool operator op(const uint128& lhs, const uint128& rhs) { \
182*da0073e9SAndroid Build Coastguard Worker return (Uint128High64(lhs) == Uint128High64(rhs)) \
183*da0073e9SAndroid Build Coastguard Worker ? (Uint128Low64(lhs) op Uint128Low64(rhs)) \
184*da0073e9SAndroid Build Coastguard Worker : (Uint128High64(lhs) op Uint128High64(rhs)); \
185*da0073e9SAndroid Build Coastguard Worker }
186*da0073e9SAndroid Build Coastguard Worker
187*da0073e9SAndroid Build Coastguard Worker CMP128(<)
188*da0073e9SAndroid Build Coastguard Worker CMP128(>)
189*da0073e9SAndroid Build Coastguard Worker CMP128(>=)
190*da0073e9SAndroid Build Coastguard Worker CMP128(<=)
191*da0073e9SAndroid Build Coastguard Worker
192*da0073e9SAndroid Build Coastguard Worker #undef CMP128
193*da0073e9SAndroid Build Coastguard Worker
194*da0073e9SAndroid Build Coastguard Worker // Unary operators
195*da0073e9SAndroid Build Coastguard Worker
196*da0073e9SAndroid Build Coastguard Worker inline uint128 operator-(const uint128& val) {
197*da0073e9SAndroid Build Coastguard Worker const uint64_t hi_flip = ~Uint128High64(val);
198*da0073e9SAndroid Build Coastguard Worker const uint64_t lo_flip = ~Uint128Low64(val);
199*da0073e9SAndroid Build Coastguard Worker const uint64_t lo_add = lo_flip + 1;
200*da0073e9SAndroid Build Coastguard Worker if (lo_add < lo_flip) {
201*da0073e9SAndroid Build Coastguard Worker return uint128(hi_flip + 1, lo_add);
202*da0073e9SAndroid Build Coastguard Worker }
203*da0073e9SAndroid Build Coastguard Worker return uint128(hi_flip, lo_add);
204*da0073e9SAndroid Build Coastguard Worker }
205*da0073e9SAndroid Build Coastguard Worker
206*da0073e9SAndroid Build Coastguard Worker inline bool operator!(const uint128& val) {
207*da0073e9SAndroid Build Coastguard Worker return !Uint128High64(val) && !Uint128Low64(val);
208*da0073e9SAndroid Build Coastguard Worker }
209*da0073e9SAndroid Build Coastguard Worker
210*da0073e9SAndroid Build Coastguard Worker // Logical operators.
211*da0073e9SAndroid Build Coastguard Worker
212*da0073e9SAndroid Build Coastguard Worker inline uint128 operator~(const uint128& val) {
213*da0073e9SAndroid Build Coastguard Worker return uint128(~Uint128High64(val), ~Uint128Low64(val));
214*da0073e9SAndroid Build Coastguard Worker }
215*da0073e9SAndroid Build Coastguard Worker
216*da0073e9SAndroid Build Coastguard Worker #define LOGIC128(op) \
217*da0073e9SAndroid Build Coastguard Worker inline uint128 operator op(const uint128& lhs, const uint128& rhs) { \
218*da0073e9SAndroid Build Coastguard Worker return uint128( \
219*da0073e9SAndroid Build Coastguard Worker Uint128High64(lhs) op Uint128High64(rhs), \
220*da0073e9SAndroid Build Coastguard Worker Uint128Low64(lhs) op Uint128Low64(rhs)); \
221*da0073e9SAndroid Build Coastguard Worker }
222*da0073e9SAndroid Build Coastguard Worker
223*da0073e9SAndroid Build Coastguard Worker LOGIC128(|)
224*da0073e9SAndroid Build Coastguard Worker LOGIC128(&)
225*da0073e9SAndroid Build Coastguard Worker LOGIC128(^)
226*da0073e9SAndroid Build Coastguard Worker
227*da0073e9SAndroid Build Coastguard Worker #undef LOGIC128
228*da0073e9SAndroid Build Coastguard Worker
229*da0073e9SAndroid Build Coastguard Worker #define LOGICASSIGN128(op) \
230*da0073e9SAndroid Build Coastguard Worker C10_API inline uint128& uint128::operator op(const uint128 & other) { \
231*da0073e9SAndroid Build Coastguard Worker hi_ op other.hi_; \
232*da0073e9SAndroid Build Coastguard Worker lo_ op other.lo_; \
233*da0073e9SAndroid Build Coastguard Worker return *this; \
234*da0073e9SAndroid Build Coastguard Worker }
235*da0073e9SAndroid Build Coastguard Worker
236*da0073e9SAndroid Build Coastguard Worker LOGICASSIGN128(|=)
237*da0073e9SAndroid Build Coastguard Worker LOGICASSIGN128(&=)
238*da0073e9SAndroid Build Coastguard Worker LOGICASSIGN128(^=)
239*da0073e9SAndroid Build Coastguard Worker
240*da0073e9SAndroid Build Coastguard Worker #undef LOGICASSIGN128
241*da0073e9SAndroid Build Coastguard Worker
242*da0073e9SAndroid Build Coastguard Worker // Shift operators.
243*da0073e9SAndroid Build Coastguard Worker
244*da0073e9SAndroid Build Coastguard Worker inline uint128 operator<<(const uint128& val, int amount) {
245*da0073e9SAndroid Build Coastguard Worker // uint64_t shifts of >= 64 are undefined, so we will need some
246*da0073e9SAndroid Build Coastguard Worker // special-casing.
247*da0073e9SAndroid Build Coastguard Worker if (amount < 64) {
248*da0073e9SAndroid Build Coastguard Worker if (amount == 0) {
249*da0073e9SAndroid Build Coastguard Worker return val;
250*da0073e9SAndroid Build Coastguard Worker }
251*da0073e9SAndroid Build Coastguard Worker uint64_t new_hi =
252*da0073e9SAndroid Build Coastguard Worker (Uint128High64(val) << amount) | (Uint128Low64(val) >> (64 - amount));
253*da0073e9SAndroid Build Coastguard Worker uint64_t new_lo = Uint128Low64(val) << amount;
254*da0073e9SAndroid Build Coastguard Worker return uint128(new_hi, new_lo);
255*da0073e9SAndroid Build Coastguard Worker } else if (amount < 128) {
256*da0073e9SAndroid Build Coastguard Worker return uint128(Uint128Low64(val) << (amount - 64), 0);
257*da0073e9SAndroid Build Coastguard Worker } else {
258*da0073e9SAndroid Build Coastguard Worker return uint128(0, 0);
259*da0073e9SAndroid Build Coastguard Worker }
260*da0073e9SAndroid Build Coastguard Worker }
261*da0073e9SAndroid Build Coastguard Worker
262*da0073e9SAndroid Build Coastguard Worker inline uint128 operator>>(const uint128& val, int amount) {
263*da0073e9SAndroid Build Coastguard Worker // uint64_t shifts of >= 64 are undefined, so we will need some
264*da0073e9SAndroid Build Coastguard Worker // special-casing.
265*da0073e9SAndroid Build Coastguard Worker if (amount < 64) {
266*da0073e9SAndroid Build Coastguard Worker if (amount == 0) {
267*da0073e9SAndroid Build Coastguard Worker return val;
268*da0073e9SAndroid Build Coastguard Worker }
269*da0073e9SAndroid Build Coastguard Worker uint64_t new_hi = Uint128High64(val) >> amount;
270*da0073e9SAndroid Build Coastguard Worker uint64_t new_lo =
271*da0073e9SAndroid Build Coastguard Worker (Uint128Low64(val) >> amount) | (Uint128High64(val) << (64 - amount));
272*da0073e9SAndroid Build Coastguard Worker return uint128(new_hi, new_lo);
273*da0073e9SAndroid Build Coastguard Worker } else if (amount < 128) {
274*da0073e9SAndroid Build Coastguard Worker return uint128(0, Uint128High64(val) >> (amount - 64));
275*da0073e9SAndroid Build Coastguard Worker } else {
276*da0073e9SAndroid Build Coastguard Worker return uint128(0, 0);
277*da0073e9SAndroid Build Coastguard Worker }
278*da0073e9SAndroid Build Coastguard Worker }
279*da0073e9SAndroid Build Coastguard Worker
280*da0073e9SAndroid Build Coastguard Worker inline uint128& operator<<=(uint128& self, int amount) {
281*da0073e9SAndroid Build Coastguard Worker // uint64_t shifts of >= 64 are undefined, so we will need some
282*da0073e9SAndroid Build Coastguard Worker // special-casing.
283*da0073e9SAndroid Build Coastguard Worker if (amount < 64) {
284*da0073e9SAndroid Build Coastguard Worker if (amount != 0) {
285*da0073e9SAndroid Build Coastguard Worker self.hi_ = (self.hi_ << amount) | (self.lo_ >> (64 - amount));
286*da0073e9SAndroid Build Coastguard Worker self.lo_ = self.lo_ << amount;
287*da0073e9SAndroid Build Coastguard Worker }
288*da0073e9SAndroid Build Coastguard Worker } else if (amount < 128) {
289*da0073e9SAndroid Build Coastguard Worker self.hi_ = self.lo_ << (amount - 64);
290*da0073e9SAndroid Build Coastguard Worker self.lo_ = 0;
291*da0073e9SAndroid Build Coastguard Worker } else {
292*da0073e9SAndroid Build Coastguard Worker self.hi_ = 0;
293*da0073e9SAndroid Build Coastguard Worker self.lo_ = 0;
294*da0073e9SAndroid Build Coastguard Worker }
295*da0073e9SAndroid Build Coastguard Worker return self;
296*da0073e9SAndroid Build Coastguard Worker }
297*da0073e9SAndroid Build Coastguard Worker
298*da0073e9SAndroid Build Coastguard Worker C10_API inline uint128& uint128::operator>>=(int amount) {
299*da0073e9SAndroid Build Coastguard Worker // uint64_t shifts of >= 64 are undefined, so we will need some
300*da0073e9SAndroid Build Coastguard Worker // special-casing.
301*da0073e9SAndroid Build Coastguard Worker if (amount < 64) {
302*da0073e9SAndroid Build Coastguard Worker if (amount != 0) {
303*da0073e9SAndroid Build Coastguard Worker lo_ = (lo_ >> amount) | (hi_ << (64 - amount));
304*da0073e9SAndroid Build Coastguard Worker hi_ = hi_ >> amount;
305*da0073e9SAndroid Build Coastguard Worker }
306*da0073e9SAndroid Build Coastguard Worker } else if (amount < 128) {
307*da0073e9SAndroid Build Coastguard Worker lo_ = hi_ >> (amount - 64);
308*da0073e9SAndroid Build Coastguard Worker hi_ = 0;
309*da0073e9SAndroid Build Coastguard Worker } else {
310*da0073e9SAndroid Build Coastguard Worker lo_ = 0;
311*da0073e9SAndroid Build Coastguard Worker hi_ = 0;
312*da0073e9SAndroid Build Coastguard Worker }
313*da0073e9SAndroid Build Coastguard Worker return *this;
314*da0073e9SAndroid Build Coastguard Worker }
315*da0073e9SAndroid Build Coastguard Worker
316*da0073e9SAndroid Build Coastguard Worker inline uint128 operator+(const uint128& lhs, const uint128& rhs) {
317*da0073e9SAndroid Build Coastguard Worker return uint128(lhs) += rhs;
318*da0073e9SAndroid Build Coastguard Worker }
319*da0073e9SAndroid Build Coastguard Worker
320*da0073e9SAndroid Build Coastguard Worker inline uint128 operator-(const uint128& lhs, const uint128& rhs) {
321*da0073e9SAndroid Build Coastguard Worker return uint128(lhs) -= rhs;
322*da0073e9SAndroid Build Coastguard Worker }
323*da0073e9SAndroid Build Coastguard Worker
324*da0073e9SAndroid Build Coastguard Worker inline uint128 operator*(const uint128& lhs, const uint128& rhs) {
325*da0073e9SAndroid Build Coastguard Worker return uint128(lhs) *= rhs;
326*da0073e9SAndroid Build Coastguard Worker }
327*da0073e9SAndroid Build Coastguard Worker
328*da0073e9SAndroid Build Coastguard Worker inline uint128 operator/(const uint128& lhs, const uint128& rhs) {
329*da0073e9SAndroid Build Coastguard Worker return uint128(lhs) /= rhs;
330*da0073e9SAndroid Build Coastguard Worker }
331*da0073e9SAndroid Build Coastguard Worker
332*da0073e9SAndroid Build Coastguard Worker inline uint128 operator%(const uint128& lhs, const uint128& rhs) {
333*da0073e9SAndroid Build Coastguard Worker return uint128(lhs) %= rhs;
334*da0073e9SAndroid Build Coastguard Worker }
335*da0073e9SAndroid Build Coastguard Worker
336*da0073e9SAndroid Build Coastguard Worker C10_API inline uint128& uint128::operator+=(const uint128& b) {
337*da0073e9SAndroid Build Coastguard Worker hi_ += b.hi_;
338*da0073e9SAndroid Build Coastguard Worker uint64_t lolo = lo_ + b.lo_;
339*da0073e9SAndroid Build Coastguard Worker if (lolo < lo_)
340*da0073e9SAndroid Build Coastguard Worker ++hi_;
341*da0073e9SAndroid Build Coastguard Worker lo_ = lolo;
342*da0073e9SAndroid Build Coastguard Worker return *this;
343*da0073e9SAndroid Build Coastguard Worker }
344*da0073e9SAndroid Build Coastguard Worker
345*da0073e9SAndroid Build Coastguard Worker C10_API inline uint128& uint128::operator-=(const uint128& b) {
346*da0073e9SAndroid Build Coastguard Worker hi_ -= b.hi_;
347*da0073e9SAndroid Build Coastguard Worker if (b.lo_ > lo_)
348*da0073e9SAndroid Build Coastguard Worker --hi_;
349*da0073e9SAndroid Build Coastguard Worker lo_ -= b.lo_;
350*da0073e9SAndroid Build Coastguard Worker return *this;
351*da0073e9SAndroid Build Coastguard Worker }
352*da0073e9SAndroid Build Coastguard Worker
353*da0073e9SAndroid Build Coastguard Worker C10_API inline uint128& uint128::operator*=(const uint128& b) {
354*da0073e9SAndroid Build Coastguard Worker uint64_t a96 = hi_ >> 32;
355*da0073e9SAndroid Build Coastguard Worker uint64_t a64 = hi_ & 0xffffffffu;
356*da0073e9SAndroid Build Coastguard Worker uint64_t a32 = lo_ >> 32;
357*da0073e9SAndroid Build Coastguard Worker uint64_t a00 = lo_ & 0xffffffffu;
358*da0073e9SAndroid Build Coastguard Worker uint64_t b96 = b.hi_ >> 32;
359*da0073e9SAndroid Build Coastguard Worker uint64_t b64 = b.hi_ & 0xffffffffu;
360*da0073e9SAndroid Build Coastguard Worker uint64_t b32 = b.lo_ >> 32;
361*da0073e9SAndroid Build Coastguard Worker uint64_t b00 = b.lo_ & 0xffffffffu;
362*da0073e9SAndroid Build Coastguard Worker // multiply [a96 .. a00] x [b96 .. b00]
363*da0073e9SAndroid Build Coastguard Worker // terms higher than c96 disappear off the high side
364*da0073e9SAndroid Build Coastguard Worker // terms c96 and c64 are safe to ignore carry bit
365*da0073e9SAndroid Build Coastguard Worker uint64_t c96 = a96 * b00 + a64 * b32 + a32 * b64 + a00 * b96;
366*da0073e9SAndroid Build Coastguard Worker uint64_t c64 = a64 * b00 + a32 * b32 + a00 * b64;
367*da0073e9SAndroid Build Coastguard Worker this->hi_ = (c96 << 32) + c64;
368*da0073e9SAndroid Build Coastguard Worker this->lo_ = 0;
369*da0073e9SAndroid Build Coastguard Worker // add terms after this one at a time to capture carry
370*da0073e9SAndroid Build Coastguard Worker *this += uint128(a32 * b00) << 32;
371*da0073e9SAndroid Build Coastguard Worker *this += uint128(a00 * b32) << 32;
372*da0073e9SAndroid Build Coastguard Worker *this += a00 * b00;
373*da0073e9SAndroid Build Coastguard Worker return *this;
374*da0073e9SAndroid Build Coastguard Worker }
375*da0073e9SAndroid Build Coastguard Worker
376*da0073e9SAndroid Build Coastguard Worker C10_API inline uint128 uint128::operator++(int) {
377*da0073e9SAndroid Build Coastguard Worker uint128 tmp(*this);
378*da0073e9SAndroid Build Coastguard Worker *this += 1;
379*da0073e9SAndroid Build Coastguard Worker return tmp;
380*da0073e9SAndroid Build Coastguard Worker }
381*da0073e9SAndroid Build Coastguard Worker
382*da0073e9SAndroid Build Coastguard Worker C10_API inline uint128 uint128::operator--(int) {
383*da0073e9SAndroid Build Coastguard Worker uint128 tmp(*this);
384*da0073e9SAndroid Build Coastguard Worker *this -= 1;
385*da0073e9SAndroid Build Coastguard Worker return tmp;
386*da0073e9SAndroid Build Coastguard Worker }
387*da0073e9SAndroid Build Coastguard Worker
388*da0073e9SAndroid Build Coastguard Worker C10_API inline uint128& uint128::operator++() {
389*da0073e9SAndroid Build Coastguard Worker *this += 1;
390*da0073e9SAndroid Build Coastguard Worker return *this;
391*da0073e9SAndroid Build Coastguard Worker }
392*da0073e9SAndroid Build Coastguard Worker
393*da0073e9SAndroid Build Coastguard Worker C10_API inline uint128& uint128::operator--() {
394*da0073e9SAndroid Build Coastguard Worker *this -= 1;
395*da0073e9SAndroid Build Coastguard Worker return *this;
396*da0073e9SAndroid Build Coastguard Worker }
397*da0073e9SAndroid Build Coastguard Worker
398*da0073e9SAndroid Build Coastguard Worker } // namespace c10
399