int128_have_intrinsic.inc 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  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. // This file contains :int128 implementation details that depend on internal
  16. // representation when ABSL_HAVE_INTRINSIC_INT128 is defined. This file is
  17. // included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined.
  18. namespace int128_internal {
  19. // Casts from unsigned to signed while preserving the underlying binary
  20. // representation.
  21. constexpr __int128 BitCastToSigned(unsigned __int128 v) {
  22. // Casting an unsigned integer to a signed integer of the same
  23. // width is implementation defined behavior if the source value would not fit
  24. // in the destination type. We step around it with a roundtrip bitwise not
  25. // operation to make sure this function remains constexpr. Clang and GCC
  26. // optimize this to a no-op on x86-64.
  27. return v & (static_cast<unsigned __int128>(1) << 127)
  28. ? ~static_cast<__int128>(~v)
  29. : static_cast<__int128>(v);
  30. }
  31. } // namespace int128_internal
  32. inline int128& int128::operator=(__int128 v) {
  33. v_ = v;
  34. return *this;
  35. }
  36. constexpr uint64_t Int128Low64(int128 v) {
  37. return static_cast<uint64_t>(v.v_ & ~uint64_t{0});
  38. }
  39. constexpr int64_t Int128High64(int128 v) {
  40. // Initially cast to unsigned to prevent a right shift on a negative value.
  41. return int128_internal::BitCastToSigned(
  42. static_cast<uint64_t>(static_cast<unsigned __int128>(v.v_) >> 64));
  43. }
  44. constexpr int128::int128(int64_t high, uint64_t low)
  45. // Initially cast to unsigned to prevent a left shift that overflows.
  46. : v_(int128_internal::BitCastToSigned(static_cast<unsigned __int128>(high)
  47. << 64) |
  48. low) {}
  49. constexpr int128::int128(int v) : v_{v} {}
  50. constexpr int128::int128(long v) : v_{v} {} // NOLINT(runtime/int)
  51. constexpr int128::int128(long long v) : v_{v} {} // NOLINT(runtime/int)
  52. constexpr int128::int128(__int128 v) : v_{v} {}
  53. constexpr int128::int128(unsigned int v) : v_{v} {}
  54. constexpr int128::int128(unsigned long v) : v_{v} {} // NOLINT(runtime/int)
  55. // NOLINTNEXTLINE(runtime/int)
  56. constexpr int128::int128(unsigned long long v) : v_{v} {}
  57. constexpr int128::int128(unsigned __int128 v) : v_{static_cast<__int128>(v)} {}
  58. inline int128::int128(float v) {
  59. v_ = static_cast<__int128>(v);
  60. }
  61. inline int128::int128(double v) {
  62. v_ = static_cast<__int128>(v);
  63. }
  64. inline int128::int128(long double v) {
  65. v_ = static_cast<__int128>(v);
  66. }
  67. constexpr int128::int128(uint128 v) : v_{static_cast<__int128>(v)} {}
  68. constexpr int128::operator bool() const { return static_cast<bool>(v_); }
  69. constexpr int128::operator char() const { return static_cast<char>(v_); }
  70. constexpr int128::operator signed char() const {
  71. return static_cast<signed char>(v_);
  72. }
  73. constexpr int128::operator unsigned char() const {
  74. return static_cast<unsigned char>(v_);
  75. }
  76. constexpr int128::operator char16_t() const {
  77. return static_cast<char16_t>(v_);
  78. }
  79. constexpr int128::operator char32_t() const {
  80. return static_cast<char32_t>(v_);
  81. }
  82. constexpr int128::operator ABSL_INTERNAL_WCHAR_T() const {
  83. return static_cast<ABSL_INTERNAL_WCHAR_T>(v_);
  84. }
  85. constexpr int128::operator short() const { // NOLINT(runtime/int)
  86. return static_cast<short>(v_); // NOLINT(runtime/int)
  87. }
  88. constexpr int128::operator unsigned short() const { // NOLINT(runtime/int)
  89. return static_cast<unsigned short>(v_); // NOLINT(runtime/int)
  90. }
  91. constexpr int128::operator int() const {
  92. return static_cast<int>(v_);
  93. }
  94. constexpr int128::operator unsigned int() const {
  95. return static_cast<unsigned int>(v_);
  96. }
  97. constexpr int128::operator long() const { // NOLINT(runtime/int)
  98. return static_cast<long>(v_); // NOLINT(runtime/int)
  99. }
  100. constexpr int128::operator unsigned long() const { // NOLINT(runtime/int)
  101. return static_cast<unsigned long>(v_); // NOLINT(runtime/int)
  102. }
  103. constexpr int128::operator long long() const { // NOLINT(runtime/int)
  104. return static_cast<long long>(v_); // NOLINT(runtime/int)
  105. }
  106. constexpr int128::operator unsigned long long() const { // NOLINT(runtime/int)
  107. return static_cast<unsigned long long>(v_); // NOLINT(runtime/int)
  108. }
  109. constexpr int128::operator __int128() const { return v_; }
  110. constexpr int128::operator unsigned __int128() const {
  111. return static_cast<unsigned __int128>(v_);
  112. }
  113. // Clang on PowerPC sometimes produces incorrect __int128 to floating point
  114. // conversions. In that case, we do the conversion with a similar implementation
  115. // to the conversion operators in int128_no_intrinsic.inc.
  116. #if defined(__clang__) && !defined(__ppc64__)
  117. inline int128::operator float() const { return static_cast<float>(v_); }
  118. inline int128::operator double() const { return static_cast<double>(v_); }
  119. inline int128::operator long double() const {
  120. return static_cast<long double>(v_);
  121. }
  122. #else // Clang on PowerPC
  123. inline int128::operator float() const {
  124. // We must convert the absolute value and then negate as needed, because
  125. // floating point types are typically sign-magnitude. Otherwise, the
  126. // difference between the high and low 64 bits when interpreted as two's
  127. // complement overwhelms the precision of the mantissa.
  128. //
  129. // Also check to make sure we don't negate Int128Min()
  130. constexpr float pow_2_64 = 18446744073709551616.0f;
  131. return v_ < 0 && *this != Int128Min()
  132. ? -static_cast<float>(-*this)
  133. : static_cast<float>(Int128Low64(*this)) +
  134. static_cast<float>(Int128High64(*this)) * pow_2_64;
  135. }
  136. inline int128::operator double() const {
  137. // See comment in int128::operator float() above.
  138. constexpr double pow_2_64 = 18446744073709551616.0;
  139. return v_ < 0 && *this != Int128Min()
  140. ? -static_cast<double>(-*this)
  141. : static_cast<double>(Int128Low64(*this)) +
  142. static_cast<double>(Int128High64(*this)) * pow_2_64;
  143. }
  144. inline int128::operator long double() const {
  145. // See comment in int128::operator float() above.
  146. constexpr long double pow_2_64 = 18446744073709551616.0L;
  147. return v_ < 0 && *this != Int128Min()
  148. ? -static_cast<long double>(-*this)
  149. : static_cast<long double>(Int128Low64(*this)) +
  150. static_cast<long double>(Int128High64(*this)) * pow_2_64;
  151. }
  152. #endif // Clang on PowerPC
  153. // Comparison operators.
  154. constexpr bool operator==(int128 lhs, int128 rhs) {
  155. return static_cast<__int128>(lhs) == static_cast<__int128>(rhs);
  156. }
  157. constexpr bool operator!=(int128 lhs, int128 rhs) {
  158. return static_cast<__int128>(lhs) != static_cast<__int128>(rhs);
  159. }
  160. constexpr bool operator<(int128 lhs, int128 rhs) {
  161. return static_cast<__int128>(lhs) < static_cast<__int128>(rhs);
  162. }
  163. constexpr bool operator>(int128 lhs, int128 rhs) {
  164. return static_cast<__int128>(lhs) > static_cast<__int128>(rhs);
  165. }
  166. constexpr bool operator<=(int128 lhs, int128 rhs) {
  167. return static_cast<__int128>(lhs) <= static_cast<__int128>(rhs);
  168. }
  169. constexpr bool operator>=(int128 lhs, int128 rhs) {
  170. return static_cast<__int128>(lhs) >= static_cast<__int128>(rhs);
  171. }
  172. #ifdef __cpp_impl_three_way_comparison
  173. constexpr absl::strong_ordering operator<=>(int128 lhs, int128 rhs) {
  174. if (auto lhs_128 = static_cast<__int128>(lhs),
  175. rhs_128 = static_cast<__int128>(rhs);
  176. lhs_128 < rhs_128) {
  177. return absl::strong_ordering::less;
  178. } else if (lhs_128 > rhs_128) {
  179. return absl::strong_ordering::greater;
  180. } else {
  181. return absl::strong_ordering::equal;
  182. }
  183. }
  184. #endif
  185. // Unary operators.
  186. constexpr int128 operator-(int128 v) { return -static_cast<__int128>(v); }
  187. constexpr bool operator!(int128 v) { return !static_cast<__int128>(v); }
  188. constexpr int128 operator~(int128 val) { return ~static_cast<__int128>(val); }
  189. // Arithmetic operators.
  190. constexpr int128 operator+(int128 lhs, int128 rhs) {
  191. return static_cast<__int128>(lhs) + static_cast<__int128>(rhs);
  192. }
  193. constexpr int128 operator-(int128 lhs, int128 rhs) {
  194. return static_cast<__int128>(lhs) - static_cast<__int128>(rhs);
  195. }
  196. inline int128 operator*(int128 lhs, int128 rhs) {
  197. return static_cast<__int128>(lhs) * static_cast<__int128>(rhs);
  198. }
  199. inline int128 operator/(int128 lhs, int128 rhs) {
  200. return static_cast<__int128>(lhs) / static_cast<__int128>(rhs);
  201. }
  202. inline int128 operator%(int128 lhs, int128 rhs) {
  203. return static_cast<__int128>(lhs) % static_cast<__int128>(rhs);
  204. }
  205. inline int128 int128::operator++(int) {
  206. int128 tmp(*this);
  207. ++v_;
  208. return tmp;
  209. }
  210. inline int128 int128::operator--(int) {
  211. int128 tmp(*this);
  212. --v_;
  213. return tmp;
  214. }
  215. inline int128& int128::operator++() {
  216. ++v_;
  217. return *this;
  218. }
  219. inline int128& int128::operator--() {
  220. --v_;
  221. return *this;
  222. }
  223. constexpr int128 operator|(int128 lhs, int128 rhs) {
  224. return static_cast<__int128>(lhs) | static_cast<__int128>(rhs);
  225. }
  226. constexpr int128 operator&(int128 lhs, int128 rhs) {
  227. return static_cast<__int128>(lhs) & static_cast<__int128>(rhs);
  228. }
  229. constexpr int128 operator^(int128 lhs, int128 rhs) {
  230. return static_cast<__int128>(lhs) ^ static_cast<__int128>(rhs);
  231. }
  232. constexpr int128 operator<<(int128 lhs, int amount) {
  233. return static_cast<__int128>(lhs) << amount;
  234. }
  235. constexpr int128 operator>>(int128 lhs, int amount) {
  236. return static_cast<__int128>(lhs) >> amount;
  237. }