8#ifndef V8_BASE_NUMERICS_CHECKED_MATH_IMPL_H_
9#define V8_BASE_NUMERICS_CHECKED_MATH_IMPL_H_
28 static_assert(std::integral<T>,
"Type must be integral");
31 using UnsignedDst =
typename std::make_unsigned<T>::type;
32 using SignedDst =
typename std::make_signed<T>::type;
33 const UnsignedDst ux =
static_cast<UnsignedDst
>(
x);
34 const UnsignedDst uy =
static_cast<UnsignedDst
>(
y);
35 const UnsignedDst uresult =
static_cast<UnsignedDst
>(ux + uy);
38 if (std::is_signed_v<T>
39 ?
static_cast<SignedDst
>((uresult ^ ux) & (uresult ^ uy)) < 0
43 *
result =
static_cast<T
>(uresult);
47template <
typename T,
typename U>
50template <
typename T,
typename U>
51 requires(std::integral<T> && std::integral<U>)
68 if (!IsValueInRangeForNumericType<Promotion>(
x) ||
69 !IsValueInRangeForNumericType<Promotion>(
y)) [[unlikely]] {
73 Promotion presult = {};
76 presult =
static_cast<Promotion
>(
x) +
static_cast<Promotion
>(
y);
79 static_cast<Promotion
>(
y), &presult);
81 if (!is_valid || !IsValueInRangeForNumericType<V>(presult)) {
84 *
result =
static_cast<V>(presult);
91 static_assert(std::integral<T>,
"Type must be integral");
94 using UnsignedDst =
typename std::make_unsigned<T>::type;
95 using SignedDst =
typename std::make_signed<T>::type;
96 const UnsignedDst ux =
static_cast<UnsignedDst
>(
x);
97 const UnsignedDst uy =
static_cast<UnsignedDst
>(
y);
98 const UnsignedDst uresult =
static_cast<UnsignedDst
>(ux - uy);
101 if (std::is_signed_v<T>
102 ?
static_cast<SignedDst
>((uresult ^ ux) & (ux ^ uy)) < 0
106 *
result =
static_cast<T
>(uresult);
110template <
typename T,
typename U>
113template <
typename T,
typename U>
114 requires(std::integral<T> && std::integral<U>)
117 template <
typename V>
131 if (!IsValueInRangeForNumericType<Promotion>(
x) ||
132 !IsValueInRangeForNumericType<Promotion>(
y)) [[unlikely]] {
136 Promotion presult = {};
137 bool is_valid =
true;
139 presult =
static_cast<Promotion
>(
x) -
static_cast<Promotion
>(
y);
142 static_cast<Promotion
>(
y), &presult);
144 if (!is_valid || !IsValueInRangeForNumericType<V>(presult)) {
147 *
result =
static_cast<V>(presult);
154 static_assert(std::integral<T>,
"Type must be integral");
157 using UnsignedDst =
typename std::make_unsigned<T>::type;
158 using SignedDst =
typename std::make_signed<T>::type;
161 const UnsignedDst uresult =
static_cast<UnsignedDst
>(ux * uy);
162 const bool is_negative =
163 std::is_signed_v<T> &&
static_cast<SignedDst
>(
x ^
y) < 0;
167 if (uy > UnsignedDst(!std::is_signed_v<T> || is_negative) &&
168 ux > (std::numeric_limits<T>::max() + UnsignedDst(is_negative)) / uy) {
171 *
result =
static_cast<T
>(is_negative ? 0 - uresult : uresult);
175template <
typename T,
typename U>
178template <
typename T,
typename U>
179 requires(std::integral<T> && std::integral<U>)
182 template <
typename V>
190 if ((!IsValueInRangeForNumericType<Promotion>(
x) ||
191 !IsValueInRangeForNumericType<Promotion>(
y)) &&
192 x &&
y) [[unlikely]] {
196 Promotion presult = {};
197 bool is_valid =
true;
203 static_cast<Promotion
>(
x),
static_cast<Promotion
>(
y), &presult);
205 presult =
static_cast<Promotion
>(
x) *
static_cast<Promotion
>(
y);
208 static_cast<Promotion
>(
y), &presult);
210 if (!is_valid || !IsValueInRangeForNumericType<V>(presult)) {
213 *
result =
static_cast<V>(presult);
220template <
typename T,
typename U>
223template <
typename T,
typename U>
224 requires(std::integral<T> && std::integral<U>)
227 template <
typename V>
229 if (!
y) [[unlikely]] {
236 if (std::is_signed_v<T> && std::is_signed_v<U> &&
237 kIsTypeInRangeForNumericType<T, Promotion> &&
238 static_cast<Promotion
>(
x) == std::numeric_limits<Promotion>::lowest() &&
239 y ==
static_cast<U
>(-1)) [[unlikely]] {
244 if ((!IsValueInRangeForNumericType<Promotion>(
x) ||
245 !IsValueInRangeForNumericType<Promotion>(
y)) &&
250 const Promotion presult = Promotion(
x) / Promotion(
y);
251 if (!IsValueInRangeForNumericType<V>(presult)) {
254 *
result =
static_cast<V>(presult);
259template <
typename T,
typename U>
262template <
typename T,
typename U>
263 requires(std::integral<T> && std::integral<U>)
266 template <
typename V>
268 if (!
y) [[unlikely]] {
273 if (std::is_signed_v<T> && std::is_signed_v<U> &&
274 kIsTypeInRangeForNumericType<T, Promotion> &&
275 static_cast<Promotion
>(
x) == std::numeric_limits<Promotion>::lowest() &&
276 y ==
static_cast<U
>(-1)) [[unlikely]] {
281 const Promotion presult =
282 static_cast<Promotion
>(
x) %
static_cast<Promotion
>(
y);
283 if (!IsValueInRangeForNumericType<V>(presult)) {
286 *
result =
static_cast<Promotion
>(presult);
291template <
typename T,
typename U>
297template <
typename T,
typename U>
298 requires(std::integral<T> && std::integral<U>)
301 template <
typename V>
314 if (!std::is_signed_v<T> ||
x ||
323template <
typename T,
typename U>
329template <
typename T,
typename U>
330 requires(std::integral<T> && std::integral<U>)
333 template <
typename V>
340 const T tmp =
x >> shift;
341 if (!IsValueInRangeForNumericType<V>(tmp)) {
349template <
typename T,
typename U>
353template <
typename T,
typename U>
354 requires(std::integral<T> && std::integral<U>)
356 using result_type = std::make_unsigned_t<MaxExponentPromotion<T, U>>;
357 template <
typename V>
361 if (!IsValueInRangeForNumericType<V>(tmp)) {
369template <
typename T,
typename U>
373template <
typename T,
typename U>
374 requires(std::integral<T> && std::integral<U>)
376 using result_type = std::make_unsigned_t<MaxExponentPromotion<T, U>>;
377 template <
typename V>
381 if (!IsValueInRangeForNumericType<V>(tmp)) {
389template <
typename T,
typename U>
393template <
typename T,
typename U>
394 requires(std::integral<T> && std::integral<U>)
396 using result_type = std::make_unsigned_t<MaxExponentPromotion<T, U>>;
397 template <
typename V>
401 if (!IsValueInRangeForNumericType<V>(tmp)) {
411template <
typename T,
typename U>
414template <
typename T,
typename U>
415 requires(std::is_arithmetic_v<T> && std::is_arithmetic_v<U>)
418 template <
typename V>
423 if (!IsValueInRangeForNumericType<V>(tmp)) {
433template <
typename T,
typename U>
436template <
typename T,
typename U>
437 requires(std::is_arithmetic_v<T> && std::is_arithmetic_v<U>)
440 template <
typename V>
445 if (!IsValueInRangeForNumericType<V>(tmp)) {
455#define BASE_FLOAT_ARITHMETIC_OPS(NAME, OP) \
456 template <typename T, typename U> \
457 requires(std::floating_point<T> || std::floating_point<U>) \
458 struct Checked##NAME##Op<T, U> { \
459 using result_type = MaxExponentPromotion<T, U>; \
460 template <typename V> \
461 static constexpr bool Do(T x, U y, V* result) { \
462 const result_type presult = x OP y; \
463 if (!IsValueInRangeForNumericType<V>(presult)) return false; \
464 *result = static_cast<V>(presult); \
474#undef BASE_FLOAT_ARITHMETIC_OPS
485template <
typename NumericType>
488 std::integral<NumericType>
502 template <
typename Src =
int>
504 : is_valid_(is_valid && IsValueInRangeForNumericType<T>(value)),
505 value_(WellDefinedConversionOrZero(value, is_valid_)) {
506 static_assert(std::is_arithmetic_v<Src>,
"Argument must be numeric.");
509 template <
typename Src>
513 constexpr bool is_valid()
const {
return is_valid_; }
519 template <
typename Src>
522 ?
static_cast<T
>(
value)
537 template <
typename Src =
double>
539 :
value_(WellDefinedConversionOrNaN(
540 value, is_valid && IsValueInRangeForNumericType<T>(value))) {}
542 template <
typename Src>
549 return std::is_constant_evaluated()
550 ? value_ <= std::numeric_limits<T>::max() &&
551 value_ >= std::numeric_limits<T>::lowest()
559 template <
typename Src>
564 ?
static_cast<T
>(
value)
565 : std::numeric_limits<T>::quiet_NaN();
#define BASE_FLOAT_ARITHMETIC_OPS(NAME, OP)
static constexpr T WellDefinedConversionOrNaN(Src value, bool is_valid)
constexpr bool is_valid() const
constexpr CheckedNumericState(Src value=0.0, bool is_valid=true)
constexpr CheckedNumericState(const CheckedNumericState< Src > &rhs)
constexpr T value() const
constexpr T value() const
constexpr CheckedNumericState(const CheckedNumericState< Src > &rhs)
constexpr CheckedNumericState(Src value=0, bool is_valid=true)
static constexpr T WellDefinedConversionOrZero(Src value, bool is_valid)
constexpr bool is_valid() const
ZoneVector< RpoNumber > & result
constexpr auto SafeUnsignedAbs(T value)
constexpr bool IsValueNegative(T value)
constexpr int kIntegerBitsPlusSign
constexpr bool CheckedAddImpl(T x, T y, T *result)
constexpr auto kStaticDstRangeRelationToSrcRange
constexpr auto as_unsigned(Src value)
UnderlyingTypeImpl< T >::type UnderlyingType
constexpr bool CheckedMulImpl(T x, T y, T *result)
BigEnoughPromotionImpl< Lhs, Rhs >::type BigEnoughPromotion
constexpr bool kIsIntegerArithmeticSafe
std::conditional_t< std::is_signed_v< Lhs > ?(!std::is_signed_v< Rhs >||kMaxExponent< Lhs > > kMaxExponent< Rhs >) :(!std::is_signed_v< Rhs > &&kMaxExponent< Lhs >< kMaxExponent< Rhs >), Lhs, Rhs > LowestValuePromotion
constexpr bool CheckedSubImpl(T x, T y, T *result)
FastIntegerArithmeticPromotionImpl< Lhs, Rhs >::type FastIntegerArithmeticPromotion
std::conditional_t<(kMaxExponent< Lhs > > kMaxExponent< Rhs >), Lhs, Rhs > MaxExponentPromotion
static constexpr bool Do(T, U, V *)
MaxExponentPromotion< T, U > result_type
static constexpr bool Do(T x, U y, V *result)
std::make_unsigned_t< MaxExponentPromotion< T, U > > result_type
static constexpr bool Do(T x, U y, V *result)
MaxExponentPromotion< T, U > result_type
static constexpr bool Do(T x, U y, V *result)
static constexpr bool Do(T x, U shift, V *result)
static constexpr bool Do(T x, U y, V *result)
MaxExponentPromotion< T, U > result_type
LowestValuePromotion< T, U > result_type
static constexpr bool Do(T x, U y, V *result)
MaxExponentPromotion< T, U > result_type
static constexpr bool Do(T x, U y, V *result)
static constexpr bool Do(T, U, V *)
MaxExponentPromotion< T, U > result_type
static constexpr bool Do(T x, U y, V *result)
static constexpr bool Do(T x, U y, V *result)
std::make_unsigned_t< MaxExponentPromotion< T, U > > result_type
static constexpr bool Do(T x, U shift, V *result)
static constexpr bool Do(T, U, V *)
MaxExponentPromotion< T, U > result_type
static constexpr bool Do(T x, U y, V *result)
static constexpr bool Do(T x, U y, V *result)
std::make_unsigned_t< MaxExponentPromotion< T, U > > result_type
static constexpr bool Test(L lhs, R rhs)
static constexpr bool Test(L lhs, R rhs)
std::unique_ptr< ValueMirror > value