int128.h 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162
  1. //
  2. // Copyright 2017 The Abseil Authors.
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // https://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. //
  16. // -----------------------------------------------------------------------------
  17. // File: int128.h
  18. // -----------------------------------------------------------------------------
  19. //
  20. // This header file defines 128-bit integer types, `uint128` and `int128`.
  21. //
  22. // TODO(y_absl-team): This module is inconsistent as many inline `uint128` methods
  23. // are defined in this file, while many inline `int128` methods are defined in
  24. // the `int128_*_intrinsic.inc` files.
  25. #ifndef Y_ABSL_NUMERIC_INT128_H_
  26. #define Y_ABSL_NUMERIC_INT128_H_
  27. #include <cassert>
  28. #include <cmath>
  29. #include <cstdint>
  30. #include <cstring>
  31. #include <iosfwd>
  32. #include <limits>
  33. #include <util/generic/string.h>
  34. #include <utility>
  35. #include "y_absl/base/config.h"
  36. #include "y_absl/base/macros.h"
  37. #include "y_absl/base/port.h"
  38. #if defined(_MSC_VER)
  39. // In very old versions of MSVC and when the /Zc:wchar_t flag is off, wchar_t is
  40. // a typedef for unsigned short. Otherwise wchar_t is mapped to the __wchar_t
  41. // builtin type. We need to make sure not to define operator wchar_t()
  42. // alongside operator unsigned short() in these instances.
  43. #define Y_ABSL_INTERNAL_WCHAR_T __wchar_t
  44. #if defined(_M_X64) && !defined(_M_ARM64EC)
  45. #include <intrin.h>
  46. #pragma intrinsic(_umul128)
  47. #endif // defined(_M_X64)
  48. #else // defined(_MSC_VER)
  49. #define Y_ABSL_INTERNAL_WCHAR_T wchar_t
  50. #endif // defined(_MSC_VER)
  51. namespace y_absl {
  52. Y_ABSL_NAMESPACE_BEGIN
  53. class int128;
  54. // uint128
  55. //
  56. // An unsigned 128-bit integer type. The API is meant to mimic an intrinsic type
  57. // as closely as is practical, including exhibiting undefined behavior in
  58. // analogous cases (e.g. division by zero). This type is intended to be a
  59. // drop-in replacement once C++ supports an intrinsic `uint128_t` type; when
  60. // that occurs, existing well-behaved uses of `uint128` will continue to work
  61. // using that new type.
  62. //
  63. // Note: code written with this type will continue to compile once `uint128_t`
  64. // is introduced, provided the replacement helper functions
  65. // `Uint128(Low|High)64()` and `MakeUint128()` are made.
  66. //
  67. // A `uint128` supports the following:
  68. //
  69. // * Implicit construction from integral types
  70. // * Explicit conversion to integral types
  71. //
  72. // Additionally, if your compiler supports `__int128`, `uint128` is
  73. // interoperable with that type. (Abseil checks for this compatibility through
  74. // the `Y_ABSL_HAVE_INTRINSIC_INT128` macro.)
  75. //
  76. // However, a `uint128` differs from intrinsic integral types in the following
  77. // ways:
  78. //
  79. // * Errors on implicit conversions that do not preserve value (such as
  80. // loss of precision when converting to float values).
  81. // * Requires explicit construction from and conversion to floating point
  82. // types.
  83. // * Conversion to integral types requires an explicit static_cast() to
  84. // mimic use of the `-Wnarrowing` compiler flag.
  85. // * The alignment requirement of `uint128` may differ from that of an
  86. // intrinsic 128-bit integer type depending on platform and build
  87. // configuration.
  88. //
  89. // Example:
  90. //
  91. // float y = y_absl::Uint128Max(); // Error. uint128 cannot be implicitly
  92. // // converted to float.
  93. //
  94. // y_absl::uint128 v;
  95. // uint64_t i = v; // Error
  96. // uint64_t i = static_cast<uint64_t>(v); // OK
  97. //
  98. class
  99. #if defined(Y_ABSL_HAVE_INTRINSIC_INT128)
  100. alignas(unsigned __int128)
  101. #endif // Y_ABSL_HAVE_INTRINSIC_INT128
  102. uint128 {
  103. public:
  104. uint128() = default;
  105. // Constructors from arithmetic types
  106. constexpr uint128(int v); // NOLINT(runtime/explicit)
  107. constexpr uint128(unsigned int v); // NOLINT(runtime/explicit)
  108. constexpr uint128(long v); // NOLINT(runtime/int)
  109. constexpr uint128(unsigned long v); // NOLINT(runtime/int)
  110. constexpr uint128(long long v); // NOLINT(runtime/int)
  111. constexpr uint128(unsigned long long v); // NOLINT(runtime/int)
  112. #ifdef Y_ABSL_HAVE_INTRINSIC_INT128
  113. constexpr uint128(__int128 v); // NOLINT(runtime/explicit)
  114. constexpr uint128(unsigned __int128 v); // NOLINT(runtime/explicit)
  115. #endif // Y_ABSL_HAVE_INTRINSIC_INT128
  116. constexpr uint128(int128 v); // NOLINT(runtime/explicit)
  117. explicit uint128(float v);
  118. explicit uint128(double v);
  119. explicit uint128(long double v);
  120. // Assignment operators from arithmetic types
  121. uint128& operator=(int v);
  122. uint128& operator=(unsigned int v);
  123. uint128& operator=(long v); // NOLINT(runtime/int)
  124. uint128& operator=(unsigned long v); // NOLINT(runtime/int)
  125. uint128& operator=(long long v); // NOLINT(runtime/int)
  126. uint128& operator=(unsigned long long v); // NOLINT(runtime/int)
  127. #ifdef Y_ABSL_HAVE_INTRINSIC_INT128
  128. uint128& operator=(__int128 v);
  129. uint128& operator=(unsigned __int128 v);
  130. #endif // Y_ABSL_HAVE_INTRINSIC_INT128
  131. uint128& operator=(int128 v);
  132. // Conversion operators to other arithmetic types
  133. constexpr explicit operator bool() const;
  134. constexpr explicit operator char() const;
  135. constexpr explicit operator signed char() const;
  136. constexpr explicit operator unsigned char() const;
  137. constexpr explicit operator char16_t() const;
  138. constexpr explicit operator char32_t() const;
  139. constexpr explicit operator Y_ABSL_INTERNAL_WCHAR_T() const;
  140. constexpr explicit operator short() const; // NOLINT(runtime/int)
  141. // NOLINTNEXTLINE(runtime/int)
  142. constexpr explicit operator unsigned short() const;
  143. constexpr explicit operator int() const;
  144. constexpr explicit operator unsigned int() const;
  145. constexpr explicit operator long() const; // NOLINT(runtime/int)
  146. // NOLINTNEXTLINE(runtime/int)
  147. constexpr explicit operator unsigned long() const;
  148. // NOLINTNEXTLINE(runtime/int)
  149. constexpr explicit operator long long() const;
  150. // NOLINTNEXTLINE(runtime/int)
  151. constexpr explicit operator unsigned long long() const;
  152. #ifdef Y_ABSL_HAVE_INTRINSIC_INT128
  153. constexpr explicit operator __int128() const;
  154. constexpr explicit operator unsigned __int128() const;
  155. #endif // Y_ABSL_HAVE_INTRINSIC_INT128
  156. explicit operator float() const;
  157. explicit operator double() const;
  158. explicit operator long double() const;
  159. // Trivial copy constructor, assignment operator and destructor.
  160. // Arithmetic operators.
  161. uint128& operator+=(uint128 other);
  162. uint128& operator-=(uint128 other);
  163. uint128& operator*=(uint128 other);
  164. // Long division/modulo for uint128.
  165. uint128& operator/=(uint128 other);
  166. uint128& operator%=(uint128 other);
  167. uint128 operator++(int);
  168. uint128 operator--(int);
  169. uint128& operator<<=(int);
  170. uint128& operator>>=(int);
  171. uint128& operator&=(uint128 other);
  172. uint128& operator|=(uint128 other);
  173. uint128& operator^=(uint128 other);
  174. uint128& operator++();
  175. uint128& operator--();
  176. // Uint128Low64()
  177. //
  178. // Returns the lower 64-bit value of a `uint128` value.
  179. friend constexpr uint64_t Uint128Low64(uint128 v);
  180. // Uint128High64()
  181. //
  182. // Returns the higher 64-bit value of a `uint128` value.
  183. friend constexpr uint64_t Uint128High64(uint128 v);
  184. // MakeUInt128()
  185. //
  186. // Constructs a `uint128` numeric value from two 64-bit unsigned integers.
  187. // Note that this factory function is the only way to construct a `uint128`
  188. // from integer values greater than 2^64.
  189. //
  190. // Example:
  191. //
  192. // y_absl::uint128 big = y_absl::MakeUint128(1, 0);
  193. friend constexpr uint128 MakeUint128(uint64_t high, uint64_t low);
  194. // Uint128Max()
  195. //
  196. // Returns the highest value for a 128-bit unsigned integer.
  197. friend constexpr uint128 Uint128Max();
  198. // Support for y_absl::Hash.
  199. template <typename H>
  200. friend H AbslHashValue(H h, uint128 v) {
  201. return H::combine(std::move(h), Uint128High64(v), Uint128Low64(v));
  202. }
  203. // Support for y_absl::StrCat() etc.
  204. template <typename Sink>
  205. friend void AbslStringify(Sink& sink, uint128 v) {
  206. sink.Append(v.ToString());
  207. }
  208. private:
  209. constexpr uint128(uint64_t high, uint64_t low);
  210. TString ToString() const;
  211. // TODO(strel) Update implementation to use __int128 once all users of
  212. // uint128 are fixed to not depend on alignof(uint128) == 8. Also add
  213. // alignas(16) to class definition to keep alignment consistent across
  214. // platforms.
  215. #if defined(Y_ABSL_IS_LITTLE_ENDIAN)
  216. uint64_t lo_;
  217. uint64_t hi_;
  218. #elif defined(Y_ABSL_IS_BIG_ENDIAN)
  219. uint64_t hi_;
  220. uint64_t lo_;
  221. #else // byte order
  222. #error "Unsupported byte order: must be little-endian or big-endian."
  223. #endif // byte order
  224. };
  225. // Prefer to use the constexpr `Uint128Max()`.
  226. //
  227. // TODO(y_absl-team) deprecate kuint128max once migration tool is released.
  228. Y_ABSL_DLL extern const uint128 kuint128max;
  229. // allow uint128 to be logged
  230. std::ostream& operator<<(std::ostream& os, uint128 v);
  231. // TODO(strel) add operator>>(std::istream&, uint128)
  232. constexpr uint128 Uint128Max() {
  233. return uint128((std::numeric_limits<uint64_t>::max)(),
  234. (std::numeric_limits<uint64_t>::max)());
  235. }
  236. Y_ABSL_NAMESPACE_END
  237. } // namespace y_absl
  238. // Specialized numeric_limits for uint128.
  239. namespace std {
  240. template <>
  241. class numeric_limits<y_absl::uint128> {
  242. public:
  243. static constexpr bool is_specialized = true;
  244. static constexpr bool is_signed = false;
  245. static constexpr bool is_integer = true;
  246. static constexpr bool is_exact = true;
  247. static constexpr bool has_infinity = false;
  248. static constexpr bool has_quiet_NaN = false;
  249. static constexpr bool has_signaling_NaN = false;
  250. static constexpr float_denorm_style has_denorm = denorm_absent;
  251. static constexpr bool has_denorm_loss = false;
  252. static constexpr float_round_style round_style = round_toward_zero;
  253. static constexpr bool is_iec559 = false;
  254. static constexpr bool is_bounded = true;
  255. static constexpr bool is_modulo = true;
  256. static constexpr int digits = 128;
  257. static constexpr int digits10 = 38;
  258. static constexpr int max_digits10 = 0;
  259. static constexpr int radix = 2;
  260. static constexpr int min_exponent = 0;
  261. static constexpr int min_exponent10 = 0;
  262. static constexpr int max_exponent = 0;
  263. static constexpr int max_exponent10 = 0;
  264. #ifdef Y_ABSL_HAVE_INTRINSIC_INT128
  265. static constexpr bool traps = numeric_limits<unsigned __int128>::traps;
  266. #else // Y_ABSL_HAVE_INTRINSIC_INT128
  267. static constexpr bool traps = numeric_limits<uint64_t>::traps;
  268. #endif // Y_ABSL_HAVE_INTRINSIC_INT128
  269. static constexpr bool tinyness_before = false;
  270. static constexpr y_absl::uint128(min)() { return 0; }
  271. static constexpr y_absl::uint128 lowest() { return 0; }
  272. static constexpr y_absl::uint128(max)() { return y_absl::Uint128Max(); }
  273. static constexpr y_absl::uint128 epsilon() { return 0; }
  274. static constexpr y_absl::uint128 round_error() { return 0; }
  275. static constexpr y_absl::uint128 infinity() { return 0; }
  276. static constexpr y_absl::uint128 quiet_NaN() { return 0; }
  277. static constexpr y_absl::uint128 signaling_NaN() { return 0; }
  278. static constexpr y_absl::uint128 denorm_min() { return 0; }
  279. };
  280. } // namespace std
  281. namespace y_absl {
  282. Y_ABSL_NAMESPACE_BEGIN
  283. // int128
  284. //
  285. // A signed 128-bit integer type. The API is meant to mimic an intrinsic
  286. // integral type as closely as is practical, including exhibiting undefined
  287. // behavior in analogous cases (e.g. division by zero).
  288. //
  289. // An `int128` supports the following:
  290. //
  291. // * Implicit construction from integral types
  292. // * Explicit conversion to integral types
  293. //
  294. // However, an `int128` differs from intrinsic integral types in the following
  295. // ways:
  296. //
  297. // * It is not implicitly convertible to other integral types.
  298. // * Requires explicit construction from and conversion to floating point
  299. // types.
  300. // Additionally, if your compiler supports `__int128`, `int128` is
  301. // interoperable with that type. (Abseil checks for this compatibility through
  302. // the `Y_ABSL_HAVE_INTRINSIC_INT128` macro.)
  303. //
  304. // The design goal for `int128` is that it will be compatible with a future
  305. // `int128_t`, if that type becomes a part of the standard.
  306. //
  307. // Example:
  308. //
  309. // float y = y_absl::int128(17); // Error. int128 cannot be implicitly
  310. // // converted to float.
  311. //
  312. // y_absl::int128 v;
  313. // int64_t i = v; // Error
  314. // int64_t i = static_cast<int64_t>(v); // OK
  315. //
  316. class int128 {
  317. public:
  318. int128() = default;
  319. // Constructors from arithmetic types
  320. constexpr int128(int v); // NOLINT(runtime/explicit)
  321. constexpr int128(unsigned int v); // NOLINT(runtime/explicit)
  322. constexpr int128(long v); // NOLINT(runtime/int)
  323. constexpr int128(unsigned long v); // NOLINT(runtime/int)
  324. constexpr int128(long long v); // NOLINT(runtime/int)
  325. constexpr int128(unsigned long long v); // NOLINT(runtime/int)
  326. #ifdef Y_ABSL_HAVE_INTRINSIC_INT128
  327. constexpr int128(__int128 v); // NOLINT(runtime/explicit)
  328. constexpr explicit int128(unsigned __int128 v);
  329. #endif // Y_ABSL_HAVE_INTRINSIC_INT128
  330. constexpr explicit int128(uint128 v);
  331. explicit int128(float v);
  332. explicit int128(double v);
  333. explicit int128(long double v);
  334. // Assignment operators from arithmetic types
  335. int128& operator=(int v);
  336. int128& operator=(unsigned int v);
  337. int128& operator=(long v); // NOLINT(runtime/int)
  338. int128& operator=(unsigned long v); // NOLINT(runtime/int)
  339. int128& operator=(long long v); // NOLINT(runtime/int)
  340. int128& operator=(unsigned long long v); // NOLINT(runtime/int)
  341. #ifdef Y_ABSL_HAVE_INTRINSIC_INT128
  342. int128& operator=(__int128 v);
  343. #endif // Y_ABSL_HAVE_INTRINSIC_INT128
  344. // Conversion operators to other arithmetic types
  345. constexpr explicit operator bool() const;
  346. constexpr explicit operator char() const;
  347. constexpr explicit operator signed char() const;
  348. constexpr explicit operator unsigned char() const;
  349. constexpr explicit operator char16_t() const;
  350. constexpr explicit operator char32_t() const;
  351. constexpr explicit operator Y_ABSL_INTERNAL_WCHAR_T() const;
  352. constexpr explicit operator short() const; // NOLINT(runtime/int)
  353. // NOLINTNEXTLINE(runtime/int)
  354. constexpr explicit operator unsigned short() const;
  355. constexpr explicit operator int() const;
  356. constexpr explicit operator unsigned int() const;
  357. constexpr explicit operator long() const; // NOLINT(runtime/int)
  358. // NOLINTNEXTLINE(runtime/int)
  359. constexpr explicit operator unsigned long() const;
  360. // NOLINTNEXTLINE(runtime/int)
  361. constexpr explicit operator long long() const;
  362. // NOLINTNEXTLINE(runtime/int)
  363. constexpr explicit operator unsigned long long() const;
  364. #ifdef Y_ABSL_HAVE_INTRINSIC_INT128
  365. constexpr explicit operator __int128() const;
  366. constexpr explicit operator unsigned __int128() const;
  367. #endif // Y_ABSL_HAVE_INTRINSIC_INT128
  368. explicit operator float() const;
  369. explicit operator double() const;
  370. explicit operator long double() const;
  371. // Trivial copy constructor, assignment operator and destructor.
  372. // Arithmetic operators
  373. int128& operator+=(int128 other);
  374. int128& operator-=(int128 other);
  375. int128& operator*=(int128 other);
  376. int128& operator/=(int128 other);
  377. int128& operator%=(int128 other);
  378. int128 operator++(int); // postfix increment: i++
  379. int128 operator--(int); // postfix decrement: i--
  380. int128& operator++(); // prefix increment: ++i
  381. int128& operator--(); // prefix decrement: --i
  382. int128& operator&=(int128 other);
  383. int128& operator|=(int128 other);
  384. int128& operator^=(int128 other);
  385. int128& operator<<=(int amount);
  386. int128& operator>>=(int amount);
  387. // Int128Low64()
  388. //
  389. // Returns the lower 64-bit value of a `int128` value.
  390. friend constexpr uint64_t Int128Low64(int128 v);
  391. // Int128High64()
  392. //
  393. // Returns the higher 64-bit value of a `int128` value.
  394. friend constexpr int64_t Int128High64(int128 v);
  395. // MakeInt128()
  396. //
  397. // Constructs a `int128` numeric value from two 64-bit integers. Note that
  398. // signedness is conveyed in the upper `high` value.
  399. //
  400. // (y_absl::int128(1) << 64) * high + low
  401. //
  402. // Note that this factory function is the only way to construct a `int128`
  403. // from integer values greater than 2^64 or less than -2^64.
  404. //
  405. // Example:
  406. //
  407. // y_absl::int128 big = y_absl::MakeInt128(1, 0);
  408. // y_absl::int128 big_n = y_absl::MakeInt128(-1, 0);
  409. friend constexpr int128 MakeInt128(int64_t high, uint64_t low);
  410. // Int128Max()
  411. //
  412. // Returns the maximum value for a 128-bit signed integer.
  413. friend constexpr int128 Int128Max();
  414. // Int128Min()
  415. //
  416. // Returns the minimum value for a 128-bit signed integer.
  417. friend constexpr int128 Int128Min();
  418. // Support for y_absl::Hash.
  419. template <typename H>
  420. friend H AbslHashValue(H h, int128 v) {
  421. return H::combine(std::move(h), Int128High64(v), Int128Low64(v));
  422. }
  423. // Support for y_absl::StrCat() etc.
  424. template <typename Sink>
  425. friend void AbslStringify(Sink& sink, int128 v) {
  426. sink.Append(v.ToString());
  427. }
  428. private:
  429. constexpr int128(int64_t high, uint64_t low);
  430. TString ToString() const;
  431. #if defined(Y_ABSL_HAVE_INTRINSIC_INT128)
  432. __int128 v_;
  433. #else // Y_ABSL_HAVE_INTRINSIC_INT128
  434. #if defined(Y_ABSL_IS_LITTLE_ENDIAN)
  435. uint64_t lo_;
  436. int64_t hi_;
  437. #elif defined(Y_ABSL_IS_BIG_ENDIAN)
  438. int64_t hi_;
  439. uint64_t lo_;
  440. #else // byte order
  441. #error "Unsupported byte order: must be little-endian or big-endian."
  442. #endif // byte order
  443. #endif // Y_ABSL_HAVE_INTRINSIC_INT128
  444. };
  445. std::ostream& operator<<(std::ostream& os, int128 v);
  446. // TODO(y_absl-team) add operator>>(std::istream&, int128)
  447. constexpr int128 Int128Max() {
  448. return int128((std::numeric_limits<int64_t>::max)(),
  449. (std::numeric_limits<uint64_t>::max)());
  450. }
  451. constexpr int128 Int128Min() {
  452. return int128((std::numeric_limits<int64_t>::min)(), 0);
  453. }
  454. Y_ABSL_NAMESPACE_END
  455. } // namespace y_absl
  456. // Specialized numeric_limits for int128.
  457. namespace std {
  458. template <>
  459. class numeric_limits<y_absl::int128> {
  460. public:
  461. static constexpr bool is_specialized = true;
  462. static constexpr bool is_signed = true;
  463. static constexpr bool is_integer = true;
  464. static constexpr bool is_exact = true;
  465. static constexpr bool has_infinity = false;
  466. static constexpr bool has_quiet_NaN = false;
  467. static constexpr bool has_signaling_NaN = false;
  468. static constexpr float_denorm_style has_denorm = denorm_absent;
  469. static constexpr bool has_denorm_loss = false;
  470. static constexpr float_round_style round_style = round_toward_zero;
  471. static constexpr bool is_iec559 = false;
  472. static constexpr bool is_bounded = true;
  473. static constexpr bool is_modulo = false;
  474. static constexpr int digits = 127;
  475. static constexpr int digits10 = 38;
  476. static constexpr int max_digits10 = 0;
  477. static constexpr int radix = 2;
  478. static constexpr int min_exponent = 0;
  479. static constexpr int min_exponent10 = 0;
  480. static constexpr int max_exponent = 0;
  481. static constexpr int max_exponent10 = 0;
  482. #ifdef Y_ABSL_HAVE_INTRINSIC_INT128
  483. static constexpr bool traps = numeric_limits<__int128>::traps;
  484. #else // Y_ABSL_HAVE_INTRINSIC_INT128
  485. static constexpr bool traps = numeric_limits<uint64_t>::traps;
  486. #endif // Y_ABSL_HAVE_INTRINSIC_INT128
  487. static constexpr bool tinyness_before = false;
  488. static constexpr y_absl::int128(min)() { return y_absl::Int128Min(); }
  489. static constexpr y_absl::int128 lowest() { return y_absl::Int128Min(); }
  490. static constexpr y_absl::int128(max)() { return y_absl::Int128Max(); }
  491. static constexpr y_absl::int128 epsilon() { return 0; }
  492. static constexpr y_absl::int128 round_error() { return 0; }
  493. static constexpr y_absl::int128 infinity() { return 0; }
  494. static constexpr y_absl::int128 quiet_NaN() { return 0; }
  495. static constexpr y_absl::int128 signaling_NaN() { return 0; }
  496. static constexpr y_absl::int128 denorm_min() { return 0; }
  497. };
  498. } // namespace std
  499. // --------------------------------------------------------------------------
  500. // Implementation details follow
  501. // --------------------------------------------------------------------------
  502. namespace y_absl {
  503. Y_ABSL_NAMESPACE_BEGIN
  504. constexpr uint128 MakeUint128(uint64_t high, uint64_t low) {
  505. return uint128(high, low);
  506. }
  507. // Assignment from integer types.
  508. inline uint128& uint128::operator=(int v) { return *this = uint128(v); }
  509. inline uint128& uint128::operator=(unsigned int v) {
  510. return *this = uint128(v);
  511. }
  512. inline uint128& uint128::operator=(long v) { // NOLINT(runtime/int)
  513. return *this = uint128(v);
  514. }
  515. // NOLINTNEXTLINE(runtime/int)
  516. inline uint128& uint128::operator=(unsigned long v) {
  517. return *this = uint128(v);
  518. }
  519. // NOLINTNEXTLINE(runtime/int)
  520. inline uint128& uint128::operator=(long long v) { return *this = uint128(v); }
  521. // NOLINTNEXTLINE(runtime/int)
  522. inline uint128& uint128::operator=(unsigned long long v) {
  523. return *this = uint128(v);
  524. }
  525. #ifdef Y_ABSL_HAVE_INTRINSIC_INT128
  526. inline uint128& uint128::operator=(__int128 v) { return *this = uint128(v); }
  527. inline uint128& uint128::operator=(unsigned __int128 v) {
  528. return *this = uint128(v);
  529. }
  530. #endif // Y_ABSL_HAVE_INTRINSIC_INT128
  531. inline uint128& uint128::operator=(int128 v) { return *this = uint128(v); }
  532. // Arithmetic operators.
  533. constexpr uint128 operator<<(uint128 lhs, int amount);
  534. constexpr uint128 operator>>(uint128 lhs, int amount);
  535. constexpr uint128 operator+(uint128 lhs, uint128 rhs);
  536. constexpr uint128 operator-(uint128 lhs, uint128 rhs);
  537. uint128 operator*(uint128 lhs, uint128 rhs);
  538. uint128 operator/(uint128 lhs, uint128 rhs);
  539. uint128 operator%(uint128 lhs, uint128 rhs);
  540. inline uint128& uint128::operator<<=(int amount) {
  541. *this = *this << amount;
  542. return *this;
  543. }
  544. inline uint128& uint128::operator>>=(int amount) {
  545. *this = *this >> amount;
  546. return *this;
  547. }
  548. inline uint128& uint128::operator+=(uint128 other) {
  549. *this = *this + other;
  550. return *this;
  551. }
  552. inline uint128& uint128::operator-=(uint128 other) {
  553. *this = *this - other;
  554. return *this;
  555. }
  556. inline uint128& uint128::operator*=(uint128 other) {
  557. *this = *this * other;
  558. return *this;
  559. }
  560. inline uint128& uint128::operator/=(uint128 other) {
  561. *this = *this / other;
  562. return *this;
  563. }
  564. inline uint128& uint128::operator%=(uint128 other) {
  565. *this = *this % other;
  566. return *this;
  567. }
  568. constexpr uint64_t Uint128Low64(uint128 v) { return v.lo_; }
  569. constexpr uint64_t Uint128High64(uint128 v) { return v.hi_; }
  570. // Constructors from integer types.
  571. #if defined(Y_ABSL_IS_LITTLE_ENDIAN)
  572. constexpr uint128::uint128(uint64_t high, uint64_t low) : lo_{low}, hi_{high} {}
  573. constexpr uint128::uint128(int v)
  574. : lo_{static_cast<uint64_t>(v)},
  575. hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}
  576. constexpr uint128::uint128(long v) // NOLINT(runtime/int)
  577. : lo_{static_cast<uint64_t>(v)},
  578. hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}
  579. constexpr uint128::uint128(long long v) // NOLINT(runtime/int)
  580. : lo_{static_cast<uint64_t>(v)},
  581. hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}
  582. constexpr uint128::uint128(unsigned int v) : lo_{v}, hi_{0} {}
  583. // NOLINTNEXTLINE(runtime/int)
  584. constexpr uint128::uint128(unsigned long v) : lo_{v}, hi_{0} {}
  585. // NOLINTNEXTLINE(runtime/int)
  586. constexpr uint128::uint128(unsigned long long v) : lo_{v}, hi_{0} {}
  587. #ifdef Y_ABSL_HAVE_INTRINSIC_INT128
  588. constexpr uint128::uint128(__int128 v)
  589. : lo_{static_cast<uint64_t>(v & ~uint64_t{0})},
  590. hi_{static_cast<uint64_t>(static_cast<unsigned __int128>(v) >> 64)} {}
  591. constexpr uint128::uint128(unsigned __int128 v)
  592. : lo_{static_cast<uint64_t>(v & ~uint64_t{0})},
  593. hi_{static_cast<uint64_t>(v >> 64)} {}
  594. #endif // Y_ABSL_HAVE_INTRINSIC_INT128
  595. constexpr uint128::uint128(int128 v)
  596. : lo_{Int128Low64(v)}, hi_{static_cast<uint64_t>(Int128High64(v))} {}
  597. #elif defined(Y_ABSL_IS_BIG_ENDIAN)
  598. constexpr uint128::uint128(uint64_t high, uint64_t low) : hi_{high}, lo_{low} {}
  599. constexpr uint128::uint128(int v)
  600. : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},
  601. lo_{static_cast<uint64_t>(v)} {}
  602. constexpr uint128::uint128(long v) // NOLINT(runtime/int)
  603. : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},
  604. lo_{static_cast<uint64_t>(v)} {}
  605. constexpr uint128::uint128(long long v) // NOLINT(runtime/int)
  606. : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},
  607. lo_{static_cast<uint64_t>(v)} {}
  608. constexpr uint128::uint128(unsigned int v) : hi_{0}, lo_{v} {}
  609. // NOLINTNEXTLINE(runtime/int)
  610. constexpr uint128::uint128(unsigned long v) : hi_{0}, lo_{v} {}
  611. // NOLINTNEXTLINE(runtime/int)
  612. constexpr uint128::uint128(unsigned long long v) : hi_{0}, lo_{v} {}
  613. #ifdef Y_ABSL_HAVE_INTRINSIC_INT128
  614. constexpr uint128::uint128(__int128 v)
  615. : hi_{static_cast<uint64_t>(static_cast<unsigned __int128>(v) >> 64)},
  616. lo_{static_cast<uint64_t>(v & ~uint64_t{0})} {}
  617. constexpr uint128::uint128(unsigned __int128 v)
  618. : hi_{static_cast<uint64_t>(v >> 64)},
  619. lo_{static_cast<uint64_t>(v & ~uint64_t{0})} {}
  620. #endif // Y_ABSL_HAVE_INTRINSIC_INT128
  621. constexpr uint128::uint128(int128 v)
  622. : hi_{static_cast<uint64_t>(Int128High64(v))}, lo_{Int128Low64(v)} {}
  623. #else // byte order
  624. #error "Unsupported byte order: must be little-endian or big-endian."
  625. #endif // byte order
  626. // Conversion operators to integer types.
  627. constexpr uint128::operator bool() const { return lo_ || hi_; }
  628. constexpr uint128::operator char() const { return static_cast<char>(lo_); }
  629. constexpr uint128::operator signed char() const {
  630. return static_cast<signed char>(lo_);
  631. }
  632. constexpr uint128::operator unsigned char() const {
  633. return static_cast<unsigned char>(lo_);
  634. }
  635. constexpr uint128::operator char16_t() const {
  636. return static_cast<char16_t>(lo_);
  637. }
  638. constexpr uint128::operator char32_t() const {
  639. return static_cast<char32_t>(lo_);
  640. }
  641. constexpr uint128::operator Y_ABSL_INTERNAL_WCHAR_T() const {
  642. return static_cast<Y_ABSL_INTERNAL_WCHAR_T>(lo_);
  643. }
  644. // NOLINTNEXTLINE(runtime/int)
  645. constexpr uint128::operator short() const { return static_cast<short>(lo_); }
  646. constexpr uint128::operator unsigned short() const { // NOLINT(runtime/int)
  647. return static_cast<unsigned short>(lo_); // NOLINT(runtime/int)
  648. }
  649. constexpr uint128::operator int() const { return static_cast<int>(lo_); }
  650. constexpr uint128::operator unsigned int() const {
  651. return static_cast<unsigned int>(lo_);
  652. }
  653. // NOLINTNEXTLINE(runtime/int)
  654. constexpr uint128::operator long() const { return static_cast<long>(lo_); }
  655. constexpr uint128::operator unsigned long() const { // NOLINT(runtime/int)
  656. return static_cast<unsigned long>(lo_); // NOLINT(runtime/int)
  657. }
  658. constexpr uint128::operator long long() const { // NOLINT(runtime/int)
  659. return static_cast<long long>(lo_); // NOLINT(runtime/int)
  660. }
  661. constexpr uint128::operator unsigned long long() const { // NOLINT(runtime/int)
  662. return static_cast<unsigned long long>(lo_); // NOLINT(runtime/int)
  663. }
  664. #ifdef Y_ABSL_HAVE_INTRINSIC_INT128
  665. constexpr uint128::operator __int128() const {
  666. return (static_cast<__int128>(hi_) << 64) + lo_;
  667. }
  668. constexpr uint128::operator unsigned __int128() const {
  669. return (static_cast<unsigned __int128>(hi_) << 64) + lo_;
  670. }
  671. #endif // Y_ABSL_HAVE_INTRINSIC_INT128
  672. // Conversion operators to floating point types.
  673. inline uint128::operator float() const {
  674. return static_cast<float>(lo_) + std::ldexp(static_cast<float>(hi_), 64);
  675. }
  676. inline uint128::operator double() const {
  677. return static_cast<double>(lo_) + std::ldexp(static_cast<double>(hi_), 64);
  678. }
  679. inline uint128::operator long double() const {
  680. return static_cast<long double>(lo_) +
  681. std::ldexp(static_cast<long double>(hi_), 64);
  682. }
  683. // Comparison operators.
  684. constexpr bool operator==(uint128 lhs, uint128 rhs) {
  685. #if defined(Y_ABSL_HAVE_INTRINSIC_INT128)
  686. return static_cast<unsigned __int128>(lhs) ==
  687. static_cast<unsigned __int128>(rhs);
  688. #else
  689. return (Uint128Low64(lhs) == Uint128Low64(rhs) &&
  690. Uint128High64(lhs) == Uint128High64(rhs));
  691. #endif
  692. }
  693. constexpr bool operator!=(uint128 lhs, uint128 rhs) { return !(lhs == rhs); }
  694. constexpr bool operator<(uint128 lhs, uint128 rhs) {
  695. #ifdef Y_ABSL_HAVE_INTRINSIC_INT128
  696. return static_cast<unsigned __int128>(lhs) <
  697. static_cast<unsigned __int128>(rhs);
  698. #else
  699. return (Uint128High64(lhs) == Uint128High64(rhs))
  700. ? (Uint128Low64(lhs) < Uint128Low64(rhs))
  701. : (Uint128High64(lhs) < Uint128High64(rhs));
  702. #endif
  703. }
  704. constexpr bool operator>(uint128 lhs, uint128 rhs) { return rhs < lhs; }
  705. constexpr bool operator<=(uint128 lhs, uint128 rhs) { return !(rhs < lhs); }
  706. constexpr bool operator>=(uint128 lhs, uint128 rhs) { return !(lhs < rhs); }
  707. // Unary operators.
  708. constexpr inline uint128 operator+(uint128 val) { return val; }
  709. constexpr inline int128 operator+(int128 val) { return val; }
  710. constexpr uint128 operator-(uint128 val) {
  711. #if defined(Y_ABSL_HAVE_INTRINSIC_INT128)
  712. return -static_cast<unsigned __int128>(val);
  713. #else
  714. return MakeUint128(
  715. ~Uint128High64(val) + static_cast<unsigned long>(Uint128Low64(val) == 0),
  716. ~Uint128Low64(val) + 1);
  717. #endif
  718. }
  719. constexpr inline bool operator!(uint128 val) {
  720. #if defined(Y_ABSL_HAVE_INTRINSIC_INT128)
  721. return !static_cast<unsigned __int128>(val);
  722. #else
  723. return !Uint128High64(val) && !Uint128Low64(val);
  724. #endif
  725. }
  726. // Logical operators.
  727. constexpr inline uint128 operator~(uint128 val) {
  728. #if defined(Y_ABSL_HAVE_INTRINSIC_INT128)
  729. return ~static_cast<unsigned __int128>(val);
  730. #else
  731. return MakeUint128(~Uint128High64(val), ~Uint128Low64(val));
  732. #endif
  733. }
  734. constexpr inline uint128 operator|(uint128 lhs, uint128 rhs) {
  735. #if defined(Y_ABSL_HAVE_INTRINSIC_INT128)
  736. return static_cast<unsigned __int128>(lhs) |
  737. static_cast<unsigned __int128>(rhs);
  738. #else
  739. return MakeUint128(Uint128High64(lhs) | Uint128High64(rhs),
  740. Uint128Low64(lhs) | Uint128Low64(rhs));
  741. #endif
  742. }
  743. constexpr inline uint128 operator&(uint128 lhs, uint128 rhs) {
  744. #if defined(Y_ABSL_HAVE_INTRINSIC_INT128)
  745. return static_cast<unsigned __int128>(lhs) &
  746. static_cast<unsigned __int128>(rhs);
  747. #else
  748. return MakeUint128(Uint128High64(lhs) & Uint128High64(rhs),
  749. Uint128Low64(lhs) & Uint128Low64(rhs));
  750. #endif
  751. }
  752. constexpr inline uint128 operator^(uint128 lhs, uint128 rhs) {
  753. #if defined(Y_ABSL_HAVE_INTRINSIC_INT128)
  754. return static_cast<unsigned __int128>(lhs) ^
  755. static_cast<unsigned __int128>(rhs);
  756. #else
  757. return MakeUint128(Uint128High64(lhs) ^ Uint128High64(rhs),
  758. Uint128Low64(lhs) ^ Uint128Low64(rhs));
  759. #endif
  760. }
  761. inline uint128& uint128::operator|=(uint128 other) {
  762. *this = *this | other;
  763. return *this;
  764. }
  765. inline uint128& uint128::operator&=(uint128 other) {
  766. *this = *this & other;
  767. return *this;
  768. }
  769. inline uint128& uint128::operator^=(uint128 other) {
  770. *this = *this ^ other;
  771. return *this;
  772. }
  773. // Arithmetic operators.
  774. constexpr uint128 operator<<(uint128 lhs, int amount) {
  775. #ifdef Y_ABSL_HAVE_INTRINSIC_INT128
  776. return static_cast<unsigned __int128>(lhs) << amount;
  777. #else
  778. // uint64_t shifts of >= 64 are undefined, so we will need some
  779. // special-casing.
  780. return amount >= 64 ? MakeUint128(Uint128Low64(lhs) << (amount - 64), 0)
  781. : amount == 0 ? lhs
  782. : MakeUint128((Uint128High64(lhs) << amount) |
  783. (Uint128Low64(lhs) >> (64 - amount)),
  784. Uint128Low64(lhs) << amount);
  785. #endif
  786. }
  787. constexpr uint128 operator>>(uint128 lhs, int amount) {
  788. #ifdef Y_ABSL_HAVE_INTRINSIC_INT128
  789. return static_cast<unsigned __int128>(lhs) >> amount;
  790. #else
  791. // uint64_t shifts of >= 64 are undefined, so we will need some
  792. // special-casing.
  793. return amount >= 64 ? MakeUint128(0, Uint128High64(lhs) >> (amount - 64))
  794. : amount == 0 ? lhs
  795. : MakeUint128(Uint128High64(lhs) >> amount,
  796. (Uint128Low64(lhs) >> amount) |
  797. (Uint128High64(lhs) << (64 - amount)));
  798. #endif
  799. }
  800. #if !defined(Y_ABSL_HAVE_INTRINSIC_INT128)
  801. namespace int128_internal {
  802. constexpr uint128 AddResult(uint128 result, uint128 lhs) {
  803. // check for carry
  804. return (Uint128Low64(result) < Uint128Low64(lhs))
  805. ? MakeUint128(Uint128High64(result) + 1, Uint128Low64(result))
  806. : result;
  807. }
  808. } // namespace int128_internal
  809. #endif
  810. constexpr uint128 operator+(uint128 lhs, uint128 rhs) {
  811. #if defined(Y_ABSL_HAVE_INTRINSIC_INT128)
  812. return static_cast<unsigned __int128>(lhs) +
  813. static_cast<unsigned __int128>(rhs);
  814. #else
  815. return int128_internal::AddResult(
  816. MakeUint128(Uint128High64(lhs) + Uint128High64(rhs),
  817. Uint128Low64(lhs) + Uint128Low64(rhs)),
  818. lhs);
  819. #endif
  820. }
  821. #if !defined(Y_ABSL_HAVE_INTRINSIC_INT128)
  822. namespace int128_internal {
  823. constexpr uint128 SubstructResult(uint128 result, uint128 lhs, uint128 rhs) {
  824. // check for carry
  825. return (Uint128Low64(lhs) < Uint128Low64(rhs))
  826. ? MakeUint128(Uint128High64(result) - 1, Uint128Low64(result))
  827. : result;
  828. }
  829. } // namespace int128_internal
  830. #endif
  831. constexpr uint128 operator-(uint128 lhs, uint128 rhs) {
  832. #if defined(Y_ABSL_HAVE_INTRINSIC_INT128)
  833. return static_cast<unsigned __int128>(lhs) -
  834. static_cast<unsigned __int128>(rhs);
  835. #else
  836. return int128_internal::SubstructResult(
  837. MakeUint128(Uint128High64(lhs) - Uint128High64(rhs),
  838. Uint128Low64(lhs) - Uint128Low64(rhs)),
  839. lhs, rhs);
  840. #endif
  841. }
  842. inline uint128 operator*(uint128 lhs, uint128 rhs) {
  843. #if defined(Y_ABSL_HAVE_INTRINSIC_INT128)
  844. // TODO(strel) Remove once alignment issues are resolved and unsigned __int128
  845. // can be used for uint128 storage.
  846. return static_cast<unsigned __int128>(lhs) *
  847. static_cast<unsigned __int128>(rhs);
  848. #elif defined(_MSC_VER) && defined(_M_X64) && !defined(_M_ARM64EC)
  849. uint64_t carry;
  850. uint64_t low = _umul128(Uint128Low64(lhs), Uint128Low64(rhs), &carry);
  851. return MakeUint128(Uint128Low64(lhs) * Uint128High64(rhs) +
  852. Uint128High64(lhs) * Uint128Low64(rhs) + carry,
  853. low);
  854. #else // Y_ABSL_HAVE_INTRINSIC128
  855. uint64_t a32 = Uint128Low64(lhs) >> 32;
  856. uint64_t a00 = Uint128Low64(lhs) & 0xffffffff;
  857. uint64_t b32 = Uint128Low64(rhs) >> 32;
  858. uint64_t b00 = Uint128Low64(rhs) & 0xffffffff;
  859. uint128 result =
  860. MakeUint128(Uint128High64(lhs) * Uint128Low64(rhs) +
  861. Uint128Low64(lhs) * Uint128High64(rhs) + a32 * b32,
  862. a00 * b00);
  863. result += uint128(a32 * b00) << 32;
  864. result += uint128(a00 * b32) << 32;
  865. return result;
  866. #endif // Y_ABSL_HAVE_INTRINSIC128
  867. }
  868. #if defined(Y_ABSL_HAVE_INTRINSIC_INT128)
  869. inline uint128 operator/(uint128 lhs, uint128 rhs) {
  870. return static_cast<unsigned __int128>(lhs) /
  871. static_cast<unsigned __int128>(rhs);
  872. }
  873. inline uint128 operator%(uint128 lhs, uint128 rhs) {
  874. return static_cast<unsigned __int128>(lhs) %
  875. static_cast<unsigned __int128>(rhs);
  876. }
  877. #endif
  878. // Increment/decrement operators.
  879. inline uint128 uint128::operator++(int) {
  880. uint128 tmp(*this);
  881. *this += 1;
  882. return tmp;
  883. }
  884. inline uint128 uint128::operator--(int) {
  885. uint128 tmp(*this);
  886. *this -= 1;
  887. return tmp;
  888. }
  889. inline uint128& uint128::operator++() {
  890. *this += 1;
  891. return *this;
  892. }
  893. inline uint128& uint128::operator--() {
  894. *this -= 1;
  895. return *this;
  896. }
  897. constexpr int128 MakeInt128(int64_t high, uint64_t low) {
  898. return int128(high, low);
  899. }
  900. // Assignment from integer types.
  901. inline int128& int128::operator=(int v) { return *this = int128(v); }
  902. inline int128& int128::operator=(unsigned int v) { return *this = int128(v); }
  903. inline int128& int128::operator=(long v) { // NOLINT(runtime/int)
  904. return *this = int128(v);
  905. }
  906. // NOLINTNEXTLINE(runtime/int)
  907. inline int128& int128::operator=(unsigned long v) { return *this = int128(v); }
  908. // NOLINTNEXTLINE(runtime/int)
  909. inline int128& int128::operator=(long long v) { return *this = int128(v); }
  910. // NOLINTNEXTLINE(runtime/int)
  911. inline int128& int128::operator=(unsigned long long v) {
  912. return *this = int128(v);
  913. }
  914. // Arithmetic operators.
  915. constexpr int128 operator-(int128 v);
  916. constexpr int128 operator+(int128 lhs, int128 rhs);
  917. constexpr int128 operator-(int128 lhs, int128 rhs);
  918. int128 operator*(int128 lhs, int128 rhs);
  919. int128 operator/(int128 lhs, int128 rhs);
  920. int128 operator%(int128 lhs, int128 rhs);
  921. constexpr int128 operator|(int128 lhs, int128 rhs);
  922. constexpr int128 operator&(int128 lhs, int128 rhs);
  923. constexpr int128 operator^(int128 lhs, int128 rhs);
  924. constexpr int128 operator<<(int128 lhs, int amount);
  925. constexpr int128 operator>>(int128 lhs, int amount);
  926. inline int128& int128::operator+=(int128 other) {
  927. *this = *this + other;
  928. return *this;
  929. }
  930. inline int128& int128::operator-=(int128 other) {
  931. *this = *this - other;
  932. return *this;
  933. }
  934. inline int128& int128::operator*=(int128 other) {
  935. *this = *this * other;
  936. return *this;
  937. }
  938. inline int128& int128::operator/=(int128 other) {
  939. *this = *this / other;
  940. return *this;
  941. }
  942. inline int128& int128::operator%=(int128 other) {
  943. *this = *this % other;
  944. return *this;
  945. }
  946. inline int128& int128::operator|=(int128 other) {
  947. *this = *this | other;
  948. return *this;
  949. }
  950. inline int128& int128::operator&=(int128 other) {
  951. *this = *this & other;
  952. return *this;
  953. }
  954. inline int128& int128::operator^=(int128 other) {
  955. *this = *this ^ other;
  956. return *this;
  957. }
  958. inline int128& int128::operator<<=(int amount) {
  959. *this = *this << amount;
  960. return *this;
  961. }
  962. inline int128& int128::operator>>=(int amount) {
  963. *this = *this >> amount;
  964. return *this;
  965. }
  966. // Forward declaration for comparison operators.
  967. constexpr bool operator!=(int128 lhs, int128 rhs);
  968. namespace int128_internal {
  969. // Casts from unsigned to signed while preserving the underlying binary
  970. // representation.
  971. constexpr int64_t BitCastToSigned(uint64_t v) {
  972. // Casting an unsigned integer to a signed integer of the same
  973. // width is implementation defined behavior if the source value would not fit
  974. // in the destination type. We step around it with a roundtrip bitwise not
  975. // operation to make sure this function remains constexpr. Clang, GCC, and
  976. // MSVC optimize this to a no-op on x86-64.
  977. return v & (uint64_t{1} << 63) ? ~static_cast<int64_t>(~v)
  978. : static_cast<int64_t>(v);
  979. }
  980. } // namespace int128_internal
  981. #if defined(Y_ABSL_HAVE_INTRINSIC_INT128)
  982. #include "y_absl/numeric/int128_have_intrinsic.inc" // IWYU pragma: export
  983. #else // Y_ABSL_HAVE_INTRINSIC_INT128
  984. #include "y_absl/numeric/int128_no_intrinsic.inc" // IWYU pragma: export
  985. #endif // Y_ABSL_HAVE_INTRINSIC_INT128
  986. Y_ABSL_NAMESPACE_END
  987. } // namespace y_absl
  988. #undef Y_ABSL_INTERNAL_WCHAR_T
  989. #endif // Y_ABSL_NUMERIC_INT128_H_