Compute Library
 21.02
SaturateCast.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-2020 Arm Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #ifndef ARM_COMPUTE_UTILS_CAST_SATURATE_CAST_H
25 #define ARM_COMPUTE_UTILS_CAST_SATURATE_CAST_H
26 
29 #include "support/Rounding.h"
30 
31 namespace arm_compute
32 {
33 namespace utils
34 {
35 namespace cast
36 {
37 // *INDENT-OFF*
38 // clang-format off
39 // same type
40 template<typename T,
41  typename U,
42  typename std::enable_if<std::is_same<T, U>::value, int >::type = 0 >
44 {
45  return v;
46 }
47 
48 // signed -> signed widening/same_width
49 template<typename T,
50  typename U,
51  typename std::enable_if<std::is_integral<T>::value &&
52  std::is_integral<U>::value &&
53  std::is_signed<U>() &&
54  std::is_signed<T>() &&
55  !std::is_same<T, U>::value &&
56  sizeof(T) >= sizeof(U),
57  int >::type = 0 >
58 inline T saturate_cast(U v)
59 {
60  return static_cast<T>(v);
61 }
62 // signed -> signed narrowing
63 template<typename T,
64  typename U,
65  typename std::enable_if<std::is_integral<T>::value &&
66  std::is_integral<U>::value &&
67  std::is_signed<U>() &&
68  std::is_signed<T>() &&
69  !std::is_same<T, U>::value &&
70  sizeof(T) < sizeof(U),
71  int >::type = 0 >
72 inline T saturate_cast(U v)
73 {
74  return static_cast<T>(utility::clamp<U>(v, std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max()));
75 }
76 
77 // unsigned -> signed widening
78 template<typename T,
79  typename U,
80  typename std::enable_if<std::is_integral<T>::value &&
81  std::is_integral<U>::value &&
82  std::is_unsigned<U>() &&
83  std::is_signed<T>() &&
84  !std::is_same<T, U>::value &&
85  (sizeof(T) > sizeof(U)),
86  int >::type = 0 >
87 inline T saturate_cast(U v)
88 {
89  return static_cast<T>(v);
90 }
91 // unsigned -> signed narrowing
92 template<typename T,
93  typename U,
94  typename std::enable_if<std::is_integral<T>::value &&
95  std::is_integral<U>::value &&
96  std::is_unsigned<U>() &&
97  std::is_signed<T>() &&
98  !std::is_same<T, U>::value &&
99  sizeof(T) < sizeof(U),
100  int >::type = 0 >
101 inline T saturate_cast(U v)
102 {
103  return static_cast<T>(std::min<U>(v, std::numeric_limits<T>::max()));
104 }
105 // unsigned -> signed same_width
106 template<typename T,
107  typename U,
108  typename std::enable_if<std::is_integral<T>::value &&
109  std::is_integral<U>::value &&
110  std::is_unsigned<U>() &&
111  std::is_signed<T>() &&
112  !std::is_same<T, U>::value &&
113  sizeof(T) == sizeof(U),
114  int >::type = 0 >
115 inline T saturate_cast(U v)
116 {
117  return static_cast<T>(std::min<U>(v, std::numeric_limits<T>::max()));
118 }
119 
120 // signed -> unsigned widening/same width
121 template<typename T,
122  typename U,
123  typename std::enable_if<std::is_integral<T>::value &&
124  std::is_integral<U>::value &&
125  std::is_signed<U>() &&
126  std::is_unsigned<T>() &&
127  !std::is_same<T, U>::value &&
128  sizeof(T) >= sizeof(U),
129  int >::type = 0 >
130 inline T saturate_cast(U v)
131 {
132  return static_cast<T>(std::max<U>(0, v));
133 }
134 
135 // signed -> unsigned narrowing
136 template<typename T,
137  typename U,
138  typename std::enable_if<std::is_integral<T>::value &&
139  std::is_integral<U>::value &&
140  std::is_signed<U>() &&
141  std::is_unsigned<T>() &&
142  !std::is_same<T, U>::value &&
143  sizeof(T) < sizeof(U),
144  int >::type = 0 >
145 inline T saturate_cast(U v)
146 {
147  return static_cast<T>(utility::clamp<U>(v, 0, std::numeric_limits<T>::max()));
148 }
149 
150 // unsigned -> unsigned widening/same width
151 template<typename T,
152  typename U,
153  typename std::enable_if<std::is_integral<T>::value &&
154  std::is_integral<U>::value &&
155  std::is_unsigned<T>() &&
156  std::is_unsigned<U>() &&
157  !std::is_same<T, U>::value &&
158  sizeof(T) >= sizeof(U),
159  int >::type = 0 >
160 inline T saturate_cast(U v)
161 {
162  return static_cast<T>(v);
163 }
164 
165 // unsigned -> unsigned narrowing
166 template<typename T,
167  typename U,
168  typename std::enable_if<std::is_integral<T>::value &&
169  std::is_integral<U>::value &&
170  std::is_unsigned<T>() &&
171  std::is_unsigned<U>() &&
172  !std::is_same<T, U>::value &&
173  sizeof(T) < sizeof(U),
174  int >::type = 0 >
175 inline T saturate_cast(U v)
176 {
177  return static_cast<T>(utility::clamp<U>(v, std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max()));
178 }
179 
180 // float -> int
181 template<typename T,
182  typename U,
183  typename std::enable_if<std::is_integral<T>::value &&
185  int >::type = 0 >
186 inline T saturate_cast(U v)
187 {
189  return saturate_cast<T>(vi);
190 }
191 
192 // int -> float
193 template<typename T,
194  typename U,
195  typename std::enable_if<traits::is_floating_point<T>::value &&
196  std::is_integral<U>::value,
197  int >::type = 0 >
198 inline T saturate_cast(U v)
199 {
200  return static_cast<T>(v);
201 }
202 
203 // float -> float
204 template<typename T,
205  typename U,
206  typename std::enable_if<traits::is_floating_point<T>::value &&
207  traits::is_floating_point<U>::value,
208  int >::type = 0 >
209 inline T saturate_cast(U v)
210 {
211  return static_cast<T>(v);
212 }
213 // clang-format on
214 // *INDENT-ON*
215 } // namespace cast
216 } // namespace utils
217 } // namespace arm_compute
218 #endif /* ARM_COMPUTE_UTILS_CAST_SATURATE_CAST_H */
T round_half_away_from_zero(T value)
Round floating-point value with half value rounding away from zero.
Definition: Rounding.h:106
decltype(strategy::transforms) typedef type
Copyright (c) 2017-2021 Arm Limited.