blob: 88c17009cc06a4a6276a0249c810a51cc8a37c50 [file] [log] [blame]
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +01001/*
Pablo Tello826c7692018-01-16 11:41:12 +00002 * Copyright (c) 2017-2018 ARM Limited.
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +01003 *
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
Ioan-Cristian Szabo33fd07b2017-10-26 15:42:24 +010037#include "support/Half.h"
38
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010039namespace arm_compute
40{
41namespace support
42{
43namespace cpp11
44{
Michalis Spyrou07781ac2017-08-31 15:11:41 +010045#if(__ANDROID__ || BARE_METAL)
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010046/** Convert integer and float values to string.
47 *
48 * @note This function implements the same behaviour as std::to_string. The
49 * latter is missing in some Android toolchains.
50 *
51 * @param[in] value Value to be converted to string.
52 *
53 * @return String representation of @p value.
54 */
55template <typename T, typename std::enable_if<std::is_arithmetic<typename std::decay<T>::type>::value, int>::type = 0>
Moritz Pflanzer572ade72017-07-21 17:36:33 +010056inline std::string to_string(T && value)
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010057{
58 std::stringstream stream;
59 stream << std::forward<T>(value);
60 return stream.str();
61}
62
63/** Convert string values to integer.
64 *
65 * @note This function implements the same behaviour as std::stoi. The latter
66 * is missing in some Android toolchains.
67 *
68 * @param[in] str String to be converted to int.
69 *
70 * @return Integer representation of @p str.
71 */
Pablo Tello7fad9b12018-03-14 17:55:27 +000072inline int stoi(const std::string &str, std::size_t *pos = 0, int base = 10)
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010073{
Pablo Tello7fad9b12018-03-14 17:55:27 +000074 unsigned int x;
75 std::stringstream ss;
76 if(base == 16)
77 {
78 ss << std::hex;
79 }
80 ss << str;
81 ss >> x;
82 return x;
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010083}
84
85/** Convert string values to unsigned long.
86 *
87 * @note This function implements the same behaviour as std::stoul. The latter
88 * is missing in some Android toolchains.
89 *
90 * @param[in] str String to be converted to unsigned long.
91 *
92 * @return Unsigned long representation of @p str.
93 */
Pablo Tello7fad9b12018-03-14 17:55:27 +000094inline unsigned long stoul(const std::string &str, std::size_t *pos = 0, int base = 10)
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010095{
Pablo Tello7fad9b12018-03-14 17:55:27 +000096 std::stringstream stream;
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010097 unsigned long value = 0;
Pablo Tello7fad9b12018-03-14 17:55:27 +000098 if(base == 16)
99 {
100 stream << std::hex;
101 }
102 stream << str;
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100103 stream >> value;
104 return value;
105}
106
107/** Convert string values to float.
108 *
109 * @note This function implements the same behaviour as std::stof. The latter
110 * is missing in some Android toolchains.
111 *
112 * @param[in] str String to be converted to float.
113 *
114 * @return Float representation of @p str.
115 */
116inline float stof(const std::string &str)
117{
118 std::stringstream stream(str);
119 float value = 0.f;
120 stream >> value;
121 return value;
122}
123
124/** Round floating-point value with half value rounding away from zero.
125 *
126 * @note This function implements the same behaviour as std::round except that it doesn't
127 * support Integral type. The latter is not in the namespace std in some Android toolchains.
128 *
129 * @param[in] value floating-point value to be rounded.
130 *
131 * @return Floating-point value of rounded @p value.
132 */
133template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
134inline T round(T value)
135{
136 return ::round(value);
137}
138
139/** Truncate floating-point value.
140 *
141 * @note This function implements the same behaviour as std::truncate except that it doesn't
142 * support Integral type. The latter is not in the namespace std in some Android toolchains.
143 *
144 * @param[in] value floating-point value to be truncated.
145 *
146 * @return Floating-point value of truncated @p value.
147 */
148template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
149inline T trunc(T value)
150{
151 return ::trunc(value);
152}
153
154/** Composes a floating point value with the magnitude of @p x and the sign of @p y.
155 *
156 * @note This function implements the same behaviour as std::copysign except that it doesn't
157 * support Integral type. The latter is not in the namespace std in some Android toolchains.
158 *
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100159 * @param[in] x value that contains the magnitude to be used in constructing the result.
160 * @param[in] y value that contains the sign to be used in construct in the result.
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100161 *
162 * @return Floating-point value with magnitude of @p x and sign of @p y.
163 */
164template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
165inline T copysign(T x, T y)
166{
167 return ::copysign(x, y);
168}
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100169
170/** Loads the data from the given location, converts them to character string equivalents
171 * and writes the result to a character string buffer.
172 *
173 * @param[in] s Pointer to a character string to write to
174 * @param[in] n Up to buf_size - 1 characters may be written, plus the null terminator
175 * @param[in] fmt Pointer to a null-terminated multibyte string specifying how to interpret the data.
176 * @param[in] args Arguments forwarded to snprintf.
177 *
178 * @return Number of characters that would have been written for a sufficiently large buffer
179 * if successful (not including the terminating null character), or a negative value if an error occurred.
180 */
181template <typename... Ts>
182inline int snprintf(char *s, size_t n, const char *fmt, Ts &&... args)
183{
184 return ::snprintf(s, n, fmt, std::forward<Ts>(args)...);
185}
Michalis Spyrou07781ac2017-08-31 15:11:41 +0100186#else /* (__ANDROID__ || BARE_METAL) */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100187/** Convert integer and float values to string.
188 *
189 * @note This function acts as a convenience wrapper around std::to_string. The
190 * latter is missing in some Android toolchains.
191 *
192 * @param[in] value Value to be converted to string.
193 *
194 * @return String representation of @p value.
195 */
196template <typename T>
Moritz Pflanzer572ade72017-07-21 17:36:33 +0100197inline std::string to_string(T &&value)
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100198{
199 return ::std::to_string(std::forward<T>(value));
200}
201
202/** Convert string values to integer.
203 *
204 * @note This function acts as a convenience wrapper around std::stoi. The
205 * latter is missing in some Android toolchains.
206 *
207 * @param[in] args Arguments forwarded to std::stoi.
208 *
209 * @return Integer representation of input string.
210 */
211template <typename... Ts>
212int stoi(Ts &&... args)
213{
214 return ::std::stoi(std::forward<Ts>(args)...);
215}
216
217/** Convert string values to unsigned long.
218 *
219 * @note This function acts as a convenience wrapper around std::stoul. The
220 * latter is missing in some Android toolchains.
221 *
222 * @param[in] args Arguments forwarded to std::stoul.
223 *
224 * @return Unsigned long representation of input string.
225 */
226template <typename... Ts>
227int stoul(Ts &&... args)
228{
229 return ::std::stoul(std::forward<Ts>(args)...);
230}
231
232/** Convert string values to float.
233 *
234 * @note This function acts as a convenience wrapper around std::stof. The
235 * latter is missing in some Android toolchains.
236 *
237 * @param[in] args Arguments forwarded to std::stof.
238 *
239 * @return Float representation of input string.
240 */
241template <typename... Ts>
242int stof(Ts &&... args)
243{
244 return ::std::stof(std::forward<Ts>(args)...);
245}
246
247/** Round floating-point value with half value rounding away from zero.
248 *
249 * @note This function implements the same behaviour as std::round except that it doesn't
250 * support Integral type. The latter is not in the namespace std in some Android toolchains.
251 *
252 * @param[in] value floating-point value to be rounded.
253 *
254 * @return Floating-point value of rounded @p value.
255 */
256template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
257inline T round(T value)
258{
Pablo Tello826c7692018-01-16 11:41:12 +0000259 //Workaround Valgrind's mismatches: when running from Valgrind the call to std::round(-4.500000) == -4.000000 instead of 5.00000
260 return (value < 0.f) ? static_cast<int>(value - 0.5f) : static_cast<int>(value + 0.5f);
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100261}
262
263/** Truncate floating-point value.
264 *
265 * @note This function implements the same behaviour as std::truncate except that it doesn't
266 * support Integral type. The latter is not in the namespace std in some Android toolchains.
267 *
268 * @param[in] value floating-point value to be truncated.
269 *
270 * @return Floating-point value of truncated @p value.
271 */
272template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
273inline T trunc(T value)
274{
275 return std::trunc(value);
276}
277
278/** Composes a floating point value with the magnitude of @p x and the sign of @p y.
279 *
280 * @note This function implements the same behaviour as std::copysign except that it doesn't
281 * support Integral type. The latter is not in the namespace std in some Android toolchains.
282 *
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100283 * @param[in] x value that contains the magnitude to be used in constructing the result.
284 * @param[in] y value that contains the sign to be used in construct in the result.
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100285 *
286 * @return Floating-point value with magnitude of @p x and sign of @p y.
287 */
288template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
289inline T copysign(T x, T y)
290{
291 return std::copysign(x, y);
292}
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100293
294/** Loads the data from the given location, converts them to character string equivalents
295 * and writes the result to a character string buffer.
296 *
297 * @param[in] s Pointer to a character string to write to
298 * @param[in] n Up to buf_size - 1 characters may be written, plus the null terminator
299 * @param[in] fmt Pointer to a null-terminated multibyte string specifying how to interpret the data.
300 * @param[in] args Arguments forwarded to std::snprintf.
301 *
302 * @return Number of characters that would have been written for a sufficiently large buffer
303 * if successful (not including the terminating null character), or a negative value if an error occurred.
304 */
305template <typename... Ts>
306inline int snprintf(char *s, std::size_t n, const char *fmt, Ts &&... args)
307{
308 return std::snprintf(s, n, fmt, std::forward<Ts>(args)...);
309}
Michalis Spyrou07781ac2017-08-31 15:11:41 +0100310#endif /* (__ANDROID__ || BARE_METAL) */
Moritz Pflanzer572ade72017-07-21 17:36:33 +0100311
312inline std::string to_string(bool value)
313{
314 std::stringstream str;
315 str << std::boolalpha << value;
316 return str.str();
317}
Moritz Pflanzerbeabe3b2017-08-31 14:56:32 +0100318
319// std::align is missing in GCC 4.9
320// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57350
321inline void *align(std::size_t alignment, std::size_t size, void *&ptr, std::size_t &space)
322{
323 std::uintptr_t pn = reinterpret_cast<std::uintptr_t>(ptr);
324 std::uintptr_t aligned = (pn + alignment - 1) & -alignment;
325 std::size_t padding = aligned - pn;
326 if(space < size + padding)
327 {
328 return nullptr;
329 }
330
331 space -= padding;
332
333 return ptr = reinterpret_cast<void *>(aligned);
334}
Ioan-Cristian Szabo33fd07b2017-10-26 15:42:24 +0100335
336// std::isfinite
337template <typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
338inline bool isfinite(T value)
339{
340 return std::isfinite(value);
341}
342
343inline bool isfinite(half_float::half value)
344{
345 return half_float::isfinite(value);
346}
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100347} // namespace cpp11
348
349namespace cpp14
350{
Georgios Pinitas84b51ad2017-11-07 13:24:57 +0000351/** make_unique is missing in CPP11. Re-implement it according to the standard proposal. */
Alex Gildayc357c472018-03-21 13:54:09 +0000352
353/**<Template for single object */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100354template <class T>
355struct _Unique_if
356{
Alex Gildayc357c472018-03-21 13:54:09 +0000357 typedef std::unique_ptr<T> _Single_object; /**< Single object type */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100358};
359
Alex Gildayc357c472018-03-21 13:54:09 +0000360/** Template for array */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100361template <class T>
362struct _Unique_if<T[]>
363{
Alex Gildayc357c472018-03-21 13:54:09 +0000364 typedef std::unique_ptr<T[]> _Unknown_bound; /**< Array type */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100365};
366
Alex Gildayc357c472018-03-21 13:54:09 +0000367/** Template for array with known bounds (to throw an error).
368 *
369 * @note this is intended to never be hit.
370 */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100371template <class T, size_t N>
372struct _Unique_if<T[N]>
373{
Alex Gildayc357c472018-03-21 13:54:09 +0000374 typedef void _Known_bound; /**< Should never be used */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100375};
376
Alex Gildayc357c472018-03-21 13:54:09 +0000377/** Construct a single object and return a unique pointer to it.
378 *
379 * @param[in] args Constructor arguments.
380 *
381 * @return a unique pointer to the new object.
382 */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100383template <class T, class... Args>
384typename _Unique_if<T>::_Single_object
385make_unique(Args &&... args)
386{
387 return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
388}
389
Alex Gildayc357c472018-03-21 13:54:09 +0000390/** Construct an array of objects and return a unique pointer to it.
391 *
392 * @param[in] n Array size
393 *
394 * @return a unique pointer to the new array.
395 */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100396template <class T>
397typename _Unique_if<T>::_Unknown_bound
398make_unique(size_t n)
399{
400 typedef typename std::remove_extent<T>::type U;
401 return std::unique_ptr<T>(new U[n]());
402}
403
Alex Gildayc357c472018-03-21 13:54:09 +0000404/** It is invalid to attempt to make_unique an array with known bounds. */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100405template <class T, class... Args>
406typename _Unique_if<T>::_Known_bound
407make_unique(Args &&...) = delete;
408} // namespace cpp14
409} // namespace support
410} // namespace arm_compute
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100411#endif /* ARM_COMPUTE_TEST_TOOLCHAINSUPPORT */