arm_compute v17.10
[platform/upstream/armcl.git] / support / ToolchainSupport.h
1 /*
2  * Copyright (c) 2017 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_TEST_TOOLCHAINSUPPORT
25 #define ARM_COMPUTE_TEST_TOOLCHAINSUPPORT
26
27 #include <algorithm>
28 #include <cmath>
29 #include <cstddef>
30 #include <limits>
31 #include <memory>
32 #include <numeric>
33 #include <sstream>
34 #include <string>
35 #include <type_traits>
36
37 namespace arm_compute
38 {
39 namespace support
40 {
41 namespace cpp11
42 {
43 #if(__ANDROID__ || BARE_METAL)
44 /** Convert integer and float values to string.
45  *
46  * @note This function implements the same behaviour as std::to_string. The
47  *       latter is missing in some Android toolchains.
48  *
49  * @param[in] value Value to be converted to string.
50  *
51  * @return String representation of @p value.
52  */
53 template <typename T, typename std::enable_if<std::is_arithmetic<typename std::decay<T>::type>::value, int>::type = 0>
54 inline std::string to_string(T && value)
55 {
56     std::stringstream stream;
57     stream << std::forward<T>(value);
58     return stream.str();
59 }
60
61 /** Convert string values to integer.
62  *
63  * @note This function implements the same behaviour as std::stoi. The latter
64  *       is missing in some Android toolchains.
65  *
66  * @param[in] str String to be converted to int.
67  *
68  * @return Integer representation of @p str.
69  */
70 inline int stoi(const std::string &str)
71 {
72     std::stringstream stream(str);
73     int               value = 0;
74     stream >> value;
75     return value;
76 }
77
78 /** Convert string values to unsigned long.
79  *
80  * @note This function implements the same behaviour as std::stoul. The latter
81  *       is missing in some Android toolchains.
82  *
83  * @param[in] str String to be converted to unsigned long.
84  *
85  * @return Unsigned long representation of @p str.
86  */
87 inline unsigned long stoul(const std::string &str)
88 {
89     std::stringstream stream(str);
90     unsigned long     value = 0;
91     stream >> value;
92     return value;
93 }
94
95 /** Convert string values to float.
96  *
97  * @note This function implements the same behaviour as std::stof. The latter
98  *       is missing in some Android toolchains.
99  *
100  * @param[in] str String to be converted to float.
101  *
102  * @return Float representation of @p str.
103  */
104 inline float stof(const std::string &str)
105 {
106     std::stringstream stream(str);
107     float             value = 0.f;
108     stream >> value;
109     return value;
110 }
111
112 /** Round floating-point value with half value rounding away from zero.
113  *
114  * @note This function implements the same behaviour as std::round except that it doesn't
115  *       support Integral type. The latter is not in the namespace std in some Android toolchains.
116  *
117  * @param[in] value floating-point value to be rounded.
118  *
119  * @return Floating-point value of rounded @p value.
120  */
121 template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
122 inline T round(T value)
123 {
124     return ::round(value);
125 }
126
127 /** Truncate floating-point value.
128  *
129  * @note This function implements the same behaviour as std::truncate except that it doesn't
130  *       support Integral type. The latter is not in the namespace std in some Android toolchains.
131  *
132  * @param[in] value floating-point value to be truncated.
133  *
134  * @return Floating-point value of truncated @p value.
135  */
136 template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
137 inline T trunc(T value)
138 {
139     return ::trunc(value);
140 }
141
142 /** Composes a floating point value with the magnitude of @p x and the sign of @p y.
143  *
144  * @note This function implements the same behaviour as std::copysign except that it doesn't
145  *       support Integral type. The latter is not in the namespace std in some Android toolchains.
146  *
147  * @param[in] x value that contains the magnitued to be used in constructing the result.
148  * @param[in] y value that contains the sign to be used in constructin the result.
149  *
150  * @return Floating-point value with magnitude of @p x and sign of @p y.
151  */
152 template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
153 inline T copysign(T x, T y)
154 {
155     return ::copysign(x, y);
156 }
157 #else  /* (__ANDROID__ || BARE_METAL) */
158 /** Convert integer and float values to string.
159  *
160  * @note This function acts as a convenience wrapper around std::to_string. The
161  *       latter is missing in some Android toolchains.
162  *
163  * @param[in] value Value to be converted to string.
164  *
165  * @return String representation of @p value.
166  */
167 template <typename T>
168 inline std::string to_string(T &&value)
169 {
170     return ::std::to_string(std::forward<T>(value));
171 }
172
173 /** Convert string values to integer.
174  *
175  * @note This function acts as a convenience wrapper around std::stoi. The
176  *       latter is missing in some Android toolchains.
177  *
178  * @param[in] args Arguments forwarded to std::stoi.
179  *
180  * @return Integer representation of input string.
181  */
182 template <typename... Ts>
183 int stoi(Ts &&... args)
184 {
185     return ::std::stoi(std::forward<Ts>(args)...);
186 }
187
188 /** Convert string values to unsigned long.
189  *
190  * @note This function acts as a convenience wrapper around std::stoul. The
191  *       latter is missing in some Android toolchains.
192  *
193  * @param[in] args Arguments forwarded to std::stoul.
194  *
195  * @return Unsigned long representation of input string.
196  */
197 template <typename... Ts>
198 int stoul(Ts &&... args)
199 {
200     return ::std::stoul(std::forward<Ts>(args)...);
201 }
202
203 /** Convert string values to float.
204  *
205  * @note This function acts as a convenience wrapper around std::stof. The
206  *       latter is missing in some Android toolchains.
207  *
208  * @param[in] args Arguments forwarded to std::stof.
209  *
210  * @return Float representation of input string.
211  */
212 template <typename... Ts>
213 int stof(Ts &&... args)
214 {
215     return ::std::stof(std::forward<Ts>(args)...);
216 }
217
218 /** Round floating-point value with half value rounding away from zero.
219  *
220  * @note This function implements the same behaviour as std::round except that it doesn't
221  *       support Integral type. The latter is not in the namespace std in some Android toolchains.
222  *
223  * @param[in] value floating-point value to be rounded.
224  *
225  * @return Floating-point value of rounded @p value.
226  */
227 template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
228 inline T round(T value)
229 {
230     return std::round(value);
231 }
232
233 /** Truncate floating-point value.
234  *
235  * @note This function implements the same behaviour as std::truncate except that it doesn't
236  *       support Integral type. The latter is not in the namespace std in some Android toolchains.
237  *
238  * @param[in] value floating-point value to be truncated.
239  *
240  * @return Floating-point value of truncated @p value.
241  */
242 template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
243 inline T trunc(T value)
244 {
245     return std::trunc(value);
246 }
247
248 /** Composes a floating point value with the magnitude of @p x and the sign of @p y.
249  *
250  * @note This function implements the same behaviour as std::copysign except that it doesn't
251  *       support Integral type. The latter is not in the namespace std in some Android toolchains.
252  *
253  * @param[in] x value that contains the magnitued to be used in constructing the result.
254  * @param[in] y value that contains the sign to be used in constructin the result.
255  *
256  * @return Floating-point value with magnitude of @p x and sign of @p y.
257  */
258 template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
259 inline T copysign(T x, T y)
260 {
261     return std::copysign(x, y);
262 }
263 #endif /* (__ANDROID__ || BARE_METAL) */
264
265 inline std::string to_string(bool value)
266 {
267     std::stringstream str;
268     str << std::boolalpha << value;
269     return str.str();
270 }
271
272 // std::align is missing in GCC 4.9
273 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57350
274 inline void *align(std::size_t alignment, std::size_t size, void *&ptr, std::size_t &space)
275 {
276     std::uintptr_t pn      = reinterpret_cast<std::uintptr_t>(ptr);
277     std::uintptr_t aligned = (pn + alignment - 1) & -alignment;
278     std::size_t    padding = aligned - pn;
279     if(space < size + padding)
280     {
281         return nullptr;
282     }
283
284     space -= padding;
285
286     return ptr = reinterpret_cast<void *>(aligned);
287 }
288 } // namespace cpp11
289
290 namespace cpp14
291 {
292 /** make_unqiue is missing in CPP11. Reimplement it according to the standard
293  * proposal.
294  */
295 template <class T>
296 struct _Unique_if
297 {
298     typedef std::unique_ptr<T> _Single_object;
299 };
300
301 template <class T>
302 struct _Unique_if<T[]>
303 {
304     typedef std::unique_ptr<T[]> _Unknown_bound;
305 };
306
307 template <class T, size_t N>
308 struct _Unique_if<T[N]>
309 {
310     typedef void _Known_bound;
311 };
312
313 template <class T, class... Args>
314 typename _Unique_if<T>::_Single_object
315 make_unique(Args &&... args)
316 {
317     return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
318 }
319
320 template <class T>
321 typename _Unique_if<T>::_Unknown_bound
322 make_unique(size_t n)
323 {
324     typedef typename std::remove_extent<T>::type U;
325     return std::unique_ptr<T>(new U[n]());
326 }
327
328 template <class T, class... Args>
329 typename _Unique_if<T>::_Known_bound
330 make_unique(Args &&...) = delete;
331 } // namespace cpp14
332 } // namespace support
333 } // namespace arm_compute
334 #endif /* ARM_COMPUTE_TEST_TOOLCHAINSUPPORT */