Flutter Engine
The Flutter Engine
saturated_math.h
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
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 FLUTTER_IMPELLER_GEOMETRY_SATURATED_MATH_H_
6#define FLUTTER_IMPELLER_GEOMETRY_SATURATED_MATH_H_
7
8#include <algorithm>
9#include <limits>
10#include <type_traits>
11
12#include "flutter/fml/logging.h"
14
15namespace impeller {
16
17namespace saturated {
18
19// NOLINTBEGIN(readability-identifier-naming)
20template <typename T>
21inline constexpr bool is_signed_integral_v =
22 std::is_integral_v<T> && std::is_signed_v<T>;
23// NOLINTEND(readability-identifier-naming)
24
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)
29
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)
34
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)
41
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>, \
47 Ret>
48#define ONLY_ON_DIFFERING_FLOAT(FPType1, FPType2) \
49 ONLY_ON_DIFFERING_FLOAT_RET(FPType1, FPType2, FPType2)
50
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)
56
58 if (location >= 0) {
59 if (distance > std::numeric_limits<SI>::max() - location) {
61 }
62 } else if (distance < std::numeric_limits<SI>::min() - location) {
64 }
65 return location + distance;
66}
67
68ONLY_ON_FLOAT(FP) Add(FP location, FP distance) {
69 return location + distance;
70}
71
73 if (upper >= 0) {
74 if (lower < 0 && upper > std::numeric_limits<SI>::max() + lower) {
76 }
77 } else if (lower > 0 && upper < std::numeric_limits<SI>::min() + lower) {
79 }
80 return upper - lower;
81}
82
83ONLY_ON_FLOAT(FP) Sub(FP upper, FP lower) {
84 return upper - lower;
85}
86
87ONLY_ON_SIGNED_INT_RET(SI, Scalar) AverageScalar(SI a, SI b) {
88 // scalbn has an implementation for ints that converts to double
89 // while adjusting the exponent.
90 return static_cast<Scalar>(std::scalbn(a, -1) + std::scalbn(b, -1));
91}
92
93ONLY_ON_FLOAT(FP) AverageScalar(FP a, FP b) {
94 // GetCenter might want this to return 0 for a Maximum Rect, but it
95 // will currently produce NaN instead. For the Maximum Rect itself
96 // a 0 would make sense as the center, but for a computed rect that
97 // incidentally ended up with infinities, NaN may be a better choice.
98 // return static_cast<Scalar>(std::scalbn(a, -1) + std::scalbn(b, -1));
99
100 // This equation would save an extra scalbn operation but at the cost
101 // of having very large (or very neagive) a's and b's overflow to
102 // +/- infinity. Scaling first allows finite numbers to be more likely
103 // to have a finite average.
104 // return std::scalbn(a + b, -1);
105
106 return static_cast<Scalar>(std::scalbn(a, -1) + std::scalbn(b, -1));
107}
108
110 return v;
111}
112
114 if (v <= static_cast<FP>(std::numeric_limits<SI>::min())) {
116 } else if (v >= static_cast<FP>(std::numeric_limits<SI>::max())) {
118 }
119 return static_cast<SI>(v);
120}
121
122ONLY_ON_DIFFERING_FLOAT(FP1, FP2) Cast(FP1 v) {
123 if (std::isfinite(v)) {
124 // Avoid truncation to inf/-inf.
125 return std::clamp(static_cast<FP2>(v), //
126 std::numeric_limits<FP2>::lowest(),
128 } else {
129 return static_cast<FP2>(v);
130 }
131}
132
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
139#undef ONLY_ON_FLOAT
140#undef ONLY_ON_FLOAT_RET
141#undef ONLY_ON_SIGNED_INT
142#undef ONLY_ON_SIGNED_INT_RET
143
144} // namespace saturated
145
146} // namespace impeller
147
148#endif // FLUTTER_IMPELLER_GEOMETRY_SATURATED_MATH_H_
static unsigned clamp(SkFixed fx, int max)
#define SI
Definition: Transform_inl.h:94
struct MyStruct a[10]
static float max(float r, float g, float b)
Definition: hsl.cpp:49
static float min(float r, float g, float b)
Definition: hsl.cpp:48
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
float Scalar
Definition: scalar.h:18
SINT bool isfinite(const Vec< N, T > &v)
Definition: SkVx.h:1003
#define T
Definition: precompiler.cc:65