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

Unified Diff: base/numerics/safe_conversions_impl.h

Issue 2582063002: Revert of Support saturation overrides in saturated_cast (Closed)
Patch Set: 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_numerics_unittest.cc » ('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 5ef3321474e5d2ac83777dc1f3210cf7f0af59ad..c4d96365ff4d71d96ceffa739fc02dccff868c3f 100644
--- a/base/numerics/safe_conversions_impl.h
+++ b/base/numerics/safe_conversions_impl.h
@@ -48,36 +48,6 @@
template <typename T>
constexpr T BinaryComplement(T x) {
return static_cast<T>(~x);
-}
-
-// Determines if a numeric value is negative without throwing compiler
-// warnings on: unsigned(value) < 0.
-template <typename T,
- typename std::enable_if<std::is_signed<T>::value>::type* = nullptr>
-constexpr bool IsValueNegative(T value) {
- static_assert(std::is_arithmetic<T>::value, "Argument must be numeric.");
- return value < 0;
-}
-
-template <typename T,
- typename std::enable_if<!std::is_signed<T>::value>::type* = nullptr>
-constexpr bool IsValueNegative(T) {
- static_assert(std::is_arithmetic<T>::value, "Argument must be numeric.");
- return false;
-}
-
-// This performs a fast negation, returning a signed value. It works on unsigned
-// arguments, but probably doesn't do what you want for any unsigned value
-// larger than max / 2 + 1 (i.e. signed min cast to unsigned).
-template <typename T>
-constexpr typename std::make_signed<T>::type ConditionalNegate(
- T x,
- bool is_negative) {
- static_assert(std::is_integral<T>::value, "Type must be integral");
- using SignedT = typename std::make_signed<T>::type;
- using UnsignedT = typename std::make_unsigned<T>::type;
- return static_cast<SignedT>(
- (static_cast<UnsignedT>(x) ^ -SignedT(is_negative)) + is_negative);
}
// This performs a safe, non-branching absolute value via unsigned overflow.
@@ -211,44 +181,28 @@
// To fix this bug we manually truncate the maximum value when the destination
// type is an integral of larger precision than the source floating-point type,
// such that the resulting maximum is represented exactly as a floating point.
-template <typename Dst,
- typename Src,
- template <typename> class Bounds = std::numeric_limits>
+template <typename Dst, typename Src>
struct NarrowingRange {
using SrcLimits = typename std::numeric_limits<Src>;
using DstLimits = typename std::numeric_limits<Dst>;
-
- // Computes the mask required to make an accurate comparison between types.
- static const int kShift =
- (MaxExponent<Src>::value > MaxExponent<Dst>::value &&
- SrcLimits::digits < DstLimits::digits)
- ? (DstLimits::digits - SrcLimits::digits)
- : 0;
- template <
- typename T,
- typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
-
- // Masks out the integer bits that are beyond the precision of the
- // intermediate type used for comparison.
- static constexpr T Adjust(T value) {
- static_assert(std::is_same<T, Dst>::value, "");
- static_assert(kShift < DstLimits::digits, "");
- return static_cast<T>(
- ConditionalNegate(SafeUnsignedAbs(value) & ~((T(1) << kShift) - T(1)),
- IsValueNegative(value)));
- }
-
- template <typename T,
- typename std::enable_if<std::is_floating_point<T>::value>::type* =
- nullptr>
- static constexpr T Adjust(T value) {
- static_assert(std::is_same<T, Dst>::value, "");
- static_assert(kShift == 0, "");
- return value;
- }
-
- static constexpr Dst max() { return Adjust(Bounds<Dst>::max()); }
- static constexpr Dst lowest() { return Adjust(Bounds<Dst>::lowest()); }
+ // The following logic avoids warnings where the max function is
+ // instantiated with invalid values for a bit shift (even though
+ // such a function can never be called).
+ static const int shift = (MaxExponent<Src>::value > MaxExponent<Dst>::value &&
+ SrcLimits::digits < DstLimits::digits &&
+ SrcLimits::is_iec559 &&
+ DstLimits::is_integer)
+ ? (DstLimits::digits - SrcLimits::digits)
+ : 0;
+
+ static constexpr Dst max() {
+ // We use UINTMAX_C below to avoid compiler warnings about shifting floating
+ // points. Since it's a compile time calculation, it shouldn't have any
+ // performance impact.
+ return DstLimits::max() - static_cast<Dst>((UINTMAX_C(1) << shift) - 1);
+ }
+
+ static constexpr Dst lowest() { return DstLimits::lowest(); }
};
template <typename Dst,
« no previous file with comments | « base/numerics/safe_conversions.h ('k') | base/numerics/safe_numerics_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698