tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

int128_no_intrinsic.inc (12084B)


      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 // This file contains :int128 implementation details that depend on internal
     17 // representation when ABSL_HAVE_INTRINSIC_INT128 is *not* defined. This file
     18 // is included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined.
     19 
     20 constexpr uint64_t Int128Low64(int128 v) { return v.lo_; }
     21 
     22 constexpr int64_t Int128High64(int128 v) { return v.hi_; }
     23 
     24 #if defined(ABSL_IS_LITTLE_ENDIAN)
     25 
     26 constexpr int128::int128(int64_t high, uint64_t low) : lo_(low), hi_(high) {}
     27 
     28 constexpr int128::int128(int v)
     29    : lo_{static_cast<uint64_t>(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {}
     30 constexpr int128::int128(long v)  // NOLINT(runtime/int)
     31    : lo_{static_cast<uint64_t>(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {}
     32 constexpr int128::int128(long long v)  // NOLINT(runtime/int)
     33    : lo_{static_cast<uint64_t>(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {}
     34 
     35 constexpr int128::int128(unsigned int v) : lo_{v}, hi_{0} {}
     36 // NOLINTNEXTLINE(runtime/int)
     37 constexpr int128::int128(unsigned long v) : lo_{v}, hi_{0} {}
     38 // NOLINTNEXTLINE(runtime/int)
     39 constexpr int128::int128(unsigned long long v) : lo_{v}, hi_{0} {}
     40 
     41 constexpr int128::int128(uint128 v)
     42    : lo_{Uint128Low64(v)}, hi_{static_cast<int64_t>(Uint128High64(v))} {}
     43 
     44 #elif defined(ABSL_IS_BIG_ENDIAN)
     45 
     46 constexpr int128::int128(int64_t high, uint64_t low) : hi_{high}, lo_{low} {}
     47 
     48 constexpr int128::int128(int v)
     49    : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast<uint64_t>(v)} {}
     50 constexpr int128::int128(long v)  // NOLINT(runtime/int)
     51    : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast<uint64_t>(v)} {}
     52 constexpr int128::int128(long long v)  // NOLINT(runtime/int)
     53    : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast<uint64_t>(v)} {}
     54 
     55 constexpr int128::int128(unsigned int v) : hi_{0}, lo_{v} {}
     56 // NOLINTNEXTLINE(runtime/int)
     57 constexpr int128::int128(unsigned long v) : hi_{0}, lo_{v} {}
     58 // NOLINTNEXTLINE(runtime/int)
     59 constexpr int128::int128(unsigned long long v) : hi_{0}, lo_{v} {}
     60 
     61 constexpr int128::int128(uint128 v)
     62    : hi_{static_cast<int64_t>(Uint128High64(v))}, lo_{Uint128Low64(v)} {}
     63 
     64 #else  // byte order
     65 #error "Unsupported byte order: must be little-endian or big-endian."
     66 #endif  // byte order
     67 
     68 constexpr int128::operator bool() const { return lo_ || hi_; }
     69 
     70 constexpr int128::operator char() const {
     71  // NOLINTNEXTLINE(runtime/int)
     72  return static_cast<char>(static_cast<long long>(*this));
     73 }
     74 
     75 constexpr int128::operator signed char() const {
     76  // NOLINTNEXTLINE(runtime/int)
     77  return static_cast<signed char>(static_cast<long long>(*this));
     78 }
     79 
     80 constexpr int128::operator unsigned char() const {
     81  return static_cast<unsigned char>(lo_);
     82 }
     83 
     84 constexpr int128::operator char16_t() const {
     85  return static_cast<char16_t>(lo_);
     86 }
     87 
     88 constexpr int128::operator char32_t() const {
     89  return static_cast<char32_t>(lo_);
     90 }
     91 
     92 constexpr int128::operator ABSL_INTERNAL_WCHAR_T() const {
     93  // NOLINTNEXTLINE(runtime/int)
     94  return static_cast<ABSL_INTERNAL_WCHAR_T>(static_cast<long long>(*this));
     95 }
     96 
     97 constexpr int128::operator short() const {  // NOLINT(runtime/int)
     98  // NOLINTNEXTLINE(runtime/int)
     99  return static_cast<short>(static_cast<long long>(*this));
    100 }
    101 
    102 constexpr int128::operator unsigned short() const {  // NOLINT(runtime/int)
    103  return static_cast<unsigned short>(lo_);           // NOLINT(runtime/int)
    104 }
    105 
    106 constexpr int128::operator int() const {
    107  // NOLINTNEXTLINE(runtime/int)
    108  return static_cast<int>(static_cast<long long>(*this));
    109 }
    110 
    111 constexpr int128::operator unsigned int() const {
    112  return static_cast<unsigned int>(lo_);
    113 }
    114 
    115 constexpr int128::operator long() const {  // NOLINT(runtime/int)
    116  // NOLINTNEXTLINE(runtime/int)
    117  return static_cast<long>(static_cast<long long>(*this));
    118 }
    119 
    120 constexpr int128::operator unsigned long() const {  // NOLINT(runtime/int)
    121  return static_cast<unsigned long>(lo_);           // NOLINT(runtime/int)
    122 }
    123 
    124 constexpr int128::operator long long() const {  // NOLINT(runtime/int)
    125  // We don't bother checking the value of hi_. If *this < 0, lo_'s high bit
    126  // must be set in order for the value to fit into a long long. Conversely, if
    127  // lo_'s high bit is set, *this must be < 0 for the value to fit.
    128  return int128_internal::BitCastToSigned(lo_);
    129 }
    130 
    131 constexpr int128::operator unsigned long long() const {  // NOLINT(runtime/int)
    132  return static_cast<unsigned long long>(lo_);           // NOLINT(runtime/int)
    133 }
    134 
    135 inline int128::operator float() const {
    136  // We must convert the absolute value and then negate as needed, because
    137  // floating point types are typically sign-magnitude. Otherwise, the
    138  // difference between the high and low 64 bits when interpreted as two's
    139  // complement overwhelms the precision of the mantissa.
    140  //
    141  // Also check to make sure we don't negate Int128Min()
    142  constexpr float pow_2_64 = 18446744073709551616.0f;
    143  return hi_ < 0 && *this != Int128Min()
    144             ? -static_cast<float>(-*this)
    145             : static_cast<float>(lo_) +
    146                   static_cast<float>(hi_) * pow_2_64;
    147 }
    148 
    149 inline int128::operator double() const {
    150  // See comment in int128::operator float() above.
    151  constexpr double pow_2_64 = 18446744073709551616.0;
    152  return hi_ < 0 && *this != Int128Min()
    153             ? -static_cast<double>(-*this)
    154             : static_cast<double>(lo_) +
    155                   static_cast<double>(hi_) * pow_2_64;
    156 }
    157 
    158 inline int128::operator long double() const {
    159  // See comment in int128::operator float() above.
    160  constexpr long double pow_2_64 = 18446744073709551616.0L;
    161  return hi_ < 0 && *this != Int128Min()
    162             ? -static_cast<long double>(-*this)
    163             : static_cast<long double>(lo_) +
    164                   static_cast<long double>(hi_) * pow_2_64;
    165 }
    166 
    167 // Comparison operators.
    168 
    169 constexpr bool operator==(int128 lhs, int128 rhs) {
    170  return (Int128Low64(lhs) == Int128Low64(rhs) &&
    171          Int128High64(lhs) == Int128High64(rhs));
    172 }
    173 
    174 constexpr bool operator!=(int128 lhs, int128 rhs) { return !(lhs == rhs); }
    175 
    176 constexpr bool operator<(int128 lhs, int128 rhs) {
    177  return (Int128High64(lhs) == Int128High64(rhs))
    178             ? (Int128Low64(lhs) < Int128Low64(rhs))
    179             : (Int128High64(lhs) < Int128High64(rhs));
    180 }
    181 
    182 constexpr bool operator>(int128 lhs, int128 rhs) {
    183  return (Int128High64(lhs) == Int128High64(rhs))
    184             ? (Int128Low64(lhs) > Int128Low64(rhs))
    185             : (Int128High64(lhs) > Int128High64(rhs));
    186 }
    187 
    188 constexpr bool operator<=(int128 lhs, int128 rhs) { return !(lhs > rhs); }
    189 
    190 constexpr bool operator>=(int128 lhs, int128 rhs) { return !(lhs < rhs); }
    191 
    192 #ifdef __cpp_impl_three_way_comparison
    193 constexpr absl::strong_ordering operator<=>(int128 lhs, int128 rhs) {
    194  if (int64_t lhs_high = Int128High64(lhs), rhs_high = Int128High64(rhs);
    195      lhs_high < rhs_high) {
    196    return absl::strong_ordering::less;
    197  } else if (lhs_high > rhs_high) {
    198    return absl::strong_ordering::greater;
    199  } else if (uint64_t lhs_low = Uint128Low64(lhs), rhs_low = Uint128Low64(rhs);
    200             lhs_low < rhs_low) {
    201    return absl::strong_ordering::less;
    202  } else if (lhs_low > rhs_low) {
    203    return absl::strong_ordering::greater;
    204  } else {
    205    return absl::strong_ordering::equal;
    206  }
    207 }
    208 #endif
    209 
    210 // Unary operators.
    211 
    212 constexpr int128 operator-(int128 v) {
    213  return MakeInt128(~Int128High64(v) + (Int128Low64(v) == 0),
    214                    ~Int128Low64(v) + 1);
    215 }
    216 
    217 constexpr bool operator!(int128 v) {
    218  return !Int128Low64(v) && !Int128High64(v);
    219 }
    220 
    221 constexpr int128 operator~(int128 val) {
    222  return MakeInt128(~Int128High64(val), ~Int128Low64(val));
    223 }
    224 
    225 // Arithmetic operators.
    226 
    227 namespace int128_internal {
    228 constexpr int128 SignedAddResult(int128 result, int128 lhs) {
    229  // check for carry
    230  return (Int128Low64(result) < Int128Low64(lhs))
    231             ? MakeInt128(Int128High64(result) + 1, Int128Low64(result))
    232             : result;
    233 }
    234 }  // namespace int128_internal
    235 constexpr int128 operator+(int128 lhs, int128 rhs) {
    236  return int128_internal::SignedAddResult(
    237      MakeInt128(Int128High64(lhs) + Int128High64(rhs),
    238                 Int128Low64(lhs) + Int128Low64(rhs)),
    239      lhs);
    240 }
    241 
    242 namespace int128_internal {
    243 constexpr int128 SignedSubstructResult(int128 result, int128 lhs, int128 rhs) {
    244  // check for carry
    245  return (Int128Low64(lhs) < Int128Low64(rhs))
    246             ? MakeInt128(Int128High64(result) - 1, Int128Low64(result))
    247             : result;
    248 }
    249 }  // namespace int128_internal
    250 constexpr int128 operator-(int128 lhs, int128 rhs) {
    251  return int128_internal::SignedSubstructResult(
    252      MakeInt128(Int128High64(lhs) - Int128High64(rhs),
    253                 Int128Low64(lhs) - Int128Low64(rhs)),
    254      lhs, rhs);
    255 }
    256 
    257 inline int128 operator*(int128 lhs, int128 rhs) {
    258  return MakeInt128(
    259      int128_internal::BitCastToSigned(Uint128High64(uint128(lhs) * rhs)),
    260      Uint128Low64(uint128(lhs) * rhs));
    261 }
    262 
    263 inline int128 int128::operator++(int) {
    264  int128 tmp(*this);
    265  *this += 1;
    266  return tmp;
    267 }
    268 
    269 inline int128 int128::operator--(int) {
    270  int128 tmp(*this);
    271  *this -= 1;
    272  return tmp;
    273 }
    274 
    275 inline int128& int128::operator++() {
    276  *this += 1;
    277  return *this;
    278 }
    279 
    280 inline int128& int128::operator--() {
    281  *this -= 1;
    282  return *this;
    283 }
    284 
    285 constexpr int128 operator|(int128 lhs, int128 rhs) {
    286  return MakeInt128(Int128High64(lhs) | Int128High64(rhs),
    287                    Int128Low64(lhs) | Int128Low64(rhs));
    288 }
    289 
    290 constexpr int128 operator&(int128 lhs, int128 rhs) {
    291  return MakeInt128(Int128High64(lhs) & Int128High64(rhs),
    292                    Int128Low64(lhs) & Int128Low64(rhs));
    293 }
    294 
    295 constexpr int128 operator^(int128 lhs, int128 rhs) {
    296  return MakeInt128(Int128High64(lhs) ^ Int128High64(rhs),
    297                    Int128Low64(lhs) ^ Int128Low64(rhs));
    298 }
    299 
    300 constexpr int128 operator<<(int128 lhs, int amount) {
    301  // int64_t shifts of >= 63 are undefined, so we need some special-casing.
    302  assert(amount >= 0 && amount < 127);
    303  if (amount <= 0) {
    304    return lhs;
    305  } else if (amount < 63) {
    306    return MakeInt128(
    307        (Int128High64(lhs) << amount) |
    308            static_cast<int64_t>(Int128Low64(lhs) >> (64 - amount)),
    309        Int128Low64(lhs) << amount);
    310  } else if (amount == 63) {
    311    return MakeInt128(((Int128High64(lhs) << 32) << 31) |
    312                          static_cast<int64_t>(Int128Low64(lhs) >> 1),
    313                      (Int128Low64(lhs) << 32) << 31);
    314  } else if (amount == 127) {
    315    return MakeInt128(static_cast<int64_t>(Int128Low64(lhs) << 63), 0);
    316  } else if (amount > 127) {
    317    return MakeInt128(0, 0);
    318  } else {
    319    // amount >= 64 && amount < 127
    320    return MakeInt128(static_cast<int64_t>(Int128Low64(lhs) << (amount - 64)),
    321                      0);
    322  }
    323 }
    324 
    325 constexpr int128 operator>>(int128 lhs, int amount) {
    326  // int64_t shifts of >= 63 are undefined, so we need some special-casing.
    327  assert(amount >= 0 && amount < 127);
    328  if (amount <= 0) {
    329    return lhs;
    330  } else if (amount < 63) {
    331    return MakeInt128(
    332        Int128High64(lhs) >> amount,
    333        Int128Low64(lhs) >> amount | static_cast<uint64_t>(Int128High64(lhs))
    334                                         << (64 - amount));
    335  } else if (amount == 63) {
    336    return MakeInt128((Int128High64(lhs) >> 32) >> 31,
    337                      static_cast<uint64_t>(Int128High64(lhs) << 1) |
    338                          (Int128Low64(lhs) >> 32) >> 31);
    339 
    340  } else if (amount >= 127) {
    341    return MakeInt128((Int128High64(lhs) >> 32) >> 31,
    342                      static_cast<uint64_t>((Int128High64(lhs) >> 32) >> 31));
    343  } else {
    344    // amount >= 64 && amount < 127
    345    return MakeInt128(
    346        (Int128High64(lhs) >> 32) >> 31,
    347        static_cast<uint64_t>(Int128High64(lhs) >> (amount - 64)));
    348  }
    349 }