1*6777b538SAndroid Build Coastguard Worker // Copyright 2014 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_NUMERICS_SAFE_CONVERSIONS_H_ 6*6777b538SAndroid Build Coastguard Worker #define BASE_NUMERICS_SAFE_CONVERSIONS_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <stddef.h> 9*6777b538SAndroid Build Coastguard Worker 10*6777b538SAndroid Build Coastguard Worker #include <cmath> 11*6777b538SAndroid Build Coastguard Worker #include <concepts> 12*6777b538SAndroid Build Coastguard Worker #include <limits> 13*6777b538SAndroid Build Coastguard Worker #include <type_traits> 14*6777b538SAndroid Build Coastguard Worker 15*6777b538SAndroid Build Coastguard Worker #include "base/numerics/safe_conversions_impl.h" 16*6777b538SAndroid Build Coastguard Worker 17*6777b538SAndroid Build Coastguard Worker #if defined(__ARMEL__) && !defined(__native_client__) 18*6777b538SAndroid Build Coastguard Worker #include "base/numerics/safe_conversions_arm_impl.h" 19*6777b538SAndroid Build Coastguard Worker #define BASE_HAS_OPTIMIZED_SAFE_CONVERSIONS (1) 20*6777b538SAndroid Build Coastguard Worker #else 21*6777b538SAndroid Build Coastguard Worker #define BASE_HAS_OPTIMIZED_SAFE_CONVERSIONS (0) 22*6777b538SAndroid Build Coastguard Worker #endif 23*6777b538SAndroid Build Coastguard Worker 24*6777b538SAndroid Build Coastguard Worker namespace base { 25*6777b538SAndroid Build Coastguard Worker namespace internal { 26*6777b538SAndroid Build Coastguard Worker 27*6777b538SAndroid Build Coastguard Worker #if !BASE_HAS_OPTIMIZED_SAFE_CONVERSIONS 28*6777b538SAndroid Build Coastguard Worker template <typename Dst, typename Src> 29*6777b538SAndroid Build Coastguard Worker struct SaturateFastAsmOp { 30*6777b538SAndroid Build Coastguard Worker static constexpr bool is_supported = false; DoSaturateFastAsmOp31*6777b538SAndroid Build Coastguard Worker static constexpr Dst Do(Src) { 32*6777b538SAndroid Build Coastguard Worker // Force a compile failure if instantiated. 33*6777b538SAndroid Build Coastguard Worker return CheckOnFailure::template HandleFailure<Dst>(); 34*6777b538SAndroid Build Coastguard Worker } 35*6777b538SAndroid Build Coastguard Worker }; 36*6777b538SAndroid Build Coastguard Worker #endif // BASE_HAS_OPTIMIZED_SAFE_CONVERSIONS 37*6777b538SAndroid Build Coastguard Worker #undef BASE_HAS_OPTIMIZED_SAFE_CONVERSIONS 38*6777b538SAndroid Build Coastguard Worker 39*6777b538SAndroid Build Coastguard Worker // The following special case a few specific integer conversions where we can 40*6777b538SAndroid Build Coastguard Worker // eke out better performance than range checking. 41*6777b538SAndroid Build Coastguard Worker template <typename Dst, typename Src> 42*6777b538SAndroid Build Coastguard Worker struct IsValueInRangeFastOp { 43*6777b538SAndroid Build Coastguard Worker static constexpr bool is_supported = false; DoIsValueInRangeFastOp44*6777b538SAndroid Build Coastguard Worker static constexpr bool Do(Src value) { 45*6777b538SAndroid Build Coastguard Worker // Force a compile failure if instantiated. 46*6777b538SAndroid Build Coastguard Worker return CheckOnFailure::template HandleFailure<bool>(); 47*6777b538SAndroid Build Coastguard Worker } 48*6777b538SAndroid Build Coastguard Worker }; 49*6777b538SAndroid Build Coastguard Worker 50*6777b538SAndroid Build Coastguard Worker // Signed to signed range comparison. 51*6777b538SAndroid Build Coastguard Worker template <typename Dst, typename Src> 52*6777b538SAndroid Build Coastguard Worker requires(std::signed_integral<Dst> && std::signed_integral<Src> && 53*6777b538SAndroid Build Coastguard Worker !IsTypeInRangeForNumericType<Dst, Src>::value) 54*6777b538SAndroid Build Coastguard Worker struct IsValueInRangeFastOp<Dst, Src> { 55*6777b538SAndroid Build Coastguard Worker static constexpr bool is_supported = true; 56*6777b538SAndroid Build Coastguard Worker 57*6777b538SAndroid Build Coastguard Worker static constexpr bool Do(Src value) { 58*6777b538SAndroid Build Coastguard Worker // Just downcast to the smaller type, sign extend it back to the original 59*6777b538SAndroid Build Coastguard Worker // type, and then see if it matches the original value. 60*6777b538SAndroid Build Coastguard Worker return value == static_cast<Dst>(value); 61*6777b538SAndroid Build Coastguard Worker } 62*6777b538SAndroid Build Coastguard Worker }; 63*6777b538SAndroid Build Coastguard Worker 64*6777b538SAndroid Build Coastguard Worker // Signed to unsigned range comparison. 65*6777b538SAndroid Build Coastguard Worker template <typename Dst, typename Src> 66*6777b538SAndroid Build Coastguard Worker requires(std::unsigned_integral<Dst> && std::signed_integral<Src> && 67*6777b538SAndroid Build Coastguard Worker !IsTypeInRangeForNumericType<Dst, Src>::value) 68*6777b538SAndroid Build Coastguard Worker struct IsValueInRangeFastOp<Dst, Src> { 69*6777b538SAndroid Build Coastguard Worker static constexpr bool is_supported = true; 70*6777b538SAndroid Build Coastguard Worker 71*6777b538SAndroid Build Coastguard Worker static constexpr bool Do(Src value) { 72*6777b538SAndroid Build Coastguard Worker // We cast a signed as unsigned to overflow negative values to the top, 73*6777b538SAndroid Build Coastguard Worker // then compare against whichever maximum is smaller, as our upper bound. 74*6777b538SAndroid Build Coastguard Worker return as_unsigned(value) <= as_unsigned(CommonMax<Src, Dst>()); 75*6777b538SAndroid Build Coastguard Worker } 76*6777b538SAndroid Build Coastguard Worker }; 77*6777b538SAndroid Build Coastguard Worker 78*6777b538SAndroid Build Coastguard Worker // Convenience function that returns true if the supplied value is in range 79*6777b538SAndroid Build Coastguard Worker // for the destination type. 80*6777b538SAndroid Build Coastguard Worker template <typename Dst, typename Src> 81*6777b538SAndroid Build Coastguard Worker constexpr bool IsValueInRangeForNumericType(Src value) { 82*6777b538SAndroid Build Coastguard Worker using SrcType = typename internal::UnderlyingType<Src>::type; 83*6777b538SAndroid Build Coastguard Worker return internal::IsValueInRangeFastOp<Dst, SrcType>::is_supported 84*6777b538SAndroid Build Coastguard Worker ? internal::IsValueInRangeFastOp<Dst, SrcType>::Do( 85*6777b538SAndroid Build Coastguard Worker static_cast<SrcType>(value)) 86*6777b538SAndroid Build Coastguard Worker : internal::DstRangeRelationToSrcRange<Dst>( 87*6777b538SAndroid Build Coastguard Worker static_cast<SrcType>(value)) 88*6777b538SAndroid Build Coastguard Worker .IsValid(); 89*6777b538SAndroid Build Coastguard Worker } 90*6777b538SAndroid Build Coastguard Worker 91*6777b538SAndroid Build Coastguard Worker // checked_cast<> is analogous to static_cast<> for numeric types, 92*6777b538SAndroid Build Coastguard Worker // except that it CHECKs that the specified numeric conversion will not 93*6777b538SAndroid Build Coastguard Worker // overflow or underflow. NaN source will always trigger a CHECK. 94*6777b538SAndroid Build Coastguard Worker template <typename Dst, 95*6777b538SAndroid Build Coastguard Worker class CheckHandler = internal::CheckOnFailure, 96*6777b538SAndroid Build Coastguard Worker typename Src> 97*6777b538SAndroid Build Coastguard Worker constexpr Dst checked_cast(Src value) { 98*6777b538SAndroid Build Coastguard Worker // This throws a compile-time error on evaluating the constexpr if it can be 99*6777b538SAndroid Build Coastguard Worker // determined at compile-time as failing, otherwise it will CHECK at runtime. 100*6777b538SAndroid Build Coastguard Worker using SrcType = typename internal::UnderlyingType<Src>::type; 101*6777b538SAndroid Build Coastguard Worker return BASE_NUMERICS_LIKELY((IsValueInRangeForNumericType<Dst>(value))) 102*6777b538SAndroid Build Coastguard Worker ? static_cast<Dst>(static_cast<SrcType>(value)) 103*6777b538SAndroid Build Coastguard Worker : CheckHandler::template HandleFailure<Dst>(); 104*6777b538SAndroid Build Coastguard Worker } 105*6777b538SAndroid Build Coastguard Worker 106*6777b538SAndroid Build Coastguard Worker // Default boundaries for integral/float: max/infinity, lowest/-infinity, 0/NaN. 107*6777b538SAndroid Build Coastguard Worker // You may provide your own limits (e.g. to saturated_cast) so long as you 108*6777b538SAndroid Build Coastguard Worker // implement all of the static constexpr member functions in the class below. 109*6777b538SAndroid Build Coastguard Worker template <typename T> 110*6777b538SAndroid Build Coastguard Worker struct SaturationDefaultLimits : public std::numeric_limits<T> { 111*6777b538SAndroid Build Coastguard Worker static constexpr T NaN() { 112*6777b538SAndroid Build Coastguard Worker if constexpr (std::numeric_limits<T>::has_quiet_NaN) { 113*6777b538SAndroid Build Coastguard Worker return std::numeric_limits<T>::quiet_NaN(); 114*6777b538SAndroid Build Coastguard Worker } else { 115*6777b538SAndroid Build Coastguard Worker return T(); 116*6777b538SAndroid Build Coastguard Worker } 117*6777b538SAndroid Build Coastguard Worker } 118*6777b538SAndroid Build Coastguard Worker using std::numeric_limits<T>::max; 119*6777b538SAndroid Build Coastguard Worker static constexpr T Overflow() { 120*6777b538SAndroid Build Coastguard Worker if constexpr (std::numeric_limits<T>::has_infinity) { 121*6777b538SAndroid Build Coastguard Worker return std::numeric_limits<T>::infinity(); 122*6777b538SAndroid Build Coastguard Worker } else { 123*6777b538SAndroid Build Coastguard Worker return std::numeric_limits<T>::max(); 124*6777b538SAndroid Build Coastguard Worker } 125*6777b538SAndroid Build Coastguard Worker } 126*6777b538SAndroid Build Coastguard Worker using std::numeric_limits<T>::lowest; 127*6777b538SAndroid Build Coastguard Worker static constexpr T Underflow() { 128*6777b538SAndroid Build Coastguard Worker if constexpr (std::numeric_limits<T>::has_infinity) { 129*6777b538SAndroid Build Coastguard Worker return std::numeric_limits<T>::infinity() * -1; 130*6777b538SAndroid Build Coastguard Worker } else { 131*6777b538SAndroid Build Coastguard Worker return std::numeric_limits<T>::lowest(); 132*6777b538SAndroid Build Coastguard Worker } 133*6777b538SAndroid Build Coastguard Worker } 134*6777b538SAndroid Build Coastguard Worker }; 135*6777b538SAndroid Build Coastguard Worker 136*6777b538SAndroid Build Coastguard Worker template <typename Dst, template <typename> class S, typename Src> 137*6777b538SAndroid Build Coastguard Worker constexpr Dst saturated_cast_impl(Src value, RangeCheck constraint) { 138*6777b538SAndroid Build Coastguard Worker // For some reason clang generates much better code when the branch is 139*6777b538SAndroid Build Coastguard Worker // structured exactly this way, rather than a sequence of checks. 140*6777b538SAndroid Build Coastguard Worker return !constraint.IsOverflowFlagSet() 141*6777b538SAndroid Build Coastguard Worker ? (!constraint.IsUnderflowFlagSet() ? static_cast<Dst>(value) 142*6777b538SAndroid Build Coastguard Worker : S<Dst>::Underflow()) 143*6777b538SAndroid Build Coastguard Worker // Skip this check for integral Src, which cannot be NaN. 144*6777b538SAndroid Build Coastguard Worker : (std::is_integral_v<Src> || !constraint.IsUnderflowFlagSet() 145*6777b538SAndroid Build Coastguard Worker ? S<Dst>::Overflow() 146*6777b538SAndroid Build Coastguard Worker : S<Dst>::NaN()); 147*6777b538SAndroid Build Coastguard Worker } 148*6777b538SAndroid Build Coastguard Worker 149*6777b538SAndroid Build Coastguard Worker // We can reduce the number of conditions and get slightly better performance 150*6777b538SAndroid Build Coastguard Worker // for normal signed and unsigned integer ranges. And in the specific case of 151*6777b538SAndroid Build Coastguard Worker // Arm, we can use the optimized saturation instructions. 152*6777b538SAndroid Build Coastguard Worker template <typename Dst, typename Src> 153*6777b538SAndroid Build Coastguard Worker struct SaturateFastOp { 154*6777b538SAndroid Build Coastguard Worker static constexpr bool is_supported = false; 155*6777b538SAndroid Build Coastguard Worker static constexpr Dst Do(Src value) { 156*6777b538SAndroid Build Coastguard Worker // Force a compile failure if instantiated. 157*6777b538SAndroid Build Coastguard Worker return CheckOnFailure::template HandleFailure<Dst>(); 158*6777b538SAndroid Build Coastguard Worker } 159*6777b538SAndroid Build Coastguard Worker }; 160*6777b538SAndroid Build Coastguard Worker 161*6777b538SAndroid Build Coastguard Worker template <typename Dst, typename Src> 162*6777b538SAndroid Build Coastguard Worker requires(std::integral<Src> && std::integral<Dst> && 163*6777b538SAndroid Build Coastguard Worker SaturateFastAsmOp<Dst, Src>::is_supported) 164*6777b538SAndroid Build Coastguard Worker struct SaturateFastOp<Dst, Src> { 165*6777b538SAndroid Build Coastguard Worker static constexpr bool is_supported = true; 166*6777b538SAndroid Build Coastguard Worker static constexpr Dst Do(Src value) { 167*6777b538SAndroid Build Coastguard Worker return SaturateFastAsmOp<Dst, Src>::Do(value); 168*6777b538SAndroid Build Coastguard Worker } 169*6777b538SAndroid Build Coastguard Worker }; 170*6777b538SAndroid Build Coastguard Worker 171*6777b538SAndroid Build Coastguard Worker template <typename Dst, typename Src> 172*6777b538SAndroid Build Coastguard Worker requires(std::integral<Src> && std::integral<Dst> && 173*6777b538SAndroid Build Coastguard Worker !SaturateFastAsmOp<Dst, Src>::is_supported) 174*6777b538SAndroid Build Coastguard Worker struct SaturateFastOp<Dst, Src> { 175*6777b538SAndroid Build Coastguard Worker static constexpr bool is_supported = true; 176*6777b538SAndroid Build Coastguard Worker static constexpr Dst Do(Src value) { 177*6777b538SAndroid Build Coastguard Worker // The exact order of the following is structured to hit the correct 178*6777b538SAndroid Build Coastguard Worker // optimization heuristics across compilers. Do not change without 179*6777b538SAndroid Build Coastguard Worker // checking the emitted code. 180*6777b538SAndroid Build Coastguard Worker const Dst saturated = CommonMaxOrMin<Dst, Src>( 181*6777b538SAndroid Build Coastguard Worker IsMaxInRangeForNumericType<Dst, Src>() || 182*6777b538SAndroid Build Coastguard Worker (!IsMinInRangeForNumericType<Dst, Src>() && IsValueNegative(value))); 183*6777b538SAndroid Build Coastguard Worker return BASE_NUMERICS_LIKELY(IsValueInRangeForNumericType<Dst>(value)) 184*6777b538SAndroid Build Coastguard Worker ? static_cast<Dst>(value) 185*6777b538SAndroid Build Coastguard Worker : saturated; 186*6777b538SAndroid Build Coastguard Worker } 187*6777b538SAndroid Build Coastguard Worker }; 188*6777b538SAndroid Build Coastguard Worker 189*6777b538SAndroid Build Coastguard Worker // saturated_cast<> is analogous to static_cast<> for numeric types, except 190*6777b538SAndroid Build Coastguard Worker // that the specified numeric conversion will saturate by default rather than 191*6777b538SAndroid Build Coastguard Worker // overflow or underflow, and NaN assignment to an integral will return 0. 192*6777b538SAndroid Build Coastguard Worker // All boundary condition behaviors can be overridden with a custom handler. 193*6777b538SAndroid Build Coastguard Worker template <typename Dst, 194*6777b538SAndroid Build Coastguard Worker template <typename> class SaturationHandler = SaturationDefaultLimits, 195*6777b538SAndroid Build Coastguard Worker typename Src> 196*6777b538SAndroid Build Coastguard Worker constexpr Dst saturated_cast(Src value) { 197*6777b538SAndroid Build Coastguard Worker using SrcType = typename UnderlyingType<Src>::type; 198*6777b538SAndroid Build Coastguard Worker return !IsConstantEvaluated() && SaturateFastOp<Dst, SrcType>::is_supported && 199*6777b538SAndroid Build Coastguard Worker std::is_same_v<SaturationHandler<Dst>, 200*6777b538SAndroid Build Coastguard Worker SaturationDefaultLimits<Dst>> 201*6777b538SAndroid Build Coastguard Worker ? SaturateFastOp<Dst, SrcType>::Do(static_cast<SrcType>(value)) 202*6777b538SAndroid Build Coastguard Worker : saturated_cast_impl<Dst, SaturationHandler, SrcType>( 203*6777b538SAndroid Build Coastguard Worker static_cast<SrcType>(value), 204*6777b538SAndroid Build Coastguard Worker DstRangeRelationToSrcRange<Dst, SaturationHandler, SrcType>( 205*6777b538SAndroid Build Coastguard Worker static_cast<SrcType>(value))); 206*6777b538SAndroid Build Coastguard Worker } 207*6777b538SAndroid Build Coastguard Worker 208*6777b538SAndroid Build Coastguard Worker // strict_cast<> is analogous to static_cast<> for numeric types, except that 209*6777b538SAndroid Build Coastguard Worker // it will cause a compile failure if the destination type is not large enough 210*6777b538SAndroid Build Coastguard Worker // to contain any value in the source type. It performs no runtime checking. 211*6777b538SAndroid Build Coastguard Worker template <typename Dst, typename Src> 212*6777b538SAndroid Build Coastguard Worker constexpr Dst strict_cast(Src value) { 213*6777b538SAndroid Build Coastguard Worker using SrcType = typename UnderlyingType<Src>::type; 214*6777b538SAndroid Build Coastguard Worker static_assert(UnderlyingType<Src>::is_numeric, "Argument must be numeric."); 215*6777b538SAndroid Build Coastguard Worker static_assert(std::is_arithmetic_v<Dst>, "Result must be numeric."); 216*6777b538SAndroid Build Coastguard Worker 217*6777b538SAndroid Build Coastguard Worker // If you got here from a compiler error, it's because you tried to assign 218*6777b538SAndroid Build Coastguard Worker // from a source type to a destination type that has insufficient range. 219*6777b538SAndroid Build Coastguard Worker // The solution may be to change the destination type you're assigning to, 220*6777b538SAndroid Build Coastguard Worker // and use one large enough to represent the source. 221*6777b538SAndroid Build Coastguard Worker // Alternatively, you may be better served with the checked_cast<> or 222*6777b538SAndroid Build Coastguard Worker // saturated_cast<> template functions for your particular use case. 223*6777b538SAndroid Build Coastguard Worker static_assert(StaticDstRangeRelationToSrcRange<Dst, SrcType>::value == 224*6777b538SAndroid Build Coastguard Worker NUMERIC_RANGE_CONTAINED, 225*6777b538SAndroid Build Coastguard Worker "The source type is out of range for the destination type. " 226*6777b538SAndroid Build Coastguard Worker "Please see strict_cast<> comments for more information."); 227*6777b538SAndroid Build Coastguard Worker 228*6777b538SAndroid Build Coastguard Worker return static_cast<Dst>(static_cast<SrcType>(value)); 229*6777b538SAndroid Build Coastguard Worker } 230*6777b538SAndroid Build Coastguard Worker 231*6777b538SAndroid Build Coastguard Worker // Some wrappers to statically check that a type is in range. 232*6777b538SAndroid Build Coastguard Worker template <typename Dst, typename Src> 233*6777b538SAndroid Build Coastguard Worker struct IsNumericRangeContained { 234*6777b538SAndroid Build Coastguard Worker static constexpr bool value = false; 235*6777b538SAndroid Build Coastguard Worker }; 236*6777b538SAndroid Build Coastguard Worker 237*6777b538SAndroid Build Coastguard Worker template <typename Dst, typename Src> 238*6777b538SAndroid Build Coastguard Worker requires(ArithmeticOrUnderlyingEnum<Dst>::value && 239*6777b538SAndroid Build Coastguard Worker ArithmeticOrUnderlyingEnum<Src>::value) 240*6777b538SAndroid Build Coastguard Worker struct IsNumericRangeContained<Dst, Src> { 241*6777b538SAndroid Build Coastguard Worker static constexpr bool value = 242*6777b538SAndroid Build Coastguard Worker StaticDstRangeRelationToSrcRange<Dst, Src>::value == 243*6777b538SAndroid Build Coastguard Worker NUMERIC_RANGE_CONTAINED; 244*6777b538SAndroid Build Coastguard Worker }; 245*6777b538SAndroid Build Coastguard Worker 246*6777b538SAndroid Build Coastguard Worker // StrictNumeric implements compile time range checking between numeric types by 247*6777b538SAndroid Build Coastguard Worker // wrapping assignment operations in a strict_cast. This class is intended to be 248*6777b538SAndroid Build Coastguard Worker // used for function arguments and return types, to ensure the destination type 249*6777b538SAndroid Build Coastguard Worker // can always contain the source type. This is essentially the same as enforcing 250*6777b538SAndroid Build Coastguard Worker // -Wconversion in gcc and C4302 warnings on MSVC, but it can be applied 251*6777b538SAndroid Build Coastguard Worker // incrementally at API boundaries, making it easier to convert code so that it 252*6777b538SAndroid Build Coastguard Worker // compiles cleanly with truncation warnings enabled. 253*6777b538SAndroid Build Coastguard Worker // This template should introduce no runtime overhead, but it also provides no 254*6777b538SAndroid Build Coastguard Worker // runtime checking of any of the associated mathematical operations. Use 255*6777b538SAndroid Build Coastguard Worker // CheckedNumeric for runtime range checks of the actual value being assigned. 256*6777b538SAndroid Build Coastguard Worker template <typename T> 257*6777b538SAndroid Build Coastguard Worker class StrictNumeric { 258*6777b538SAndroid Build Coastguard Worker public: 259*6777b538SAndroid Build Coastguard Worker using type = T; 260*6777b538SAndroid Build Coastguard Worker 261*6777b538SAndroid Build Coastguard Worker constexpr StrictNumeric() : value_(0) {} 262*6777b538SAndroid Build Coastguard Worker 263*6777b538SAndroid Build Coastguard Worker // Copy constructor. 264*6777b538SAndroid Build Coastguard Worker template <typename Src> 265*6777b538SAndroid Build Coastguard Worker constexpr StrictNumeric(const StrictNumeric<Src>& rhs) 266*6777b538SAndroid Build Coastguard Worker : value_(strict_cast<T>(rhs.value_)) {} 267*6777b538SAndroid Build Coastguard Worker 268*6777b538SAndroid Build Coastguard Worker // Strictly speaking, this is not necessary, but declaring this allows class 269*6777b538SAndroid Build Coastguard Worker // template argument deduction to be used so that it is possible to simply 270*6777b538SAndroid Build Coastguard Worker // write `StrictNumeric(777)` instead of `StrictNumeric<int>(777)`. 271*6777b538SAndroid Build Coastguard Worker // NOLINTNEXTLINE(google-explicit-constructor) 272*6777b538SAndroid Build Coastguard Worker constexpr StrictNumeric(T value) : value_(value) {} 273*6777b538SAndroid Build Coastguard Worker 274*6777b538SAndroid Build Coastguard Worker // This is not an explicit constructor because we implicitly upgrade regular 275*6777b538SAndroid Build Coastguard Worker // numerics to StrictNumerics to make them easier to use. 276*6777b538SAndroid Build Coastguard Worker template <typename Src> 277*6777b538SAndroid Build Coastguard Worker // NOLINTNEXTLINE(google-explicit-constructor) 278*6777b538SAndroid Build Coastguard Worker constexpr StrictNumeric(Src value) : value_(strict_cast<T>(value)) {} 279*6777b538SAndroid Build Coastguard Worker 280*6777b538SAndroid Build Coastguard Worker // If you got here from a compiler error, it's because you tried to assign 281*6777b538SAndroid Build Coastguard Worker // from a source type to a destination type that has insufficient range. 282*6777b538SAndroid Build Coastguard Worker // The solution may be to change the destination type you're assigning to, 283*6777b538SAndroid Build Coastguard Worker // and use one large enough to represent the source. 284*6777b538SAndroid Build Coastguard Worker // If you're assigning from a CheckedNumeric<> class, you may be able to use 285*6777b538SAndroid Build Coastguard Worker // the AssignIfValid() member function, specify a narrower destination type to 286*6777b538SAndroid Build Coastguard Worker // the member value functions (e.g. val.template ValueOrDie<Dst>()), use one 287*6777b538SAndroid Build Coastguard Worker // of the value helper functions (e.g. ValueOrDieForType<Dst>(val)). 288*6777b538SAndroid Build Coastguard Worker // If you've encountered an _ambiguous overload_ you can use a static_cast<> 289*6777b538SAndroid Build Coastguard Worker // to explicitly cast the result to the destination type. 290*6777b538SAndroid Build Coastguard Worker // If none of that works, you may be better served with the checked_cast<> or 291*6777b538SAndroid Build Coastguard Worker // saturated_cast<> template functions for your particular use case. 292*6777b538SAndroid Build Coastguard Worker template <typename Dst> 293*6777b538SAndroid Build Coastguard Worker requires(IsNumericRangeContained<Dst, T>::value) 294*6777b538SAndroid Build Coastguard Worker constexpr operator Dst() const { 295*6777b538SAndroid Build Coastguard Worker return static_cast<typename ArithmeticOrUnderlyingEnum<Dst>::type>(value_); 296*6777b538SAndroid Build Coastguard Worker } 297*6777b538SAndroid Build Coastguard Worker 298*6777b538SAndroid Build Coastguard Worker private: 299*6777b538SAndroid Build Coastguard Worker const T value_; 300*6777b538SAndroid Build Coastguard Worker }; 301*6777b538SAndroid Build Coastguard Worker 302*6777b538SAndroid Build Coastguard Worker // Convenience wrapper returns a StrictNumeric from the provided arithmetic 303*6777b538SAndroid Build Coastguard Worker // type. 304*6777b538SAndroid Build Coastguard Worker template <typename T> 305*6777b538SAndroid Build Coastguard Worker constexpr StrictNumeric<typename UnderlyingType<T>::type> MakeStrictNum( 306*6777b538SAndroid Build Coastguard Worker const T value) { 307*6777b538SAndroid Build Coastguard Worker return value; 308*6777b538SAndroid Build Coastguard Worker } 309*6777b538SAndroid Build Coastguard Worker 310*6777b538SAndroid Build Coastguard Worker #define BASE_NUMERIC_COMPARISON_OPERATORS(CLASS, NAME, OP) \ 311*6777b538SAndroid Build Coastguard Worker template <typename L, typename R> \ 312*6777b538SAndroid Build Coastguard Worker requires(internal::Is##CLASS##Op<L, R>::value) \ 313*6777b538SAndroid Build Coastguard Worker constexpr bool operator OP(const L lhs, const R rhs) { \ 314*6777b538SAndroid Build Coastguard Worker return SafeCompare<NAME, typename UnderlyingType<L>::type, \ 315*6777b538SAndroid Build Coastguard Worker typename UnderlyingType<R>::type>(lhs, rhs); \ 316*6777b538SAndroid Build Coastguard Worker } 317*6777b538SAndroid Build Coastguard Worker 318*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_COMPARISON_OPERATORS(Strict, IsLess, <) 319*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_COMPARISON_OPERATORS(Strict, IsLessOrEqual, <=) 320*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_COMPARISON_OPERATORS(Strict, IsGreater, >) 321*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_COMPARISON_OPERATORS(Strict, IsGreaterOrEqual, >=) 322*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_COMPARISON_OPERATORS(Strict, IsEqual, ==) 323*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_COMPARISON_OPERATORS(Strict, IsNotEqual, !=) 324*6777b538SAndroid Build Coastguard Worker 325*6777b538SAndroid Build Coastguard Worker } // namespace internal 326*6777b538SAndroid Build Coastguard Worker 327*6777b538SAndroid Build Coastguard Worker using internal::as_signed; 328*6777b538SAndroid Build Coastguard Worker using internal::as_unsigned; 329*6777b538SAndroid Build Coastguard Worker using internal::checked_cast; 330*6777b538SAndroid Build Coastguard Worker using internal::IsTypeInRangeForNumericType; 331*6777b538SAndroid Build Coastguard Worker using internal::IsValueInRangeForNumericType; 332*6777b538SAndroid Build Coastguard Worker using internal::IsValueNegative; 333*6777b538SAndroid Build Coastguard Worker using internal::MakeStrictNum; 334*6777b538SAndroid Build Coastguard Worker using internal::SafeUnsignedAbs; 335*6777b538SAndroid Build Coastguard Worker using internal::saturated_cast; 336*6777b538SAndroid Build Coastguard Worker using internal::strict_cast; 337*6777b538SAndroid Build Coastguard Worker using internal::StrictNumeric; 338*6777b538SAndroid Build Coastguard Worker 339*6777b538SAndroid Build Coastguard Worker // Explicitly make a shorter size_t alias for convenience. 340*6777b538SAndroid Build Coastguard Worker using SizeT = StrictNumeric<size_t>; 341*6777b538SAndroid Build Coastguard Worker 342*6777b538SAndroid Build Coastguard Worker // floating -> integral conversions that saturate and thus can actually return 343*6777b538SAndroid Build Coastguard Worker // an integral type. 344*6777b538SAndroid Build Coastguard Worker // 345*6777b538SAndroid Build Coastguard Worker // Generally, what you want is saturated_cast<Dst>(std::nearbyint(x)), which 346*6777b538SAndroid Build Coastguard Worker // rounds correctly according to IEEE-754 (round to nearest, ties go to nearest 347*6777b538SAndroid Build Coastguard Worker // even number; this avoids bias). If your code is performance-critical 348*6777b538SAndroid Build Coastguard Worker // and you are sure that you will never overflow, you can use std::lrint() 349*6777b538SAndroid Build Coastguard Worker // or std::llrint(), which return a long or long long directly. 350*6777b538SAndroid Build Coastguard Worker // 351*6777b538SAndroid Build Coastguard Worker // Below are convenience functions around similar patterns, except that 352*6777b538SAndroid Build Coastguard Worker // they round in nonstandard directions and will generally be slower. 353*6777b538SAndroid Build Coastguard Worker 354*6777b538SAndroid Build Coastguard Worker // Rounds towards negative infinity (i.e., down). 355*6777b538SAndroid Build Coastguard Worker template <typename Dst = int, typename Src> 356*6777b538SAndroid Build Coastguard Worker requires(std::integral<Dst> && std::floating_point<Src>) 357*6777b538SAndroid Build Coastguard Worker Dst ClampFloor(Src value) { 358*6777b538SAndroid Build Coastguard Worker return saturated_cast<Dst>(std::floor(value)); 359*6777b538SAndroid Build Coastguard Worker } 360*6777b538SAndroid Build Coastguard Worker 361*6777b538SAndroid Build Coastguard Worker // Rounds towards positive infinity (i.e., up). 362*6777b538SAndroid Build Coastguard Worker template <typename Dst = int, typename Src> 363*6777b538SAndroid Build Coastguard Worker requires(std::integral<Dst> && std::floating_point<Src>) 364*6777b538SAndroid Build Coastguard Worker Dst ClampCeil(Src value) { 365*6777b538SAndroid Build Coastguard Worker return saturated_cast<Dst>(std::ceil(value)); 366*6777b538SAndroid Build Coastguard Worker } 367*6777b538SAndroid Build Coastguard Worker 368*6777b538SAndroid Build Coastguard Worker // Rounds towards nearest integer, with ties away from zero. 369*6777b538SAndroid Build Coastguard Worker // This means that 0.5 will be rounded to 1 and 1.5 will be rounded to 2. 370*6777b538SAndroid Build Coastguard Worker // Similarly, -0.5 will be rounded to -1 and -1.5 will be rounded to -2. 371*6777b538SAndroid Build Coastguard Worker // 372*6777b538SAndroid Build Coastguard Worker // This is normally not what you want accuracy-wise (it introduces a small bias 373*6777b538SAndroid Build Coastguard Worker // away from zero), and it is not the fastest option, but it is frequently what 374*6777b538SAndroid Build Coastguard Worker // existing code expects. Compare with saturated_cast<Dst>(std::nearbyint(x)) 375*6777b538SAndroid Build Coastguard Worker // or std::lrint(x), which would round 0.5 and -0.5 to 0 but 1.5 to 2 and 376*6777b538SAndroid Build Coastguard Worker // -1.5 to -2. 377*6777b538SAndroid Build Coastguard Worker template <typename Dst = int, typename Src> 378*6777b538SAndroid Build Coastguard Worker requires(std::integral<Dst> && std::floating_point<Src>) 379*6777b538SAndroid Build Coastguard Worker Dst ClampRound(Src value) { 380*6777b538SAndroid Build Coastguard Worker const Src rounded = std::round(value); 381*6777b538SAndroid Build Coastguard Worker return saturated_cast<Dst>(rounded); 382*6777b538SAndroid Build Coastguard Worker } 383*6777b538SAndroid Build Coastguard Worker 384*6777b538SAndroid Build Coastguard Worker } // namespace base 385*6777b538SAndroid Build Coastguard Worker 386*6777b538SAndroid Build Coastguard Worker #endif // BASE_NUMERICS_SAFE_CONVERSIONS_H_ 387