8 #ifndef V8_BASE_SAFE_MATH_H_ 9 #define V8_BASE_SAFE_MATH_H_ 11 #include "src/base/safe_math_impl.h" 48 class CheckedNumeric {
52 CheckedNumeric() =
default;
55 template <
typename Src>
56 CheckedNumeric(
const CheckedNumeric<Src>& rhs)
57 : state_(rhs.ValueUnsafe(), rhs.validity()) {}
59 template <
typename Src>
60 CheckedNumeric(Src value, RangeConstraint validity)
61 : state_(value, validity) {}
65 template <
typename Src>
66 CheckedNumeric(Src value)
69 STATIC_ASSERT(std::numeric_limits<Src>::is_specialized);
73 bool IsValid()
const {
return validity() == RANGE_VALID; }
77 T ValueOrDie()
const {
79 return state_.value();
85 T ValueOrDefault(T default_value)
const {
86 return IsValid() ? state_.value() : default_value;
92 T ValueFloating()
const {
94 STATIC_ASSERT(std::numeric_limits<T>::is_iec559);
95 return CheckedNumeric<T>::cast(*this).ValueUnsafe();
105 RangeConstraint validity()
const {
return state_.validity(); }
114 T ValueUnsafe()
const {
return state_.value(); }
117 template <
typename Src> CheckedNumeric& operator+=(Src rhs);
118 template <
typename Src> CheckedNumeric& operator-=(Src rhs);
119 template <
typename Src> CheckedNumeric& operator*=(Src rhs);
120 template <
typename Src> CheckedNumeric& operator/=(Src rhs);
121 template <
typename Src> CheckedNumeric& operator%=(Src rhs);
123 CheckedNumeric operator-()
const {
124 RangeConstraint validity;
125 T value = CheckedNeg(state_.value(), &validity);
127 if (std::numeric_limits<T>::is_iec559)
128 return CheckedNumeric<T>(value);
130 validity = GetRangeConstraint(state_.validity() | validity);
131 return CheckedNumeric<T>(value, validity);
134 CheckedNumeric Abs()
const {
135 RangeConstraint validity;
136 T value = CheckedAbs(state_.value(), &validity);
138 if (std::numeric_limits<T>::is_iec559)
139 return CheckedNumeric<T>(value);
141 validity = GetRangeConstraint(state_.validity() | validity);
142 return CheckedNumeric<T>(value, validity);
145 CheckedNumeric& operator++() {
150 CheckedNumeric operator++(
int) {
151 CheckedNumeric value = *
this;
156 CheckedNumeric& operator--() {
161 CheckedNumeric operator--(
int) {
162 CheckedNumeric value = *
this;
170 template <
typename Src>
171 static CheckedNumeric<T> cast(
173 typename enable_if<std::numeric_limits<Src>::is_specialized,
int>::type =
178 template <
typename Src>
179 static CheckedNumeric<T> cast(
180 const CheckedNumeric<Src>& u,
181 typename enable_if<!is_same<Src, T>::value,
int>::type = 0) {
185 static const CheckedNumeric<T>& cast(
const CheckedNumeric<T>& u) {
return u; }
188 CheckedNumericState<T> state_;
198 #define BASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP) \ 200 template <typename T> \ 201 CheckedNumeric<typename ArithmeticPromotion<T>::type> operator OP( \ 202 const CheckedNumeric<T>& lhs, const CheckedNumeric<T>& rhs) { \ 203 typedef typename ArithmeticPromotion<T>::type Promotion; \ 205 if (std::numeric_limits<T>::is_iec559) \ 206 return CheckedNumeric<T>(lhs.ValueUnsafe() OP rhs.ValueUnsafe()); \ 207 if (IsIntegerArithmeticSafe<Promotion, T, T>::value) \ 208 return CheckedNumeric<Promotion>( \ 209 lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \ 210 GetRangeConstraint(rhs.validity() | lhs.validity())); \ 211 RangeConstraint validity = RANGE_VALID; \ 212 T result = Checked##NAME(static_cast<Promotion>(lhs.ValueUnsafe()), \ 213 static_cast<Promotion>(rhs.ValueUnsafe()), \ 215 return CheckedNumeric<Promotion>( \ 217 GetRangeConstraint(validity | lhs.validity() | rhs.validity())); \ 220 template <typename T> \ 221 template <typename Src> \ 222 CheckedNumeric<T>& CheckedNumeric<T>::operator COMPOUND_OP(Src rhs) { \ 223 *this = CheckedNumeric<T>::cast(*this) OP CheckedNumeric<Src>::cast(rhs); \ 227 template <typename T, typename Src> \ 228 CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \ 229 const CheckedNumeric<Src>& lhs, const CheckedNumeric<T>& rhs) { \ 230 typedef typename ArithmeticPromotion<T, Src>::type Promotion; \ 231 if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \ 232 return CheckedNumeric<Promotion>( \ 233 lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \ 234 GetRangeConstraint(rhs.validity() | lhs.validity())); \ 235 return CheckedNumeric<Promotion>::cast(lhs) \ 236 OP CheckedNumeric<Promotion>::cast(rhs); \ 239 template <typename T, typename Src> \ 240 CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \ 241 const CheckedNumeric<T>& lhs, Src rhs) { \ 242 typedef typename ArithmeticPromotion<T, Src>::type Promotion; \ 243 if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \ 244 return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs, \ 246 return CheckedNumeric<Promotion>::cast(lhs) \ 247 OP CheckedNumeric<Promotion>::cast(rhs); \ 250 template <typename T, typename Src> \ 251 CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \ 252 Src lhs, const CheckedNumeric<T>& rhs) { \ 253 typedef typename ArithmeticPromotion<T, Src>::type Promotion; \ 254 if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \ 255 return CheckedNumeric<Promotion>(lhs OP rhs.ValueUnsafe(), \ 257 return CheckedNumeric<Promotion>::cast(lhs) \ 258 OP CheckedNumeric<Promotion>::cast(rhs); \ 261 BASE_NUMERIC_ARITHMETIC_OPERATORS(Add, +, += )
262 BASE_NUMERIC_ARITHMETIC_OPERATORS(Sub, -, -= )
263 BASE_NUMERIC_ARITHMETIC_OPERATORS(Mul, *, *= )
264 BASE_NUMERIC_ARITHMETIC_OPERATORS(Div, /, /= )
265 BASE_NUMERIC_ARITHMETIC_OPERATORS(Mod, %, %= )
267 #undef BASE_NUMERIC_ARITHMETIC_OPERATORS 271 using internal::CheckedNumeric;
276 #endif // V8_BASE_SAFE_MATH_H_