Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(140)

Unified Diff: base/numerics/safe_conversions_impl.h

Issue 2566733002: Performance optimizations for base/numerics absolute value and multiply (Closed)
Patch Set: one more nit Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/numerics/safe_conversions_impl.h
diff --git a/base/numerics/safe_conversions_impl.h b/base/numerics/safe_conversions_impl.h
index f383d9c07a60664cb075a8191dc0ee09754343ac..33d86bcedb250588d6df3fa21196501edb781ca7 100644
--- a/base/numerics/safe_conversions_impl.h
+++ b/base/numerics/safe_conversions_impl.h
@@ -30,6 +30,52 @@ struct IntegerBitsPlusSign {
std::is_signed<NumericType>::value;
};
+// Helper templates for integer manipulations.
+
+template <typename Integer>
+struct PositionOfSignBit {
+ static const size_t value = IntegerBitsPlusSign<Integer>::value - 1;
+};
+
+template <typename T>
+constexpr bool HasSignBit(T x) {
+ // Cast to unsigned since right shift on signed is undefined.
+ return !!(static_cast<typename std::make_unsigned<T>::type>(x) >>
+ PositionOfSignBit<T>::value);
+}
+
+// This wrapper undoes the standard integer promotions.
+template <typename T>
+constexpr T BinaryComplement(T x) {
+ return static_cast<T>(~x);
+}
+
+// This performs a safe, non-branching absolute value via unsigned overflow.
+template <typename T>
+constexpr T SafeUnsignedAbsImpl(T value, T sign_mask) {
+ static_assert(!std::is_signed<T>::value, "Types must be unsigned.");
+ return (value + sign_mask) ^ sign_mask;
+}
+
+template <typename T,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_signed<T>::value>::type* = nullptr>
+constexpr typename std::make_unsigned<T>::type SafeUnsignedAbs(T value) {
+ using UnsignedT = typename std::make_unsigned<T>::type;
+ return SafeUnsignedAbsImpl(
+ static_cast<UnsignedT>(value),
+ // The sign mask is all ones for negative and zero otherwise.
+ static_cast<UnsignedT>(-static_cast<T>(HasSignBit(value))));
+}
+
+template <typename T,
+ typename std::enable_if<std::is_integral<T>::value &&
+ !std::is_signed<T>::value>::type* = nullptr>
+constexpr T SafeUnsignedAbs(T value) {
+ // T is unsigned, so |value| must already be positive.
+ return static_cast<T>(value);
+}
+
enum IntegerRepresentation {
INTEGER_REPRESENTATION_UNSIGNED,
INTEGER_REPRESENTATION_SIGNED
@@ -288,11 +334,6 @@ struct TwiceWiderInteger {
IsSigned>::type;
};
-template <typename Integer>
-struct PositionOfSignBit {
- static const size_t value = IntegerBitsPlusSign<Integer>::value - 1;
-};
-
enum ArithmeticPromotionCategory {
LEFT_PROMOTION, // Use the type of the left-hand argument.
RIGHT_PROMOTION // Use the type of the right-hand argument.

Powered by Google App Engine
This is Rietveld 408576698