5 #ifndef FLUTTER_IMPELLER_GEOMETRY_SATURATED_MATH_H_
6 #define FLUTTER_IMPELLER_GEOMETRY_SATURATED_MATH_H_
10 #include <type_traits>
12 #include "flutter/fml/logging.h"
22 std::is_integral_v<T> && std::is_signed_v<T>;
25 #define ONLY_ON_SIGNED_INT_RET(Type, Ret) \
26 template <typename Type> \
27 constexpr inline std::enable_if_t<is_signed_integral_v<Type>, Ret>
28 #define ONLY_ON_SIGNED_INT(Type) ONLY_ON_SIGNED_INT_RET(Type, Type)
30 #define ONLY_ON_FLOAT_RET(Type, Ret) \
31 template <typename Type> \
32 constexpr inline std::enable_if_t<std::is_floating_point_v<Type>, Ret>
33 #define ONLY_ON_FLOAT(Type) ONLY_ON_FLOAT_RET(Type, Type)
35 #define ONLY_ON_FLOAT_TO_SIGNED_INT_RET(FPType, SIType, Ret) \
36 template <typename FPType, typename SIType> \
37 constexpr inline std::enable_if_t< \
38 std::is_floating_point_v<FPType> && is_signed_integral_v<SIType>, Ret>
39 #define ONLY_ON_FLOAT_TO_SIGNED_INT(FPType, SIType) \
40 ONLY_ON_FLOAT_TO_SIGNED_INT_RET(FPType, SIType, SIType)
42 #define ONLY_ON_DIFFERING_FLOAT_RET(FPType1, FPType2, Ret) \
43 template <typename FPType1, typename FPType2> \
44 constexpr inline std::enable_if_t<std::is_floating_point_v<FPType1> && \
45 std::is_floating_point_v<FPType2> && \
46 !std::is_same_v<FPType1, FPType2>, \
48 #define ONLY_ON_DIFFERING_FLOAT(FPType1, FPType2) \
49 ONLY_ON_DIFFERING_FLOAT_RET(FPType1, FPType2, FPType2)
51 #define ONLY_ON_SAME_TYPES_RET(Type1, Type2, Ret) \
52 template <typename Type1, typename Type2> \
53 constexpr inline std::enable_if_t<std::is_same_v<Type1, Type2>, Ret>
54 #define ONLY_ON_SAME_TYPES(Type1, Type2) \
55 ONLY_ON_SAME_TYPES_RET(Type1, Type2, Type2)
59 if (
distance > std::numeric_limits<SI>::max() - location) {
60 return std::numeric_limits<SI>::max();
62 }
else if (
distance < std::numeric_limits<SI>::min() - location) {
63 return std::numeric_limits<SI>::min();
74 if (lower < 0 && upper > std::numeric_limits<SI>::max() +
lower) {
75 return std::numeric_limits<SI>::max();
77 }
else if (
lower > 0 && upper < std::numeric_limits<SI>::min() +
lower) {
78 return std::numeric_limits<SI>::min();
90 return static_cast<Scalar>(std::scalbn(a, -1) + std::scalbn(
b, -1));
106 return static_cast<Scalar>(std::scalbn(a, -1) + std::scalbn(
b, -1));
114 if (v <=
static_cast<FP
>(std::numeric_limits<SI>::min())) {
115 return std::numeric_limits<SI>::min();
116 }
else if (v >=
static_cast<FP
>(std::numeric_limits<SI>::max())) {
117 return std::numeric_limits<SI>::max();
119 return static_cast<SI
>(v);
123 if (std::isfinite(v)) {
125 return std::clamp(
static_cast<FP2
>(v),
126 std::numeric_limits<FP2>::lowest(),
127 std::numeric_limits<FP2>::max());
129 return static_cast<FP2
>(v);
133 #undef ONLY_ON_SAME_TYPES
134 #undef ONLY_ON_SAME_TYPES_RET
135 #undef ONLY_ON_DIFFERING_FLOAT
136 #undef ONLY_ON_DIFFERING_FLOAT_RET
137 #undef ONLY_ON_FLOAT_TO_SIGNED_INT
138 #undef ONLY_ON_FLOAT_TO_SIGNED_INT_RET
140 #undef ONLY_ON_FLOAT_RET
141 #undef ONLY_ON_SIGNED_INT
142 #undef ONLY_ON_SIGNED_INT_RET
ONLY_ON_SAME_TYPES(T, U) Cast(T v)
ONLY_ON_SIGNED_INT(SI) Add(SI location
ONLY_ON_DIFFERING_FLOAT(FP1, FP2) Cast(FP1 v)
ONLY_ON_FLOAT_TO_SIGNED_INT(FP, SI) Cast(FP v)
ONLY_ON_FLOAT(FP) Add(FP location
constexpr bool is_signed_integral_v
ONLY_ON_SIGNED_INT_RET(SI, Scalar) AverageScalar(SI a