tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

clamped_math.h (9130B)


      1 // Copyright 2017 The Chromium Authors
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef BASE_NUMERICS_CLAMPED_MATH_H_
      6 #define BASE_NUMERICS_CLAMPED_MATH_H_
      7 
      8 #include <stddef.h>
      9 
     10 #include <limits>
     11 #include <type_traits>
     12 
     13 #include "base/numerics/clamped_math_impl.h"
     14 
     15 namespace base {
     16 namespace internal {
     17 
     18 template <typename T>
     19 class ClampedNumeric {
     20  static_assert(std::is_arithmetic_v<T>,
     21                "ClampedNumeric<T>: T must be a numeric type.");
     22 
     23 public:
     24  using type = T;
     25 
     26  constexpr ClampedNumeric() : value_(0) {}
     27 
     28  // Copy constructor.
     29  template <typename Src>
     30  constexpr ClampedNumeric(const ClampedNumeric<Src>& rhs)
     31      : value_(saturated_cast<T>(rhs.value_)) {}
     32 
     33  template <typename Src>
     34  friend class ClampedNumeric;
     35 
     36  // Strictly speaking, this is not necessary, but declaring this allows class
     37  // template argument deduction to be used so that it is possible to simply
     38  // write `ClampedNumeric(777)` instead of `ClampedNumeric<int>(777)`.
     39  // NOLINTNEXTLINE(google-explicit-constructor)
     40  constexpr ClampedNumeric(T value) : value_(value) {}
     41 
     42  // This is not an explicit constructor because we implicitly upgrade regular
     43  // numerics to ClampedNumerics to make them easier to use.
     44  template <typename Src>
     45  // NOLINTNEXTLINE(google-explicit-constructor)
     46  constexpr ClampedNumeric(Src value) : value_(saturated_cast<T>(value)) {
     47    static_assert(UnderlyingType<Src>::is_numeric, "Argument must be numeric.");
     48  }
     49 
     50  // This is not an explicit constructor because we want a seamless conversion
     51  // from StrictNumeric types.
     52  template <typename Src>
     53  // NOLINTNEXTLINE(google-explicit-constructor)
     54  constexpr ClampedNumeric(StrictNumeric<Src> value)
     55      : value_(saturated_cast<T>(static_cast<Src>(value))) {}
     56 
     57  // Returns a ClampedNumeric of the specified type, cast from the current
     58  // ClampedNumeric, and saturated to the destination type.
     59  template <typename Dst>
     60  constexpr ClampedNumeric<typename UnderlyingType<Dst>::type> Cast() const {
     61    return *this;
     62  }
     63 
     64  // Prototypes for the supported arithmetic operator overloads.
     65  template <typename Src>
     66  constexpr ClampedNumeric& operator+=(const Src rhs);
     67  template <typename Src>
     68  constexpr ClampedNumeric& operator-=(const Src rhs);
     69  template <typename Src>
     70  constexpr ClampedNumeric& operator*=(const Src rhs);
     71  template <typename Src>
     72  constexpr ClampedNumeric& operator/=(const Src rhs);
     73  template <typename Src>
     74  constexpr ClampedNumeric& operator%=(const Src rhs);
     75  template <typename Src>
     76  constexpr ClampedNumeric& operator<<=(const Src rhs);
     77  template <typename Src>
     78  constexpr ClampedNumeric& operator>>=(const Src rhs);
     79  template <typename Src>
     80  constexpr ClampedNumeric& operator&=(const Src rhs);
     81  template <typename Src>
     82  constexpr ClampedNumeric& operator|=(const Src rhs);
     83  template <typename Src>
     84  constexpr ClampedNumeric& operator^=(const Src rhs);
     85 
     86  constexpr ClampedNumeric operator-() const {
     87    // The negation of two's complement int min is int min, so that's the
     88    // only overflow case where we will saturate.
     89    return ClampedNumeric<T>(SaturatedNegWrapper(value_));
     90  }
     91 
     92  constexpr ClampedNumeric operator~() const {
     93    return ClampedNumeric<decltype(InvertWrapper(T()))>(InvertWrapper(value_));
     94  }
     95 
     96  constexpr ClampedNumeric Abs() const {
     97    // The negation of two's complement int min is int min, so that's the
     98    // only overflow case where we will saturate.
     99    return ClampedNumeric<T>(SaturatedAbsWrapper(value_));
    100  }
    101 
    102  template <typename U>
    103  constexpr ClampedNumeric<typename MathWrapper<ClampedMaxOp, T, U>::type> Max(
    104      const U rhs) const {
    105    using result_type = typename MathWrapper<ClampedMaxOp, T, U>::type;
    106    return ClampedNumeric<result_type>(
    107        ClampedMaxOp<T, U>::Do(value_, Wrapper<U>::value(rhs)));
    108  }
    109 
    110  template <typename U>
    111  constexpr ClampedNumeric<typename MathWrapper<ClampedMinOp, T, U>::type> Min(
    112      const U rhs) const {
    113    using result_type = typename MathWrapper<ClampedMinOp, T, U>::type;
    114    return ClampedNumeric<result_type>(
    115        ClampedMinOp<T, U>::Do(value_, Wrapper<U>::value(rhs)));
    116  }
    117 
    118  // This function is available only for integral types. It returns an unsigned
    119  // integer of the same width as the source type, containing the absolute value
    120  // of the source, and properly handling signed min.
    121  constexpr ClampedNumeric<typename UnsignedOrFloatForSize<T>::type>
    122  UnsignedAbs() const {
    123    return ClampedNumeric<typename UnsignedOrFloatForSize<T>::type>(
    124        SafeUnsignedAbs(value_));
    125  }
    126 
    127  constexpr ClampedNumeric& operator++() {
    128    *this += 1;
    129    return *this;
    130  }
    131 
    132  constexpr ClampedNumeric operator++(int) {
    133    ClampedNumeric value = *this;
    134    *this += 1;
    135    return value;
    136  }
    137 
    138  constexpr ClampedNumeric& operator--() {
    139    *this -= 1;
    140    return *this;
    141  }
    142 
    143  constexpr ClampedNumeric operator--(int) {
    144    ClampedNumeric value = *this;
    145    *this -= 1;
    146    return value;
    147  }
    148 
    149  // These perform the actual math operations on the ClampedNumerics.
    150  // Binary arithmetic operations.
    151  template <template <typename, typename, typename> class M,
    152            typename L,
    153            typename R>
    154  static constexpr ClampedNumeric MathOp(const L lhs, const R rhs) {
    155    using Math = typename MathWrapper<M, L, R>::math;
    156    return ClampedNumeric<T>(
    157        Math::template Do<T>(Wrapper<L>::value(lhs), Wrapper<R>::value(rhs)));
    158  }
    159 
    160  // Assignment arithmetic operations.
    161  template <template <typename, typename, typename> class M, typename R>
    162  constexpr ClampedNumeric& MathOp(const R rhs) {
    163    using Math = typename MathWrapper<M, T, R>::math;
    164    *this =
    165        ClampedNumeric<T>(Math::template Do<T>(value_, Wrapper<R>::value(rhs)));
    166    return *this;
    167  }
    168 
    169  template <typename Dst>
    170  constexpr operator Dst() const {
    171    return saturated_cast<typename ArithmeticOrUnderlyingEnum<Dst>::type>(
    172        value_);
    173  }
    174 
    175  // This method extracts the raw integer value without saturating it to the
    176  // destination type as the conversion operator does. This is useful when
    177  // e.g. assigning to an auto type or passing as a deduced template parameter.
    178  constexpr T RawValue() const { return value_; }
    179 
    180 private:
    181  T value_;
    182 
    183  // These wrappers allow us to handle state the same way for both
    184  // ClampedNumeric and POD arithmetic types.
    185  template <typename Src>
    186  struct Wrapper {
    187    static constexpr typename UnderlyingType<Src>::type value(Src value) {
    188      return value;
    189    }
    190  };
    191 };
    192 
    193 // Convenience wrapper to return a new ClampedNumeric from the provided
    194 // arithmetic or ClampedNumericType.
    195 template <typename T>
    196 constexpr ClampedNumeric<typename UnderlyingType<T>::type> MakeClampedNum(
    197    const T value) {
    198  return value;
    199 }
    200 
    201 // These implement the variadic wrapper for the math operations.
    202 template <template <typename, typename, typename> class M,
    203          typename L,
    204          typename R>
    205 constexpr ClampedNumeric<typename MathWrapper<M, L, R>::type> ClampMathOp(
    206    const L lhs,
    207    const R rhs) {
    208  using Math = typename MathWrapper<M, L, R>::math;
    209  return ClampedNumeric<typename Math::result_type>::template MathOp<M>(lhs,
    210                                                                        rhs);
    211 }
    212 
    213 // General purpose wrapper template for arithmetic operations.
    214 template <template <typename, typename, typename> class M,
    215          typename L,
    216          typename R,
    217          typename... Args>
    218 constexpr auto ClampMathOp(const L lhs, const R rhs, const Args... args) {
    219  return ClampMathOp<M>(ClampMathOp<M>(lhs, rhs), args...);
    220 }
    221 
    222 BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Add, +, +=)
    223 BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Sub, -, -=)
    224 BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Mul, *, *=)
    225 BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Div, /, /=)
    226 BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Mod, %, %=)
    227 BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Lsh, <<, <<=)
    228 BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Rsh, >>, >>=)
    229 BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, And, &, &=)
    230 BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Or, |, |=)
    231 BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Xor, ^, ^=)
    232 BASE_NUMERIC_ARITHMETIC_VARIADIC(Clamped, Clamp, Max)
    233 BASE_NUMERIC_ARITHMETIC_VARIADIC(Clamped, Clamp, Min)
    234 BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsLess, <)
    235 BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsLessOrEqual, <=)
    236 BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsGreater, >)
    237 BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsGreaterOrEqual, >=)
    238 BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsEqual, ==)
    239 BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsNotEqual, !=)
    240 
    241 }  // namespace internal
    242 
    243 using internal::ClampAdd;
    244 using internal::ClampAnd;
    245 using internal::ClampDiv;
    246 using internal::ClampedNumeric;
    247 using internal::ClampLsh;
    248 using internal::ClampMax;
    249 using internal::ClampMin;
    250 using internal::ClampMod;
    251 using internal::ClampMul;
    252 using internal::ClampOr;
    253 using internal::ClampRsh;
    254 using internal::ClampSub;
    255 using internal::ClampXor;
    256 using internal::MakeClampedNum;
    257 
    258 }  // namespace base
    259 
    260 #endif  // BASE_NUMERICS_CLAMPED_MATH_H_