summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/common/third_party/base/anglebase/numerics')
-rw-r--r--src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/OWNERS3
-rw-r--r--src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_conversions.h179
-rw-r--r--src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_conversions_impl.h274
-rw-r--r--src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_math.h329
-rw-r--r--src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_math_impl.h575
-rw-r--r--src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_numerics_unittest.cc771
6 files changed, 0 insertions, 2131 deletions
diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/OWNERS b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/OWNERS
deleted file mode 100644
index 41f35fc79b..0000000000
--- a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-jschuh@chromium.org
-tsepez@chromium.org
-
diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_conversions.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_conversions.h
deleted file mode 100644
index 43babc31a8..0000000000
--- a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_conversions.h
+++ /dev/null
@@ -1,179 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ANGLEBASE_NUMERICS_SAFE_CONVERSIONS_H_
-#define ANGLEBASE_NUMERICS_SAFE_CONVERSIONS_H_
-
-#include <stddef.h>
-
-#include <limits>
-#include <type_traits>
-
-#include "anglebase/logging.h"
-#include "anglebase/numerics/safe_conversions_impl.h"
-
-namespace angle
-{
-
-namespace base
-{
-
-// Convenience function that returns true if the supplied value is in range
-// for the destination type.
-template <typename Dst, typename Src>
-constexpr bool IsValueInRangeForNumericType(Src value)
-{
- return internal::DstRangeRelationToSrcRange<Dst>(value) == internal::RANGE_VALID;
-}
-
-// Convenience function for determining if a numeric value is negative without
-// throwing compiler warnings on: unsigned(value) < 0.
-template <typename T>
-constexpr typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type IsValueNegative(
- T value)
-{
- static_assert(std::numeric_limits<T>::is_specialized, "Argument must be numeric.");
- return value < 0;
-}
-
-template <typename T>
-constexpr typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type IsValueNegative(T)
-{
- static_assert(std::numeric_limits<T>::is_specialized, "Argument must be numeric.");
- return false;
-}
-
-// checked_cast<> is analogous to static_cast<> for numeric types,
-// except that it CHECKs that the specified numeric conversion will not
-// overflow or underflow. NaN source will always trigger a CHECK.
-template <typename Dst, typename Src>
-inline Dst checked_cast(Src value)
-{
- CHECK(IsValueInRangeForNumericType<Dst>(value));
- return static_cast<Dst>(value);
-}
-
-// HandleNaN will cause this class to CHECK(false).
-struct SaturatedCastNaNBehaviorCheck
-{
- template <typename T>
- static T HandleNaN()
- {
- CHECK(false);
- return T();
- }
-};
-
-// HandleNaN will return 0 in this case.
-struct SaturatedCastNaNBehaviorReturnZero
-{
- template <typename T>
- static constexpr T HandleNaN()
- {
- return T();
- }
-};
-
-namespace internal
-{
-// This wrapper is used for C++11 constexpr support by avoiding the declaration
-// of local variables in the saturated_cast template function.
-template <typename Dst, class NaNHandler, typename Src>
-constexpr Dst saturated_cast_impl(const Src value, const RangeConstraint constraint)
-{
- return constraint == RANGE_VALID
- ? static_cast<Dst>(value)
- : (constraint == RANGE_UNDERFLOW
- ? std::numeric_limits<Dst>::min()
- : (constraint == RANGE_OVERFLOW
- ? std::numeric_limits<Dst>::max()
- : (constraint == RANGE_INVALID
- ? NaNHandler::template HandleNaN<Dst>()
- : (NOTREACHED(), static_cast<Dst>(value)))));
-}
-} // namespace internal
-
-// saturated_cast<> is analogous to static_cast<> for numeric types, except
-// that the specified numeric conversion will saturate rather than overflow or
-// underflow. NaN assignment to an integral will defer the behavior to a
-// specified class. By default, it will return 0.
-template <typename Dst, class NaNHandler = SaturatedCastNaNBehaviorReturnZero, typename Src>
-constexpr Dst saturated_cast(Src value)
-{
- return std::numeric_limits<Dst>::is_iec559
- ? static_cast<Dst>(value) // Floating point optimization.
- : internal::saturated_cast_impl<Dst, NaNHandler>(
- value, internal::DstRangeRelationToSrcRange<Dst>(value));
-}
-
-// strict_cast<> is analogous to static_cast<> for numeric types, except that
-// it will cause a compile failure if the destination type is not large enough
-// to contain any value in the source type. It performs no runtime checking.
-template <typename Dst, typename Src>
-constexpr Dst strict_cast(Src value)
-{
- static_assert(std::numeric_limits<Src>::is_specialized, "Argument must be numeric.");
- static_assert(std::numeric_limits<Dst>::is_specialized, "Result must be numeric.");
- static_assert((internal::StaticDstRangeRelationToSrcRange<Dst, Src>::value ==
- internal::NUMERIC_RANGE_CONTAINED),
- "The numeric conversion is out of range for this type. You "
- "should probably use one of the following conversion "
- "mechanisms on the value you want to pass:\n"
- "- base::checked_cast\n"
- "- base::saturated_cast\n"
- "- base::CheckedNumeric");
-
- return static_cast<Dst>(value);
-}
-
-// StrictNumeric implements compile time range checking between numeric types by
-// wrapping assignment operations in a strict_cast. This class is intended to be
-// used for function arguments and return types, to ensure the destination type
-// can always contain the source type. This is essentially the same as enforcing
-// -Wconversion in gcc and C4302 warnings on MSVC, but it can be applied
-// incrementally at API boundaries, making it easier to convert code so that it
-// compiles cleanly with truncation warnings enabled.
-// This template should introduce no runtime overhead, but it also provides no
-// runtime checking of any of the associated mathematical operations. Use
-// CheckedNumeric for runtime range checks of the actual value being assigned.
-template <typename T>
-class StrictNumeric
-{
- public:
- typedef T type;
-
- constexpr StrictNumeric() : value_(0) {}
-
- // Copy constructor.
- template <typename Src>
- constexpr StrictNumeric(const StrictNumeric<Src> &rhs) : value_(strict_cast<T>(rhs.value_))
- {
- }
-
- // This is not an explicit constructor because we implicitly upgrade regular
- // numerics to StrictNumerics to make them easier to use.
- template <typename Src>
- constexpr StrictNumeric(Src value) : value_(strict_cast<T>(value))
- {
- }
-
- // The numeric cast operator basically handles all the magic.
- template <typename Dst>
- constexpr operator Dst() const
- {
- return strict_cast<Dst>(value_);
- }
-
- private:
- const T value_;
-};
-
-// Explicitly make a shorter size_t typedef for convenience.
-typedef StrictNumeric<size_t> SizeT;
-
-} // namespace base
-
-} // namespace angle
-
-#endif // ANGLEBASE_NUMERICS_SAFE_CONVERSIONS_H_
diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_conversions_impl.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_conversions_impl.h
deleted file mode 100644
index 10ed6c7a7f..0000000000
--- a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_conversions_impl.h
+++ /dev/null
@@ -1,274 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ANGLEBASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_
-#define ANGLEBASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_
-
-#include <limits.h>
-#include <stdint.h>
-
-#include <climits>
-#include <limits>
-
-namespace angle
-{
-
-namespace base
-{
-namespace internal
-{
-
-// The std library doesn't provide a binary max_exponent for integers, however
-// we can compute one by adding one to the number of non-sign bits. This allows
-// for accurate range comparisons between floating point and integer types.
-template <typename NumericType>
-struct MaxExponent
-{
- static_assert(std::is_arithmetic<NumericType>::value, "Argument must be numeric.");
- static const int value =
- std::numeric_limits<NumericType>::is_iec559
- ? std::numeric_limits<NumericType>::max_exponent
- : (sizeof(NumericType) * CHAR_BIT + 1 - std::numeric_limits<NumericType>::is_signed);
-};
-
-enum IntegerRepresentation
-{
- INTEGER_REPRESENTATION_UNSIGNED,
- INTEGER_REPRESENTATION_SIGNED
-};
-
-// A range for a given nunmeric Src type is contained for a given numeric Dst
-// type if both numeric_limits<Src>::max() <= numeric_limits<Dst>::max() and
-// numeric_limits<Src>::min() >= numeric_limits<Dst>::min() are true.
-// We implement this as template specializations rather than simple static
-// comparisons to ensure type correctness in our comparisons.
-enum NumericRangeRepresentation
-{
- NUMERIC_RANGE_NOT_CONTAINED,
- NUMERIC_RANGE_CONTAINED
-};
-
-// Helper templates to statically determine if our destination type can contain
-// maximum and minimum values represented by the source type.
-
-template <typename Dst,
- typename Src,
- IntegerRepresentation DstSign = std::numeric_limits<Dst>::is_signed
- ? INTEGER_REPRESENTATION_SIGNED
- : INTEGER_REPRESENTATION_UNSIGNED,
- IntegerRepresentation SrcSign = std::numeric_limits<Src>::is_signed
- ? INTEGER_REPRESENTATION_SIGNED
- : INTEGER_REPRESENTATION_UNSIGNED>
-struct StaticDstRangeRelationToSrcRange;
-
-// Same sign: Dst is guaranteed to contain Src only if its range is equal or
-// larger.
-template <typename Dst, typename Src, IntegerRepresentation Sign>
-struct StaticDstRangeRelationToSrcRange<Dst, Src, Sign, Sign>
-{
- static const NumericRangeRepresentation value =
- MaxExponent<Dst>::value >= MaxExponent<Src>::value ? NUMERIC_RANGE_CONTAINED
- : NUMERIC_RANGE_NOT_CONTAINED;
-};
-
-// Unsigned to signed: Dst is guaranteed to contain source only if its range is
-// larger.
-template <typename Dst, typename Src>
-struct StaticDstRangeRelationToSrcRange<Dst,
- Src,
- INTEGER_REPRESENTATION_SIGNED,
- INTEGER_REPRESENTATION_UNSIGNED>
-{
- static const NumericRangeRepresentation value =
- MaxExponent<Dst>::value > MaxExponent<Src>::value ? NUMERIC_RANGE_CONTAINED
- : NUMERIC_RANGE_NOT_CONTAINED;
-};
-
-// Signed to unsigned: Dst cannot be statically determined to contain Src.
-template <typename Dst, typename Src>
-struct StaticDstRangeRelationToSrcRange<Dst,
- Src,
- INTEGER_REPRESENTATION_UNSIGNED,
- INTEGER_REPRESENTATION_SIGNED>
-{
- static const NumericRangeRepresentation value = NUMERIC_RANGE_NOT_CONTAINED;
-};
-
-enum RangeConstraint : unsigned char
-{
- RANGE_VALID = 0x0, // Value can be represented by the destination type.
- RANGE_UNDERFLOW = 0x1, // Value would overflow.
- RANGE_OVERFLOW = 0x2, // Value would underflow.
- RANGE_INVALID = RANGE_UNDERFLOW | RANGE_OVERFLOW // Invalid (i.e. NaN).
-};
-
-// Helper function for coercing an int back to a RangeContraint.
-constexpr RangeConstraint GetRangeConstraint(int integer_range_constraint)
-{
- // TODO(jschuh): Once we get full C++14 support we want this
- // assert(integer_range_constraint >= RANGE_VALID &&
- // integer_range_constraint <= RANGE_INVALID)
- return static_cast<RangeConstraint>(integer_range_constraint);
-}
-
-// This function creates a RangeConstraint from an upper and lower bound
-// check by taking advantage of the fact that only NaN can be out of range in
-// both directions at once.
-constexpr inline RangeConstraint GetRangeConstraint(bool is_in_upper_bound, bool is_in_lower_bound)
-{
- return GetRangeConstraint((is_in_upper_bound ? 0 : RANGE_OVERFLOW) |
- (is_in_lower_bound ? 0 : RANGE_UNDERFLOW));
-}
-
-// The following helper template addresses a corner case in range checks for
-// conversion from a floating-point type to an integral type of smaller range
-// but larger precision (e.g. float -> unsigned). The problem is as follows:
-// 1. Integral maximum is always one less than a power of two, so it must be
-// truncated to fit the mantissa of the floating point. The direction of
-// rounding is implementation defined, but by default it's always IEEE
-// floats, which round to nearest and thus result in a value of larger
-// magnitude than the integral value.
-// Example: float f = UINT_MAX; // f is 4294967296f but UINT_MAX
-// // is 4294967295u.
-// 2. If the floating point value is equal to the promoted integral maximum
-// value, a range check will erroneously pass.
-// Example: (4294967296f <= 4294967295u) // This is true due to a precision
-// // loss in rounding up to float.
-// 3. When the floating point value is then converted to an integral, the
-// resulting value is out of range for the target integral type and
-// thus is implementation defined.
-// Example: unsigned u = (float)INT_MAX; // u will typically overflow to 0.
-// 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>
-struct NarrowingRange
-{
- typedef typename std::numeric_limits<Src> SrcLimits;
- typedef typename std::numeric_limits<Dst> DstLimits;
- // 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 min()
- {
- return std::numeric_limits<Dst>::is_iec559 ? -DstLimits::max() : DstLimits::min();
- }
-};
-
-template <typename Dst,
- typename Src,
- IntegerRepresentation DstSign = std::numeric_limits<Dst>::is_signed
- ? INTEGER_REPRESENTATION_SIGNED
- : INTEGER_REPRESENTATION_UNSIGNED,
- IntegerRepresentation SrcSign = std::numeric_limits<Src>::is_signed
- ? INTEGER_REPRESENTATION_SIGNED
- : INTEGER_REPRESENTATION_UNSIGNED,
- NumericRangeRepresentation DstRange = StaticDstRangeRelationToSrcRange<Dst, Src>::value>
-struct DstRangeRelationToSrcRangeImpl;
-
-// The following templates are for ranges that must be verified at runtime. We
-// split it into checks based on signedness to avoid confusing casts and
-// compiler warnings on signed an unsigned comparisons.
-
-// Dst range is statically determined to contain Src: Nothing to check.
-template <typename Dst, typename Src, IntegerRepresentation DstSign, IntegerRepresentation SrcSign>
-struct DstRangeRelationToSrcRangeImpl<Dst, Src, DstSign, SrcSign, NUMERIC_RANGE_CONTAINED>
-{
- static constexpr RangeConstraint Check(Src value) { return RANGE_VALID; }
-};
-
-// Signed to signed narrowing: Both the upper and lower boundaries may be
-// exceeded.
-template <typename Dst, typename Src>
-struct DstRangeRelationToSrcRangeImpl<Dst,
- Src,
- INTEGER_REPRESENTATION_SIGNED,
- INTEGER_REPRESENTATION_SIGNED,
- NUMERIC_RANGE_NOT_CONTAINED>
-{
- static constexpr RangeConstraint Check(Src value)
- {
- return GetRangeConstraint((value <= NarrowingRange<Dst, Src>::max()),
- (value >= NarrowingRange<Dst, Src>::min()));
- }
-};
-
-// Unsigned to unsigned narrowing: Only the upper boundary can be exceeded.
-template <typename Dst, typename Src>
-struct DstRangeRelationToSrcRangeImpl<Dst,
- Src,
- INTEGER_REPRESENTATION_UNSIGNED,
- INTEGER_REPRESENTATION_UNSIGNED,
- NUMERIC_RANGE_NOT_CONTAINED>
-{
- static constexpr RangeConstraint Check(Src value)
- {
- return GetRangeConstraint(value <= NarrowingRange<Dst, Src>::max(), true);
- }
-};
-
-// Unsigned to signed: The upper boundary may be exceeded.
-template <typename Dst, typename Src>
-struct DstRangeRelationToSrcRangeImpl<Dst,
- Src,
- INTEGER_REPRESENTATION_SIGNED,
- INTEGER_REPRESENTATION_UNSIGNED,
- NUMERIC_RANGE_NOT_CONTAINED>
-{
- static constexpr RangeConstraint Check(Src value)
- {
- return sizeof(Dst) > sizeof(Src)
- ? RANGE_VALID
- : GetRangeConstraint(value <= static_cast<Src>(NarrowingRange<Dst, Src>::max()),
- true);
- }
-};
-
-// Signed to unsigned: The upper boundary may be exceeded for a narrower Dst,
-// and any negative value exceeds the lower boundary.
-template <typename Dst, typename Src>
-struct DstRangeRelationToSrcRangeImpl<Dst,
- Src,
- INTEGER_REPRESENTATION_UNSIGNED,
- INTEGER_REPRESENTATION_SIGNED,
- NUMERIC_RANGE_NOT_CONTAINED>
-{
- static constexpr RangeConstraint Check(Src value)
- {
- return (MaxExponent<Dst>::value >= MaxExponent<Src>::value)
- ? GetRangeConstraint(true, value >= static_cast<Src>(0))
- : GetRangeConstraint(value <= static_cast<Src>(NarrowingRange<Dst, Src>::max()),
- value >= static_cast<Src>(0));
- }
-};
-
-template <typename Dst, typename Src>
-constexpr RangeConstraint DstRangeRelationToSrcRange(Src value)
-{
- static_assert(std::numeric_limits<Src>::is_specialized, "Argument must be numeric.");
- static_assert(std::numeric_limits<Dst>::is_specialized, "Result must be numeric.");
- return DstRangeRelationToSrcRangeImpl<Dst, Src>::Check(value);
-}
-
-} // namespace internal
-} // namespace base
-
-} // namespace angle
-
-#endif // ANGLEBASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_
diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_math.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_math.h
deleted file mode 100644
index 3af4db63f7..0000000000
--- a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_math.h
+++ /dev/null
@@ -1,329 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ANGLEBASE_NUMERICS_SAFE_MATH_H_
-#define ANGLEBASE_NUMERICS_SAFE_MATH_H_
-
-#include <stddef.h>
-
-#include <limits>
-#include <type_traits>
-
-#include "anglebase/logging.h"
-#include "anglebase/numerics/safe_math_impl.h"
-
-namespace angle
-{
-
-namespace base
-{
-
-namespace internal
-{
-
-// CheckedNumeric implements all the logic and operators for detecting integer
-// boundary conditions such as overflow, underflow, and invalid conversions.
-// The CheckedNumeric type implicitly converts from floating point and integer
-// data types, and contains overloads for basic arithmetic operations (i.e.: +,
-// -, *, /, %).
-//
-// The following methods convert from CheckedNumeric to standard numeric values:
-// IsValid() - Returns true if the underlying numeric value is valid (i.e. has
-// has not wrapped and is not the result of an invalid conversion).
-// ValueOrDie() - Returns the underlying value. If the state is not valid this
-// call will crash on a CHECK.
-// ValueOrDefault() - Returns the current value, or the supplied default if the
-// state is not valid.
-// ValueFloating() - Returns the underlying floating point value (valid only
-// only for floating point CheckedNumeric types).
-//
-// Bitwise operations are explicitly not supported, because correct
-// handling of some cases (e.g. sign manipulation) is ambiguous. Comparison
-// operations are explicitly not supported because they could result in a crash
-// on a CHECK condition. You should use patterns like the following for these
-// operations:
-// Bitwise operation:
-// CheckedNumeric<int> checked_int = untrusted_input_value;
-// int x = checked_int.ValueOrDefault(0) | kFlagValues;
-// Comparison:
-// CheckedNumeric<size_t> checked_size = untrusted_input_value;
-// checked_size += HEADER LENGTH;
-// if (checked_size.IsValid() && checked_size.ValueOrDie() < buffer_size)
-// Do stuff...
-template <typename T>
-class CheckedNumeric
-{
- static_assert(std::is_arithmetic<T>::value, "CheckedNumeric<T>: T must be a numeric type.");
-
- public:
- typedef T type;
-
- CheckedNumeric() {}
-
- // Copy constructor.
- template <typename Src>
- CheckedNumeric(const CheckedNumeric<Src> &rhs) : state_(rhs.ValueUnsafe(), rhs.validity())
- {
- }
-
- template <typename Src>
- CheckedNumeric(Src value, RangeConstraint validity) : state_(value, validity)
- {
- }
-
- // This is not an explicit constructor because we implicitly upgrade regular
- // numerics to CheckedNumerics to make them easier to use.
- template <typename Src>
- CheckedNumeric(Src value) // NOLINT(runtime/explicit)
- : state_(value)
- {
- static_assert(std::numeric_limits<Src>::is_specialized, "Argument must be numeric.");
- }
-
- // This is not an explicit constructor because we want a seamless conversion
- // from StrictNumeric types.
- template <typename Src>
- CheckedNumeric(StrictNumeric<Src> value) // NOLINT(runtime/explicit)
- : state_(static_cast<Src>(value))
- {
- }
-
- // IsValid() is the public API to test if a CheckedNumeric is currently valid.
- bool IsValid() const { return validity() == RANGE_VALID; }
-
- // ValueOrDie() The primary accessor for the underlying value. If the current
- // state is not valid it will CHECK and crash.
- T ValueOrDie() const
- {
- CHECK(IsValid());
- return state_.value();
- }
-
- // ValueOrDefault(T default_value) A convenience method that returns the
- // current value if the state is valid, and the supplied default_value for
- // any other state.
- T ValueOrDefault(T default_value) const { return IsValid() ? state_.value() : default_value; }
-
- // ValueFloating() - Since floating point values include their validity state,
- // we provide an easy method for extracting them directly, without a risk of
- // crashing on a CHECK.
- T ValueFloating() const
- {
- static_assert(std::numeric_limits<T>::is_iec559, "Argument must be float.");
- return CheckedNumeric<T>::cast(*this).ValueUnsafe();
- }
-
- // validity() - DO NOT USE THIS IN EXTERNAL CODE - It is public right now for
- // tests and to avoid a big matrix of friend operator overloads. But the
- // values it returns are likely to change in the future.
- // Returns: current validity state (i.e. valid, overflow, underflow, nan).
- // TODO(jschuh): crbug.com/332611 Figure out and implement semantics for
- // saturation/wrapping so we can expose this state consistently and implement
- // saturated arithmetic.
- RangeConstraint validity() const { return state_.validity(); }
-
- // ValueUnsafe() - DO NOT USE THIS IN EXTERNAL CODE - It is public right now
- // for tests and to avoid a big matrix of friend operator overloads. But the
- // values it returns are likely to change in the future.
- // Returns: the raw numeric value, regardless of the current state.
- // TODO(jschuh): crbug.com/332611 Figure out and implement semantics for
- // saturation/wrapping so we can expose this state consistently and implement
- // saturated arithmetic.
- T ValueUnsafe() const { return state_.value(); }
-
- // Prototypes for the supported arithmetic operator overloads.
- template <typename Src>
- CheckedNumeric &operator+=(Src rhs);
- template <typename Src>
- CheckedNumeric &operator-=(Src rhs);
- template <typename Src>
- CheckedNumeric &operator*=(Src rhs);
- template <typename Src>
- CheckedNumeric &operator/=(Src rhs);
- template <typename Src>
- CheckedNumeric &operator%=(Src rhs);
-
- CheckedNumeric operator-() const
- {
- RangeConstraint validity;
- T value = CheckedNeg(state_.value(), &validity);
- // Negation is always valid for floating point.
- if (std::numeric_limits<T>::is_iec559)
- return CheckedNumeric<T>(value);
-
- validity = GetRangeConstraint(state_.validity() | validity);
- return CheckedNumeric<T>(value, validity);
- }
-
- CheckedNumeric Abs() const
- {
- RangeConstraint validity;
- T value = CheckedAbs(state_.value(), &validity);
- // Absolute value is always valid for floating point.
- if (std::numeric_limits<T>::is_iec559)
- return CheckedNumeric<T>(value);
-
- validity = GetRangeConstraint(state_.validity() | validity);
- return CheckedNumeric<T>(value, validity);
- }
-
- // This function is available only for integral types. It returns an unsigned
- // integer of the same width as the source type, containing the absolute value
- // of the source, and properly handling signed min.
- CheckedNumeric<typename UnsignedOrFloatForSize<T>::type> UnsignedAbs() const
- {
- return CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>(
- CheckedUnsignedAbs(state_.value()), state_.validity());
- }
-
- CheckedNumeric &operator++()
- {
- *this += 1;
- return *this;
- }
-
- CheckedNumeric operator++(int)
- {
- CheckedNumeric value = *this;
- *this += 1;
- return value;
- }
-
- CheckedNumeric &operator--()
- {
- *this -= 1;
- return *this;
- }
-
- CheckedNumeric operator--(int)
- {
- CheckedNumeric value = *this;
- *this -= 1;
- return value;
- }
-
- // These static methods behave like a convenience cast operator targeting
- // the desired CheckedNumeric type. As an optimization, a reference is
- // returned when Src is the same type as T.
- template <typename Src>
- static CheckedNumeric<T> cast(
- Src u,
- typename std::enable_if<std::numeric_limits<Src>::is_specialized, int>::type = 0)
- {
- return u;
- }
-
- template <typename Src>
- static CheckedNumeric<T> cast(
- const CheckedNumeric<Src> &u,
- typename std::enable_if<!std::is_same<Src, T>::value, int>::type = 0)
- {
- return u;
- }
-
- static const CheckedNumeric<T> &cast(const CheckedNumeric<T> &u) { return u; }
-
- private:
- template <typename NumericType>
- struct UnderlyingType
- {
- using type = NumericType;
- };
-
- template <typename NumericType>
- struct UnderlyingType<CheckedNumeric<NumericType>>
- {
- using type = NumericType;
- };
-
- CheckedNumericState<T> state_;
-};
-
-// This is the boilerplate for the standard arithmetic operator overloads. A
-// macro isn't the prettiest solution, but it beats rewriting these five times.
-// Some details worth noting are:
-// * We apply the standard arithmetic promotions.
-// * We skip range checks for floating points.
-// * We skip range checks for destination integers with sufficient range.
-// TODO(jschuh): extract these out into templates.
-#define ANGLEBASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP) \
- /* Binary arithmetic operator for CheckedNumerics of the same type. */ \
- template <typename T> \
- CheckedNumeric<typename ArithmeticPromotion<T>::type> operator OP( \
- const CheckedNumeric<T> &lhs, const CheckedNumeric<T> &rhs) \
- { \
- typedef typename ArithmeticPromotion<T>::type Promotion; \
- /* Floating point always takes the fast path */ \
- if (std::numeric_limits<T>::is_iec559) \
- return CheckedNumeric<T>(lhs.ValueUnsafe() OP rhs.ValueUnsafe()); \
- if (IsIntegerArithmeticSafe<Promotion, T, T>::value) \
- return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \
- GetRangeConstraint(rhs.validity() | lhs.validity())); \
- RangeConstraint validity = RANGE_VALID; \
- T result = \
- static_cast<T>(Checked##NAME(static_cast<Promotion>(lhs.ValueUnsafe()), \
- static_cast<Promotion>(rhs.ValueUnsafe()), &validity)); \
- return CheckedNumeric<Promotion>( \
- result, GetRangeConstraint(validity | lhs.validity() | rhs.validity())); \
- } \
- /* Assignment arithmetic operator implementation from CheckedNumeric. */ \
- template <typename T> \
- template <typename Src> \
- CheckedNumeric<T> &CheckedNumeric<T>::operator COMPOUND_OP(Src rhs) \
- { \
- *this = CheckedNumeric<T>::cast(*this) \
- OP CheckedNumeric<typename UnderlyingType<Src>::type>::cast(rhs); \
- return *this; \
- } \
- /* Binary arithmetic operator for CheckedNumeric of different type. */ \
- template <typename T, typename Src> \
- CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \
- const CheckedNumeric<Src> &lhs, const CheckedNumeric<T> &rhs) \
- { \
- typedef typename ArithmeticPromotion<T, Src>::type Promotion; \
- if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \
- return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \
- GetRangeConstraint(rhs.validity() | lhs.validity())); \
- return CheckedNumeric<Promotion>::cast(lhs) OP CheckedNumeric<Promotion>::cast(rhs); \
- } \
- /* Binary arithmetic operator for left CheckedNumeric and right numeric. */ \
- template <typename T, typename Src, \
- typename std::enable_if<std::is_arithmetic<Src>::value>::type * = nullptr> \
- CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \
- const CheckedNumeric<T> &lhs, Src rhs) \
- { \
- typedef typename ArithmeticPromotion<T, Src>::type Promotion; \
- if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \
- return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs, lhs.validity()); \
- return CheckedNumeric<Promotion>::cast(lhs) OP CheckedNumeric<Promotion>::cast(rhs); \
- } \
- /* Binary arithmetic operator for left numeric and right CheckedNumeric. */ \
- template <typename T, typename Src, \
- typename std::enable_if<std::is_arithmetic<Src>::value>::type * = nullptr> \
- CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \
- Src lhs, const CheckedNumeric<T> &rhs) \
- { \
- typedef typename ArithmeticPromotion<T, Src>::type Promotion; \
- if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \
- return CheckedNumeric<Promotion>(lhs OP rhs.ValueUnsafe(), rhs.validity()); \
- return CheckedNumeric<Promotion>::cast(lhs) OP CheckedNumeric<Promotion>::cast(rhs); \
- }
-
-ANGLEBASE_NUMERIC_ARITHMETIC_OPERATORS(Add, +, +=)
-ANGLEBASE_NUMERIC_ARITHMETIC_OPERATORS(Sub, -, -=)
-ANGLEBASE_NUMERIC_ARITHMETIC_OPERATORS(Mul, *, *=)
-ANGLEBASE_NUMERIC_ARITHMETIC_OPERATORS(Div, /, /=)
-ANGLEBASE_NUMERIC_ARITHMETIC_OPERATORS(Mod, %, %=)
-
-#undef ANGLEBASE_NUMERIC_ARITHMETIC_OPERATORS
-
-} // namespace internal
-
-using internal::CheckedNumeric;
-
-} // namespace base
-
-} // namespace angle
-
-#endif // ANGLEBASE_NUMERICS_SAFE_MATH_H_
diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_math_impl.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_math_impl.h
deleted file mode 100644
index 2831cc6ceb..0000000000
--- a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_math_impl.h
+++ /dev/null
@@ -1,575 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ANGLEBASE_NUMERICS_SAFE_MATH_IMPL_H_
-#define ANGLEBASE_NUMERICS_SAFE_MATH_IMPL_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <climits>
-#include <cmath>
-#include <cstdlib>
-#include <limits>
-#include <type_traits>
-
-#include "anglebase/numerics/safe_conversions.h"
-
-namespace angle
-{
-
-namespace base
-{
-namespace internal
-{
-
-// Everything from here up to the floating point operations is portable C++,
-// but it may not be fast. This code could be split based on
-// platform/architecture and replaced with potentially faster implementations.
-
-// Integer promotion templates used by the portable checked integer arithmetic.
-template <size_t Size, bool IsSigned>
-struct IntegerForSizeAndSign;
-template <>
-struct IntegerForSizeAndSign<1, true>
-{
- typedef int8_t type;
-};
-template <>
-struct IntegerForSizeAndSign<1, false>
-{
- typedef uint8_t type;
-};
-template <>
-struct IntegerForSizeAndSign<2, true>
-{
- typedef int16_t type;
-};
-template <>
-struct IntegerForSizeAndSign<2, false>
-{
- typedef uint16_t type;
-};
-template <>
-struct IntegerForSizeAndSign<4, true>
-{
- typedef int32_t type;
-};
-template <>
-struct IntegerForSizeAndSign<4, false>
-{
- typedef uint32_t type;
-};
-template <>
-struct IntegerForSizeAndSign<8, true>
-{
- typedef int64_t type;
-};
-template <>
-struct IntegerForSizeAndSign<8, false>
-{
- typedef uint64_t type;
-};
-
-// WARNING: We have no IntegerForSizeAndSign<16, *>. If we ever add one to
-// support 128-bit math, then the ArithmeticPromotion template below will need
-// to be updated (or more likely replaced with a decltype expression).
-
-template <typename Integer>
-struct UnsignedIntegerForSize
-{
- typedef
- typename std::enable_if<std::numeric_limits<Integer>::is_integer,
- typename IntegerForSizeAndSign<sizeof(Integer), false>::type>::type
- type;
-};
-
-template <typename Integer>
-struct SignedIntegerForSize
-{
- typedef
- typename std::enable_if<std::numeric_limits<Integer>::is_integer,
- typename IntegerForSizeAndSign<sizeof(Integer), true>::type>::type
- type;
-};
-
-template <typename Integer>
-struct TwiceWiderInteger
-{
- typedef typename std::enable_if<
- std::numeric_limits<Integer>::is_integer,
- typename IntegerForSizeAndSign<sizeof(Integer) * 2,
- std::numeric_limits<Integer>::is_signed>::type>::type type;
-};
-
-template <typename Integer>
-struct PositionOfSignBit
-{
- static const typename std::enable_if<std::numeric_limits<Integer>::is_integer, size_t>::type
- value = CHAR_BIT * sizeof(Integer) - 1;
-};
-
-// This is used for UnsignedAbs, where we need to support floating-point
-// template instantiations even though we don't actually support the operations.
-// However, there is no corresponding implementation of e.g. CheckedUnsignedAbs,
-// so the float versions will not compile.
-template <typename Numeric,
- bool IsInteger = std::numeric_limits<Numeric>::is_integer,
- bool IsFloat = std::numeric_limits<Numeric>::is_iec559>
-struct UnsignedOrFloatForSize;
-
-template <typename Numeric>
-struct UnsignedOrFloatForSize<Numeric, true, false>
-{
- typedef typename UnsignedIntegerForSize<Numeric>::type type;
-};
-
-template <typename Numeric>
-struct UnsignedOrFloatForSize<Numeric, false, true>
-{
- typedef Numeric type;
-};
-
-// Helper templates for integer manipulations.
-
-template <typename T>
-constexpr bool HasSignBit(T x)
-{
- // Cast to unsigned since right shift on signed is undefined.
- return !!(static_cast<typename UnsignedIntegerForSize<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);
-}
-
-// Here are the actual portable checked integer math implementations.
-// TODO(jschuh): Break this code out from the enable_if pattern and find a clean
-// way to coalesce things into the CheckedNumericState specializations below.
-
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer, T>::type
-CheckedAdd(T x, T y, RangeConstraint *validity)
-{
- // Since the value of x+y is undefined if we have a signed type, we compute
- // it using the unsigned type of the same size.
- typedef typename UnsignedIntegerForSize<T>::type UnsignedDst;
- UnsignedDst ux = static_cast<UnsignedDst>(x);
- UnsignedDst uy = static_cast<UnsignedDst>(y);
- UnsignedDst uresult = static_cast<UnsignedDst>(ux + uy);
- // Addition is valid if the sign of (x + y) is equal to either that of x or
- // that of y.
- if (std::numeric_limits<T>::is_signed)
- {
- if (HasSignBit(BinaryComplement(static_cast<UnsignedDst>((uresult ^ ux) & (uresult ^ uy)))))
- {
- *validity = RANGE_VALID;
- }
- else
- { // Direction of wrap is inverse of result sign.
- *validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW;
- }
- }
- else
- { // Unsigned is either valid or overflow.
- *validity = BinaryComplement(x) >= y ? RANGE_VALID : RANGE_OVERFLOW;
- }
- return static_cast<T>(uresult);
-}
-
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer, T>::type
-CheckedSub(T x, T y, RangeConstraint *validity)
-{
- // Since the value of x+y is undefined if we have a signed type, we compute
- // it using the unsigned type of the same size.
- typedef typename UnsignedIntegerForSize<T>::type UnsignedDst;
- UnsignedDst ux = static_cast<UnsignedDst>(x);
- UnsignedDst uy = static_cast<UnsignedDst>(y);
- UnsignedDst uresult = static_cast<UnsignedDst>(ux - uy);
- // Subtraction is valid if either x and y have same sign, or (x-y) and x have
- // the same sign.
- if (std::numeric_limits<T>::is_signed)
- {
- if (HasSignBit(BinaryComplement(static_cast<UnsignedDst>((uresult ^ ux) & (ux ^ uy)))))
- {
- *validity = RANGE_VALID;
- }
- else
- { // Direction of wrap is inverse of result sign.
- *validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW;
- }
- }
- else
- { // Unsigned is either valid or underflow.
- *validity = x >= y ? RANGE_VALID : RANGE_UNDERFLOW;
- }
- return static_cast<T>(uresult);
-}
-
-// Integer multiplication is a bit complicated. In the fast case we just
-// we just promote to a twice wider type, and range check the result. In the
-// slow case we need to manually check that the result won't be truncated by
-// checking with division against the appropriate bound.
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer && sizeof(T) * 2 <= sizeof(uintmax_t),
- T>::type
-CheckedMul(T x, T y, RangeConstraint *validity)
-{
- typedef typename TwiceWiderInteger<T>::type IntermediateType;
- IntermediateType tmp = static_cast<IntermediateType>(x) * static_cast<IntermediateType>(y);
- *validity = DstRangeRelationToSrcRange<T>(tmp);
- return static_cast<T>(tmp);
-}
-
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed &&
- (sizeof(T) * 2 > sizeof(uintmax_t)),
- T>::type
-CheckedMul(T x, T y, RangeConstraint *validity)
-{
- // If either side is zero then the result will be zero.
- if (!x || !y)
- {
- *validity = RANGE_VALID;
- return static_cast<T>(0);
- }
- else if (x > 0)
- {
- if (y > 0)
- *validity = x <= std::numeric_limits<T>::max() / y ? RANGE_VALID : RANGE_OVERFLOW;
- else
- *validity = y >= std::numeric_limits<T>::min() / x ? RANGE_VALID : RANGE_UNDERFLOW;
- }
- else
- {
- if (y > 0)
- *validity = x >= std::numeric_limits<T>::min() / y ? RANGE_VALID : RANGE_UNDERFLOW;
- else
- *validity = y >= std::numeric_limits<T>::max() / x ? RANGE_VALID : RANGE_OVERFLOW;
- }
-
- return static_cast<T>(x * y);
-}
-
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed &&
- (sizeof(T) * 2 > sizeof(uintmax_t)),
- T>::type
-CheckedMul(T x, T y, RangeConstraint *validity)
-{
- *validity = (y == 0 || x <= std::numeric_limits<T>::max() / y) ? RANGE_VALID : RANGE_OVERFLOW;
- return static_cast<T>(x * y);
-}
-
-// Division just requires a check for an invalid negation on signed min/-1.
-template <typename T>
-T CheckedDiv(T x,
- T y,
- RangeConstraint *validity,
- typename std::enable_if<std::numeric_limits<T>::is_integer, int>::type = 0)
-{
- if (std::numeric_limits<T>::is_signed && x == std::numeric_limits<T>::min() &&
- y == static_cast<T>(-1))
- {
- *validity = RANGE_OVERFLOW;
- return std::numeric_limits<T>::min();
- }
-
- *validity = RANGE_VALID;
- return static_cast<T>(x / y);
-}
-
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed,
- T>::type
-CheckedMod(T x, T y, RangeConstraint *validity)
-{
- *validity = y > 0 ? RANGE_VALID : RANGE_INVALID;
- return static_cast<T>(x % y);
-}
-
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed,
- T>::type
-CheckedMod(T x, T y, RangeConstraint *validity)
-{
- *validity = RANGE_VALID;
- return static_cast<T>(x % y);
-}
-
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed,
- T>::type
-CheckedNeg(T value, RangeConstraint *validity)
-{
- *validity = value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW;
- // The negation of signed min is min, so catch that one.
- return static_cast<T>(-value);
-}
-
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed,
- T>::type
-CheckedNeg(T value, RangeConstraint *validity)
-{
- // The only legal unsigned negation is zero.
- *validity = value ? RANGE_UNDERFLOW : RANGE_VALID;
- return static_cast<T>(-static_cast<typename SignedIntegerForSize<T>::type>(value));
-}
-
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed,
- T>::type
-CheckedAbs(T value, RangeConstraint *validity)
-{
- *validity = value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW;
- return static_cast<T>(std::abs(value));
-}
-
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed,
- T>::type
-CheckedAbs(T value, RangeConstraint *validity)
-{
- // T is unsigned, so |value| must already be positive.
- *validity = RANGE_VALID;
- return value;
-}
-
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed,
- typename UnsignedIntegerForSize<T>::type>::type
-CheckedUnsignedAbs(T value)
-{
- typedef typename UnsignedIntegerForSize<T>::type UnsignedT;
- return value == std::numeric_limits<T>::min()
- ? static_cast<UnsignedT>(std::numeric_limits<T>::max()) + 1
- : static_cast<UnsignedT>(std::abs(value));
-}
-
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed,
- T>::type
-CheckedUnsignedAbs(T value)
-{
- // T is unsigned, so |value| must already be positive.
- return static_cast<T>(value);
-}
-
-// These are the floating point stubs that the compiler needs to see. Only the
-// negation operation is ever called.
-#define ANGLEBASE_FLOAT_ARITHMETIC_STUBS(NAME) \
- template <typename T> \
- typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type Checked##NAME( \
- T, T, RangeConstraint *) \
- { \
- NOTREACHED(); \
- return static_cast<T>(0); \
- }
-
-ANGLEBASE_FLOAT_ARITHMETIC_STUBS(Add)
-ANGLEBASE_FLOAT_ARITHMETIC_STUBS(Sub)
-ANGLEBASE_FLOAT_ARITHMETIC_STUBS(Mul)
-ANGLEBASE_FLOAT_ARITHMETIC_STUBS(Div)
-ANGLEBASE_FLOAT_ARITHMETIC_STUBS(Mod)
-
-#undef ANGLEBASE_FLOAT_ARITHMETIC_STUBS
-
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type CheckedNeg(T value,
- RangeConstraint *)
-{
- return static_cast<T>(-value);
-}
-
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type CheckedAbs(T value,
- RangeConstraint *)
-{
- return static_cast<T>(std::abs(value));
-}
-
-// Floats carry around their validity state with them, but integers do not. So,
-// we wrap the underlying value in a specialization in order to hide that detail
-// and expose an interface via accessors.
-enum NumericRepresentation
-{
- NUMERIC_INTEGER,
- NUMERIC_FLOATING,
- NUMERIC_UNKNOWN
-};
-
-template <typename NumericType>
-struct GetNumericRepresentation
-{
- static const NumericRepresentation value =
- std::numeric_limits<NumericType>::is_integer
- ? NUMERIC_INTEGER
- : (std::numeric_limits<NumericType>::is_iec559 ? NUMERIC_FLOATING : NUMERIC_UNKNOWN);
-};
-
-template <typename T, NumericRepresentation type = GetNumericRepresentation<T>::value>
-class CheckedNumericState
-{
-};
-
-// Integrals require quite a bit of additional housekeeping to manage state.
-template <typename T>
-class CheckedNumericState<T, NUMERIC_INTEGER>
-{
- private:
- T value_;
- RangeConstraint validity_ : CHAR_BIT; // Actually requires only two bits.
-
- public:
- template <typename Src, NumericRepresentation type>
- friend class CheckedNumericState;
-
- CheckedNumericState() : value_(0), validity_(RANGE_VALID) {}
-
- template <typename Src>
- CheckedNumericState(Src value, RangeConstraint validity)
- : value_(static_cast<T>(value)),
- validity_(GetRangeConstraint(validity | DstRangeRelationToSrcRange<T>(value)))
- {
- static_assert(std::numeric_limits<Src>::is_specialized, "Argument must be numeric.");
- }
-
- // Copy constructor.
- template <typename Src>
- CheckedNumericState(const CheckedNumericState<Src> &rhs)
- : value_(static_cast<T>(rhs.value())),
- validity_(GetRangeConstraint(rhs.validity() | DstRangeRelationToSrcRange<T>(rhs.value())))
- {
- }
-
- template <typename Src>
- explicit CheckedNumericState(
- Src value,
- typename std::enable_if<std::numeric_limits<Src>::is_specialized, int>::type = 0)
- : value_(static_cast<T>(value)), validity_(DstRangeRelationToSrcRange<T>(value))
- {
- }
-
- RangeConstraint validity() const { return validity_; }
- T value() const { return value_; }
-};
-
-// Floating points maintain their own validity, but need translation wrappers.
-template <typename T>
-class CheckedNumericState<T, NUMERIC_FLOATING>
-{
- private:
- T value_;
-
- public:
- template <typename Src, NumericRepresentation type>
- friend class CheckedNumericState;
-
- CheckedNumericState() : value_(0.0) {}
-
- template <typename Src>
- CheckedNumericState(
- Src value,
- RangeConstraint validity,
- typename std::enable_if<std::numeric_limits<Src>::is_integer, int>::type = 0)
- {
- switch (DstRangeRelationToSrcRange<T>(value))
- {
- case RANGE_VALID:
- value_ = static_cast<T>(value);
- break;
-
- case RANGE_UNDERFLOW:
- value_ = -std::numeric_limits<T>::infinity();
- break;
-
- case RANGE_OVERFLOW:
- value_ = std::numeric_limits<T>::infinity();
- break;
-
- case RANGE_INVALID:
- value_ = std::numeric_limits<T>::quiet_NaN();
- break;
-
- default:
- NOTREACHED();
- }
- }
-
- template <typename Src>
- explicit CheckedNumericState(
- Src value,
- typename std::enable_if<std::numeric_limits<Src>::is_specialized, int>::type = 0)
- : value_(static_cast<T>(value))
- {
- }
-
- // Copy constructor.
- template <typename Src>
- CheckedNumericState(const CheckedNumericState<Src> &rhs) : value_(static_cast<T>(rhs.value()))
- {
- }
-
- RangeConstraint validity() const
- {
- return GetRangeConstraint(value_ <= std::numeric_limits<T>::max(),
- value_ >= -std::numeric_limits<T>::max());
- }
- T value() const { return value_; }
-};
-
-// For integers less than 128-bit and floats 32-bit or larger, we have the type
-// with the larger maximum exponent take precedence.
-enum ArithmeticPromotionCategory
-{
- LEFT_PROMOTION,
- RIGHT_PROMOTION
-};
-
-template <typename Lhs,
- typename Rhs = Lhs,
- ArithmeticPromotionCategory Promotion =
- (MaxExponent<Lhs>::value > MaxExponent<Rhs>::value) ? LEFT_PROMOTION
- : RIGHT_PROMOTION>
-struct ArithmeticPromotion;
-
-template <typename Lhs, typename Rhs>
-struct ArithmeticPromotion<Lhs, Rhs, LEFT_PROMOTION>
-{
- typedef Lhs type;
-};
-
-template <typename Lhs, typename Rhs>
-struct ArithmeticPromotion<Lhs, Rhs, RIGHT_PROMOTION>
-{
- typedef Rhs type;
-};
-
-// We can statically check if operations on the provided types can wrap, so we
-// can skip the checked operations if they're not needed. So, for an integer we
-// care if the destination type preserves the sign and is twice the width of
-// the source.
-template <typename T, typename Lhs, typename Rhs>
-struct IsIntegerArithmeticSafe
-{
- static const bool value =
- !std::numeric_limits<T>::is_iec559 &&
- StaticDstRangeRelationToSrcRange<T, Lhs>::value == NUMERIC_RANGE_CONTAINED &&
- sizeof(T) >= (2 * sizeof(Lhs)) &&
- StaticDstRangeRelationToSrcRange<T, Rhs>::value != NUMERIC_RANGE_CONTAINED &&
- sizeof(T) >= (2 * sizeof(Rhs));
-};
-
-} // namespace internal
-} // namespace base
-
-} // namespace angle
-
-#endif // ANGLEBASE_NUMERICS_SAFE_MATH_IMPL_H_
diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_numerics_unittest.cc b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_numerics_unittest.cc
deleted file mode 100644
index 052d850427..0000000000
--- a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_numerics_unittest.cc
+++ /dev/null
@@ -1,771 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <limits>
-#include <type_traits>
-
-#include "base/compiler_specific.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/numerics/safe_math.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
-#include <mmintrin.h>
-#endif
-
-using std::numeric_limits;
-using base::CheckedNumeric;
-using base::checked_cast;
-using base::IsValueInRangeForNumericType;
-using base::IsValueNegative;
-using base::SizeT;
-using base::StrictNumeric;
-using base::saturated_cast;
-using base::strict_cast;
-using base::internal::MaxExponent;
-using base::internal::RANGE_VALID;
-using base::internal::RANGE_INVALID;
-using base::internal::RANGE_OVERFLOW;
-using base::internal::RANGE_UNDERFLOW;
-using base::internal::SignedIntegerForSize;
-
-// These tests deliberately cause arithmetic overflows. If the compiler is
-// aggressive enough, it can const fold these overflows. Disable warnings about
-// overflows for const expressions.
-#if defined(OS_WIN)
-#pragma warning(disable : 4756)
-#endif
-
-// This is a helper function for finding the maximum value in Src that can be
-// wholy represented as the destination floating-point type.
-template <typename Dst, typename Src>
-Dst GetMaxConvertibleToFloat()
-{
- typedef numeric_limits<Dst> DstLimits;
- typedef numeric_limits<Src> SrcLimits;
- static_assert(SrcLimits::is_specialized, "Source must be numeric.");
- static_assert(DstLimits::is_specialized, "Destination must be numeric.");
- CHECK(DstLimits::is_iec559);
-
- if (SrcLimits::digits <= DstLimits::digits &&
- MaxExponent<Src>::value <= MaxExponent<Dst>::value)
- return SrcLimits::max();
- Src max = SrcLimits::max() / 2 + (SrcLimits::is_integer ? 1 : 0);
- while (max != static_cast<Src>(static_cast<Dst>(max)))
- {
- max /= 2;
- }
- return static_cast<Dst>(max);
-}
-
-// Helper macros to wrap displaying the conversion types and line numbers.
-#define TEST_EXPECTED_VALIDITY(expected, actual) \
- EXPECT_EQ(expected, CheckedNumeric<Dst>(actual).IsValid()) \
- << "Result test: Value " << +(actual).ValueUnsafe() << " as " << dst << " on line " \
- << line;
-
-#define TEST_EXPECTED_SUCCESS(actual) TEST_EXPECTED_VALIDITY(true, actual)
-#define TEST_EXPECTED_FAILURE(actual) TEST_EXPECTED_VALIDITY(false, actual)
-
-#define TEST_EXPECTED_VALUE(expected, actual) \
- EXPECT_EQ(static_cast<Dst>(expected), CheckedNumeric<Dst>(actual).ValueUnsafe()) \
- << "Result test: Value " << +((actual).ValueUnsafe()) << " as " << dst << " on line " \
- << line;
-
-// Signed integer arithmetic.
-template <typename Dst>
-static void TestSpecializedArithmetic(
- const char *dst,
- int line,
- typename std::enable_if<numeric_limits<Dst>::is_integer && numeric_limits<Dst>::is_signed,
- int>::type = 0)
-{
- typedef numeric_limits<Dst> DstLimits;
- TEST_EXPECTED_FAILURE(-CheckedNumeric<Dst>(DstLimits::min()));
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()).Abs());
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
-
- TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + -1);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) + -1);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) + -DstLimits::max());
-
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) - 1);
- TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) - -1);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - -DstLimits::max());
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) - DstLimits::max());
-
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) * 2);
-
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) / -1);
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) / 2);
-
- // Modulus is legal only for integers.
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
- TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % 2);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-1) % -2);
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) % 2);
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
- // Test all the different modulus combinations.
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
- CheckedNumeric<Dst> checked_dst = 1;
- TEST_EXPECTED_VALUE(0, checked_dst %= 1);
-}
-
-// Unsigned integer arithmetic.
-template <typename Dst>
-static void TestSpecializedArithmetic(
- const char *dst,
- int line,
- typename std::enable_if<numeric_limits<Dst>::is_integer && !numeric_limits<Dst>::is_signed,
- int>::type = 0)
-{
- typedef numeric_limits<Dst> DstLimits;
- TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::min()));
- TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).Abs());
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) + -1);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) - 1);
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) * 2);
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) / 2);
- TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).UnsignedAbs());
- TEST_EXPECTED_SUCCESS(CheckedNumeric<typename SignedIntegerForSize<Dst>::type>(
- std::numeric_limits<typename SignedIntegerForSize<Dst>::type>::min())
- .UnsignedAbs());
-
- // Modulus is legal only for integers.
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % 2);
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) % 2);
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
- // Test all the different modulus combinations.
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
- CheckedNumeric<Dst> checked_dst = 1;
- TEST_EXPECTED_VALUE(0, checked_dst %= 1);
-}
-
-// Floating point arithmetic.
-template <typename Dst>
-void TestSpecializedArithmetic(
- const char *dst,
- int line,
- typename std::enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0)
-{
- typedef numeric_limits<Dst> DstLimits;
- TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::min()));
-
- TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).Abs());
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
-
- TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) + -1);
- TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + 1);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) + -DstLimits::max());
-
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - -DstLimits::max());
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) - DstLimits::max());
-
- TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) * 2);
-
- TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2);
- EXPECT_EQ(static_cast<Dst>(1.0), CheckedNumeric<Dst>(1.0).ValueFloating());
-}
-
-// Generic arithmetic tests.
-template <typename Dst>
-static void TestArithmetic(const char *dst, int line)
-{
- typedef numeric_limits<Dst> DstLimits;
-
- EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid());
- EXPECT_EQ(
- false,
- CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) * DstLimits::max()).IsValid());
- EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDie());
- EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDefault(1));
- EXPECT_EQ(static_cast<Dst>(1),
- CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) * DstLimits::max())
- .ValueOrDefault(1));
-
- // Test the operator combinations.
- TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(2, 1 + CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(0, 1 - CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(1, 1 * CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(1, 1 / CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + 1);
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - 1);
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * 1);
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
- CheckedNumeric<Dst> checked_dst = 1;
- TEST_EXPECTED_VALUE(2, checked_dst += 1);
- checked_dst = 1;
- TEST_EXPECTED_VALUE(0, checked_dst -= 1);
- checked_dst = 1;
- TEST_EXPECTED_VALUE(1, checked_dst *= 1);
- checked_dst = 1;
- TEST_EXPECTED_VALUE(1, checked_dst /= 1);
-
- // Generic negation.
- TEST_EXPECTED_VALUE(0, -CheckedNumeric<Dst>());
- TEST_EXPECTED_VALUE(-1, -CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(1, -CheckedNumeric<Dst>(-1));
- TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
- -CheckedNumeric<Dst>(DstLimits::max()));
-
- // Generic absolute value.
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>().Abs());
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).Abs());
- TEST_EXPECTED_VALUE(DstLimits::max(), CheckedNumeric<Dst>(DstLimits::max()).Abs());
-
- // Generic addition.
- TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>() + 1));
- TEST_EXPECTED_VALUE(2, (CheckedNumeric<Dst>(1) + 1));
- TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) + 1));
- TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) + 1);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) + DstLimits::max());
-
- // Generic subtraction.
- TEST_EXPECTED_VALUE(-1, (CheckedNumeric<Dst>() - 1));
- TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(1) - 1));
- TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) - 1));
- TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) - 1);
-
- // Generic multiplication.
- TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>() * 1));
- TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>(1) * 1));
- TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) * 2));
- TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * 0));
- TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) * 0));
- TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * -1));
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) * DstLimits::max());
-
- // Generic division.
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() / 1);
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
- TEST_EXPECTED_VALUE(DstLimits::min() / 2, CheckedNumeric<Dst>(DstLimits::min()) / 2);
- TEST_EXPECTED_VALUE(DstLimits::max() / 2, CheckedNumeric<Dst>(DstLimits::max()) / 2);
-
- TestSpecializedArithmetic<Dst>(dst, line);
-}
-
-// Helper macro to wrap displaying the conversion types and line numbers.
-#define TEST_ARITHMETIC(Dst) TestArithmetic<Dst>(#Dst, __LINE__)
-
-TEST(SafeNumerics, SignedIntegerMath)
-{
- TEST_ARITHMETIC(int8_t);
- TEST_ARITHMETIC(int);
- TEST_ARITHMETIC(intptr_t);
- TEST_ARITHMETIC(intmax_t);
-}
-
-TEST(SafeNumerics, UnsignedIntegerMath)
-{
- TEST_ARITHMETIC(uint8_t);
- TEST_ARITHMETIC(unsigned int);
- TEST_ARITHMETIC(uintptr_t);
- TEST_ARITHMETIC(uintmax_t);
-}
-
-TEST(SafeNumerics, FloatingPointMath)
-{
- TEST_ARITHMETIC(float);
- TEST_ARITHMETIC(double);
-}
-
-// Enumerates the five different conversions types we need to test.
-enum NumericConversionType
-{
- SIGN_PRESERVING_VALUE_PRESERVING,
- SIGN_PRESERVING_NARROW,
- SIGN_TO_UNSIGN_WIDEN_OR_EQUAL,
- SIGN_TO_UNSIGN_NARROW,
- UNSIGN_TO_SIGN_NARROW_OR_EQUAL,
-};
-
-// Template covering the different conversion tests.
-template <typename Dst, typename Src, NumericConversionType conversion>
-struct TestNumericConversion
-{
-};
-
-// EXPECT_EQ wrappers providing specific detail on test failures.
-#define TEST_EXPECTED_RANGE(expected, actual) \
- EXPECT_EQ(expected, base::internal::DstRangeRelationToSrcRange<Dst>(actual)) \
- << "Conversion test: " << src << " value " << actual << " to " << dst << " on line " \
- << line;
-
-template <typename Dst, typename Src>
-struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING>
-{
- static void Test(const char *dst, const char *src, int line)
- {
- typedef numeric_limits<Src> SrcLimits;
- typedef numeric_limits<Dst> DstLimits;
- // Integral to floating.
- static_assert(
- (DstLimits::is_iec559 && SrcLimits::is_integer) ||
- // Not floating to integral and...
- (!(DstLimits::is_integer && SrcLimits::is_iec559) &&
- // Same sign, same numeric, source is narrower or same.
- ((SrcLimits::is_signed == DstLimits::is_signed && sizeof(Dst) >= sizeof(Src)) ||
- // Or signed destination and source is smaller
- (DstLimits::is_signed && sizeof(Dst) > sizeof(Src)))),
- "Comparison must be sign preserving and value preserving");
-
- const CheckedNumeric<Dst> checked_dst = SrcLimits::max();
- TEST_EXPECTED_SUCCESS(checked_dst);
- if (MaxExponent<Dst>::value > MaxExponent<Src>::value)
- {
- if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1)
- {
- // At least twice larger type.
- TEST_EXPECTED_SUCCESS(SrcLimits::max() * checked_dst);
- }
- else
- { // Larger, but not at least twice as large.
- TEST_EXPECTED_FAILURE(SrcLimits::max() * checked_dst);
- TEST_EXPECTED_SUCCESS(checked_dst + 1);
- }
- }
- else
- { // Same width type.
- TEST_EXPECTED_FAILURE(checked_dst + 1);
- }
-
- TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
- if (SrcLimits::is_iec559)
- {
- TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max() * static_cast<Src>(-1));
- TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
- TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
- TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
- }
- else if (numeric_limits<Src>::is_signed)
- {
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
- TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
- }
- }
-};
-
-template <typename Dst, typename Src>
-struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW>
-{
- static void Test(const char *dst, const char *src, int line)
- {
- typedef numeric_limits<Src> SrcLimits;
- typedef numeric_limits<Dst> DstLimits;
- static_assert(SrcLimits::is_signed == DstLimits::is_signed,
- "Destination and source sign must be the same");
- static_assert(sizeof(Dst) < sizeof(Src) || (DstLimits::is_integer && SrcLimits::is_iec559),
- "Destination must be narrower than source");
-
- const CheckedNumeric<Dst> checked_dst;
- TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
- TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
- TEST_EXPECTED_FAILURE(checked_dst - SrcLimits::max());
-
- TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
- if (SrcLimits::is_iec559)
- {
- TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
- TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
- TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
- TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
- if (DstLimits::is_integer)
- {
- if (SrcLimits::digits < DstLimits::digits)
- {
- TEST_EXPECTED_RANGE(RANGE_OVERFLOW, static_cast<Src>(DstLimits::max()));
- }
- else
- {
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
- }
- TEST_EXPECTED_RANGE(RANGE_VALID,
- static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::min()));
- }
- }
- else if (SrcLimits::is_signed)
- {
- TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1));
- TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
- }
- else
- {
- TEST_EXPECTED_FAILURE(checked_dst - static_cast<Src>(1));
- TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
- }
- }
-};
-
-template <typename Dst, typename Src>
-struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL>
-{
- static void Test(const char *dst, const char *src, int line)
- {
- typedef numeric_limits<Src> SrcLimits;
- typedef numeric_limits<Dst> DstLimits;
- static_assert(sizeof(Dst) >= sizeof(Src),
- "Destination must be equal or wider than source.");
- static_assert(SrcLimits::is_signed, "Source must be signed");
- static_assert(!DstLimits::is_signed, "Destination must be unsigned");
-
- const CheckedNumeric<Dst> checked_dst;
- TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max());
- TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
- TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max());
-
- TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
- TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
- TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
- }
-};
-
-template <typename Dst, typename Src>
-struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW>
-{
- static void Test(const char *dst, const char *src, int line)
- {
- typedef numeric_limits<Src> SrcLimits;
- typedef numeric_limits<Dst> DstLimits;
- static_assert(
- (DstLimits::is_integer && SrcLimits::is_iec559) || (sizeof(Dst) < sizeof(Src)),
- "Destination must be narrower than source.");
- static_assert(SrcLimits::is_signed, "Source must be signed.");
- static_assert(!DstLimits::is_signed, "Destination must be unsigned.");
-
- const CheckedNumeric<Dst> checked_dst;
- TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
- TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
- TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
- TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max());
-
- TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
- TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
- if (SrcLimits::is_iec559)
- {
- TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
- TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
- TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
- TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
- if (DstLimits::is_integer)
- {
- if (SrcLimits::digits < DstLimits::digits)
- {
- TEST_EXPECTED_RANGE(RANGE_OVERFLOW, static_cast<Src>(DstLimits::max()));
- }
- else
- {
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
- }
- TEST_EXPECTED_RANGE(RANGE_VALID,
- static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::min()));
- }
- }
- else
- {
- TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
- }
- }
-};
-
-template <typename Dst, typename Src>
-struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL>
-{
- static void Test(const char *dst, const char *src, int line)
- {
- typedef numeric_limits<Src> SrcLimits;
- typedef numeric_limits<Dst> DstLimits;
- static_assert(sizeof(Dst) <= sizeof(Src),
- "Destination must be narrower or equal to source.");
- static_assert(!SrcLimits::is_signed, "Source must be unsigned.");
- static_assert(DstLimits::is_signed, "Destination must be signed.");
-
- const CheckedNumeric<Dst> checked_dst;
- TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
- TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
- TEST_EXPECTED_VALUE(SrcLimits::min(), checked_dst + SrcLimits::min());
-
- TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
- TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
- }
-};
-
-// Helper macro to wrap displaying the conversion types and line numbers
-#define TEST_NUMERIC_CONVERSION(d, s, t) TestNumericConversion<d, s, t>::Test(#d, #s, __LINE__)
-
-TEST(SafeNumerics, IntMinOperations)
-{
- TEST_NUMERIC_CONVERSION(int8_t, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(uint8_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
-
- TEST_NUMERIC_CONVERSION(int8_t, int, SIGN_PRESERVING_NARROW);
- TEST_NUMERIC_CONVERSION(uint8_t, unsigned int, SIGN_PRESERVING_NARROW);
- TEST_NUMERIC_CONVERSION(int8_t, float, SIGN_PRESERVING_NARROW);
-
- TEST_NUMERIC_CONVERSION(uint8_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
-
- TEST_NUMERIC_CONVERSION(uint8_t, int, SIGN_TO_UNSIGN_NARROW);
- TEST_NUMERIC_CONVERSION(uint8_t, intmax_t, SIGN_TO_UNSIGN_NARROW);
- TEST_NUMERIC_CONVERSION(uint8_t, float, SIGN_TO_UNSIGN_NARROW);
-
- TEST_NUMERIC_CONVERSION(int8_t, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
- TEST_NUMERIC_CONVERSION(int8_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
-}
-
-TEST(SafeNumerics, IntOperations)
-{
- TEST_NUMERIC_CONVERSION(int, int, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(unsigned int, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(int, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(unsigned int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
-
- TEST_NUMERIC_CONVERSION(int, intmax_t, SIGN_PRESERVING_NARROW);
- TEST_NUMERIC_CONVERSION(unsigned int, uintmax_t, SIGN_PRESERVING_NARROW);
- TEST_NUMERIC_CONVERSION(int, float, SIGN_PRESERVING_NARROW);
- TEST_NUMERIC_CONVERSION(int, double, SIGN_PRESERVING_NARROW);
-
- TEST_NUMERIC_CONVERSION(unsigned int, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
- TEST_NUMERIC_CONVERSION(unsigned int, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
-
- TEST_NUMERIC_CONVERSION(unsigned int, intmax_t, SIGN_TO_UNSIGN_NARROW);
- TEST_NUMERIC_CONVERSION(unsigned int, float, SIGN_TO_UNSIGN_NARROW);
- TEST_NUMERIC_CONVERSION(unsigned int, double, SIGN_TO_UNSIGN_NARROW);
-
- TEST_NUMERIC_CONVERSION(int, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
- TEST_NUMERIC_CONVERSION(int, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
-}
-
-TEST(SafeNumerics, IntMaxOperations)
-{
- TEST_NUMERIC_CONVERSION(intmax_t, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(uintmax_t, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(intmax_t, int, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(uintmax_t, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(intmax_t, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(intmax_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
-
- TEST_NUMERIC_CONVERSION(intmax_t, float, SIGN_PRESERVING_NARROW);
- TEST_NUMERIC_CONVERSION(intmax_t, double, SIGN_PRESERVING_NARROW);
-
- TEST_NUMERIC_CONVERSION(uintmax_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
- TEST_NUMERIC_CONVERSION(uintmax_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
-
- TEST_NUMERIC_CONVERSION(uintmax_t, float, SIGN_TO_UNSIGN_NARROW);
- TEST_NUMERIC_CONVERSION(uintmax_t, double, SIGN_TO_UNSIGN_NARROW);
-
- TEST_NUMERIC_CONVERSION(intmax_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
-}
-
-TEST(SafeNumerics, FloatOperations)
-{
- TEST_NUMERIC_CONVERSION(float, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(float, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(float, int, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(float, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
-
- TEST_NUMERIC_CONVERSION(float, double, SIGN_PRESERVING_NARROW);
-}
-
-TEST(SafeNumerics, DoubleOperations)
-{
- TEST_NUMERIC_CONVERSION(double, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(double, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(double, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
-}
-
-TEST(SafeNumerics, SizeTOperations)
-{
- TEST_NUMERIC_CONVERSION(size_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
- TEST_NUMERIC_CONVERSION(int, size_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
-}
-
-TEST(SafeNumerics, CastTests)
-{
-// MSVC catches and warns that we're forcing saturation in these tests.
-// Since that's intentional, we need to shut this warning off.
-#if defined(COMPILER_MSVC)
-#pragma warning(disable : 4756)
-#endif
-
- int small_positive = 1;
- int small_negative = -1;
- double double_small = 1.0;
- double double_large = numeric_limits<double>::max();
- double double_infinity = numeric_limits<float>::infinity();
- double double_large_int = numeric_limits<int>::max();
- double double_small_int = numeric_limits<int>::min();
-
- // Just test that the casts compile, since the other tests cover logic.
- EXPECT_EQ(0, checked_cast<int>(static_cast<size_t>(0)));
- EXPECT_EQ(0, strict_cast<int>(static_cast<char>(0)));
- EXPECT_EQ(0, strict_cast<int>(static_cast<unsigned char>(0)));
- EXPECT_EQ(0U, strict_cast<unsigned>(static_cast<unsigned char>(0)));
- EXPECT_EQ(1ULL, static_cast<uint64_t>(StrictNumeric<size_t>(1U)));
- EXPECT_EQ(1ULL, static_cast<uint64_t>(SizeT(1U)));
- EXPECT_EQ(1U, static_cast<size_t>(StrictNumeric<unsigned>(1U)));
-
- EXPECT_TRUE(CheckedNumeric<uint64_t>(StrictNumeric<unsigned>(1U)).IsValid());
- EXPECT_TRUE(CheckedNumeric<int>(StrictNumeric<unsigned>(1U)).IsValid());
- EXPECT_FALSE(CheckedNumeric<unsigned>(StrictNumeric<int>(-1)).IsValid());
-
- EXPECT_TRUE(IsValueNegative(-1));
- EXPECT_TRUE(IsValueNegative(numeric_limits<int>::min()));
- EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::min()));
- EXPECT_TRUE(IsValueNegative(-numeric_limits<double>::max()));
- EXPECT_FALSE(IsValueNegative(0));
- EXPECT_FALSE(IsValueNegative(1));
- EXPECT_FALSE(IsValueNegative(0u));
- EXPECT_FALSE(IsValueNegative(1u));
- EXPECT_FALSE(IsValueNegative(numeric_limits<int>::max()));
- EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::max()));
- EXPECT_FALSE(IsValueNegative(numeric_limits<double>::max()));
-
- // These casts and coercions will fail to compile:
- // EXPECT_EQ(0, strict_cast<int>(static_cast<size_t>(0)));
- // EXPECT_EQ(0, strict_cast<size_t>(static_cast<int>(0)));
- // EXPECT_EQ(1ULL, StrictNumeric<size_t>(1));
- // EXPECT_EQ(1, StrictNumeric<size_t>(1U));
-
- // Test various saturation corner cases.
- EXPECT_EQ(saturated_cast<int>(small_negative), static_cast<int>(small_negative));
- EXPECT_EQ(saturated_cast<int>(small_positive), static_cast<int>(small_positive));
- EXPECT_EQ(saturated_cast<unsigned>(small_negative), static_cast<unsigned>(0));
- EXPECT_EQ(saturated_cast<int>(double_small), static_cast<int>(double_small));
- EXPECT_EQ(saturated_cast<int>(double_large), numeric_limits<int>::max());
- EXPECT_EQ(saturated_cast<float>(double_large), double_infinity);
- EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity);
- EXPECT_EQ(numeric_limits<int>::min(), saturated_cast<int>(double_small_int));
- EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int));
-
- float not_a_number =
- std::numeric_limits<float>::infinity() - std::numeric_limits<float>::infinity();
- EXPECT_TRUE(std::isnan(not_a_number));
- EXPECT_EQ(0, saturated_cast<int>(not_a_number));
-}
-
-#if GTEST_HAS_DEATH_TEST
-
-TEST(SafeNumerics, SaturatedCastChecks)
-{
- float not_a_number =
- std::numeric_limits<float>::infinity() - std::numeric_limits<float>::infinity();
- EXPECT_TRUE(std::isnan(not_a_number));
- EXPECT_DEATH((saturated_cast<int, base::SaturatedCastNaNBehaviorCheck>(not_a_number)), "");
-}
-
-#endif // GTEST_HAS_DEATH_TEST
-
-TEST(SafeNumerics, IsValueInRangeForNumericType)
-{
- EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0));
- EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(1));
- EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(2));
- EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1));
- EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0xffffffffu));
- EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0xffffffff)));
- EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000000)));
- EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000001)));
- EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(std::numeric_limits<int32_t>::min()));
- EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(std::numeric_limits<int64_t>::min()));
-
- EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0));
- EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(1));
- EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(2));
- EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(-1));
- EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffff));
- EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffffu));
- EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0x80000000u));
- EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0xffffffffu));
- EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x80000000)));
- EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0xffffffff)));
- EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x100000000)));
- EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(std::numeric_limits<int32_t>::min()));
- EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
- static_cast<int64_t>(std::numeric_limits<int32_t>::min())));
- EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
- static_cast<int64_t>(std::numeric_limits<int32_t>::min()) - 1));
- EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(std::numeric_limits<int64_t>::min()));
-
- EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0));
- EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(1));
- EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(2));
- EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1));
- EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0xffffffffu));
- EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0xffffffff)));
- EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000000)));
- EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000001)));
- EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(std::numeric_limits<int32_t>::min()));
- EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(INT64_C(-1)));
- EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(std::numeric_limits<int64_t>::min()));
-
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(1));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(2));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(-1));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffff));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffffu));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x80000000u));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0xffffffffu));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x80000000)));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0xffffffff)));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x100000000)));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x7fffffffffffffff)));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(UINT64_C(0x7fffffffffffffff)));
- EXPECT_FALSE(IsValueInRangeForNumericType<int64_t>(UINT64_C(0x8000000000000000)));
- EXPECT_FALSE(IsValueInRangeForNumericType<int64_t>(UINT64_C(0xffffffffffffffff)));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(std::numeric_limits<int32_t>::min()));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
- static_cast<int64_t>(std::numeric_limits<int32_t>::min())));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(std::numeric_limits<int64_t>::min()));
-}
-
-TEST(SafeNumerics, CompoundNumericOperations)
-{
- CheckedNumeric<int> a = 1;
- CheckedNumeric<int> b = 2;
- CheckedNumeric<int> c = 3;
- CheckedNumeric<int> d = 4;
- a += b;
- EXPECT_EQ(3, a.ValueOrDie());
- a -= c;
- EXPECT_EQ(0, a.ValueOrDie());
- d /= b;
- EXPECT_EQ(2, d.ValueOrDie());
- d *= d;
- EXPECT_EQ(4, d.ValueOrDie());
-
- CheckedNumeric<int> too_large = std::numeric_limits<int>::max();
- EXPECT_TRUE(too_large.IsValid());
- too_large += d;
- EXPECT_FALSE(too_large.IsValid());
- too_large -= d;
- EXPECT_FALSE(too_large.IsValid());
- too_large /= d;
- EXPECT_FALSE(too_large.IsValid());
-}