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


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:06