Index: src/utils.h |
diff --git a/src/utils.h b/src/utils.h |
index 0ea1de1e0732ec289a27776867bd770d6cd4fbfd..6d0d3c84a3845750283340bf2bf611576f460994 100644 |
--- a/src/utils.h |
+++ b/src/utils.h |
@@ -137,15 +137,20 @@ inline int MostSignificantBit(uint32_t x) { |
return nibble + msb4[x]; |
} |
- |
-// The C++ standard leaves the semantics of '>>' undefined for |
-// negative signed operands. Most implementations do the right thing, |
-// though. |
-inline int ArithmeticShiftRight(int x, int s) { |
- return x >> s; |
+template <typename T> |
+static T ArithmeticShiftRight(T x, int shift) { |
+ DCHECK_LE(0, shift); |
+ if (x < 0) { |
+ // Right shift of signed values is implementation defined. Simulate a |
+ // true arithmetic right shift by adding leading sign bits. |
+ using UnsignedT = typename std::make_unsigned<T>::type; |
+ UnsignedT mask = ~(static_cast<UnsignedT>(~0) >> shift); |
+ return (static_cast<UnsignedT>(x) >> shift) | mask; |
+ } else { |
+ return x >> shift; |
+ } |
} |
- |
template <typename T> |
int Compare(const T& a, const T& b) { |
if (a == b) |