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

Unified Diff: base/numerics/safe_conversions_impl.h

Issue 2566733002: Performance optimizations for base/numerics absolute value and multiply (Closed)
Patch Set: more shuffling 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
« no previous file with comments | « base/numerics/safe_conversions.h ('k') | base/numerics/safe_math_impl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..774a5373ab96afb0c1829f53ede5ca4f6e72c5fa 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.
scottmg 2016/12/09 22:48:24 I don't see this getting used?
jschuh 2016/12/09 22:58:05 It is in safe_math_impl.h. I just moved it because
+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,
+ typename std::enable_if<!std::is_signed<T>::value>::type* = nullptr>
scottmg 2016/12/09 23:27:02 std::is_integral<T>::value && in the enable_if fo
jschuh 2016/12/09 23:31:28 I had that originally, but there are no unsigned n
+constexpr T SafeUnsignedAbsImpl(T value, T sign_mask) {
+ 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.
« no previous file with comments | « base/numerics/safe_conversions.h ('k') | base/numerics/safe_math_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698