summaryrefslogtreecommitdiff
path: root/absl/numeric/int128_no_intrinsic.inc
diff options
context:
space:
mode:
Diffstat (limited to 'absl/numeric/int128_no_intrinsic.inc')
-rw-r--r--absl/numeric/int128_no_intrinsic.inc12
1 files changed, 9 insertions, 3 deletions
diff --git a/absl/numeric/int128_no_intrinsic.inc b/absl/numeric/int128_no_intrinsic.inc
index 66f6809f..8834804c 100644
--- a/absl/numeric/int128_no_intrinsic.inc
+++ b/absl/numeric/int128_no_intrinsic.inc
@@ -279,7 +279,7 @@ constexpr int128 operator^(int128 lhs, int128 rhs) {
}
constexpr int128 operator<<(int128 lhs, int amount) {
- // uint64_t shifts of >= 64 are undefined, so we need some special-casing.
+ // int64_t shifts of >= 64 are undefined, so we need some special-casing.
return amount >= 64
? MakeInt128(
static_cast<int64_t>(Int128Low64(lhs) << (amount - 64)), 0)
@@ -292,10 +292,16 @@ constexpr int128 operator<<(int128 lhs, int amount) {
}
constexpr int128 operator>>(int128 lhs, int amount) {
- // uint64_t shifts of >= 64 are undefined, so we need some special-casing.
+ // int64_t shifts of >= 64 are undefined, so we need some special-casing.
+ // The (Int128High64(lhs) >> 32) >> 32 "trick" causes the the most significant
+ // int64 to be inititialized with all zeros or all ones correctly. It takes
+ // into account whether the number is negative or positive, and whether the
+ // current architecture does arithmetic or logical right shifts for negative
+ // numbers.
return amount >= 64
? MakeInt128(
- 0, static_cast<uint64_t>(Int128High64(lhs) >> (amount - 64)))
+ (Int128High64(lhs) >> 32) >> 32,
+ static_cast<uint64_t>(Int128High64(lhs) >> (amount - 64)))
: amount == 0
? lhs
: MakeInt128(Int128High64(lhs) >> amount,