blob: f90d65c9d988367601c5c4866f88ae8fbb86b9b2 [file] [log] [blame]
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +01001/*
Michalis Spyroue6bcb5b2019-06-07 11:47:16 +01002 * Copyright (c) 2017-2019 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>
Pablo Tello65f99822018-05-24 11:40:15 +010028#include <cassert>
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010029#include <cmath>
30#include <cstddef>
31#include <limits>
32#include <memory>
33#include <numeric>
34#include <sstream>
35#include <string>
36#include <type_traits>
37
Giorgio Arenad93e2632019-10-15 11:09:33 +010038#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
39#include <arm_neon.h>
40#endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
41
Ioan-Cristian Szabo33fd07b2017-10-26 15:42:24 +010042#include "support/Half.h"
43
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010044namespace arm_compute
45{
46namespace support
47{
48namespace cpp11
49{
Pablo Tello65f99822018-05-24 11:40:15 +010050enum class NumericBase
51{
52 BASE_10,
53 BASE_16
54};
55
56/** Convert string values to integer.
57 *
58 * @note This function implements the same behaviour as std::stoi. The latter
59 * is missing in some Android toolchains.
60 *
61 * @param[in] str String to be converted to int.
62 * @param[in] pos If idx is not a null pointer, the function sets the value of pos to the position of the first character in str after the number.
63 * @param[in] base Numeric base used to interpret the string.
64 *
65 * @return Integer representation of @p str.
66 */
67inline int stoi(const std::string &str, std::size_t *pos = 0, NumericBase base = NumericBase::BASE_10)
68{
69 assert(base == NumericBase::BASE_10 || base == NumericBase::BASE_16);
70 unsigned int x;
71 std::stringstream ss;
72 if(base == NumericBase::BASE_16)
73 {
74 ss << std::hex;
75 }
76 ss << str;
77 ss >> x;
Michalis Spyrou6bff1952019-10-02 17:22:11 +010078
79 if(pos)
80 {
81 std::string s;
82 std::stringstream ss_p;
83
84 ss_p << x;
85 ss_p >> s;
86 *pos = s.length();
87 }
88
Pablo Tello65f99822018-05-24 11:40:15 +010089 return x;
90}
91
92/** Convert string values to unsigned long.
93 *
94 * @note This function implements the same behaviour as std::stoul. The latter
95 * is missing in some Android toolchains.
96 *
97 * @param[in] str String to be converted to unsigned long.
98 * @param[in] pos If idx is not a null pointer, the function sets the value of pos to the position of the first character in str after the number.
99 * @param[in] base Numeric base used to interpret the string.
100 *
101 * @return Unsigned long representation of @p str.
102 */
103inline unsigned long stoul(const std::string &str, std::size_t *pos = 0, NumericBase base = NumericBase::BASE_10)
104{
105 assert(base == NumericBase::BASE_10 || base == NumericBase::BASE_16);
106 std::stringstream stream;
107 unsigned long value = 0;
108 if(base == NumericBase::BASE_16)
109 {
110 stream << std::hex;
111 }
112 stream << str;
113 stream >> value;
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100114
115 if(pos)
116 {
117 std::string s;
118 std::stringstream ss_p;
119
120 ss_p << value;
121 ss_p >> s;
122 *pos = s.length();
123 }
124
Pablo Tello65f99822018-05-24 11:40:15 +0100125 return value;
126}
127
Michalis Spyrou07781ac2017-08-31 15:11:41 +0100128#if(__ANDROID__ || BARE_METAL)
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100129/** Convert integer and float values to string.
130 *
131 * @note This function implements the same behaviour as std::to_string. The
132 * latter is missing in some Android toolchains.
133 *
134 * @param[in] value Value to be converted to string.
135 *
136 * @return String representation of @p value.
137 */
138template <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 +0100139inline std::string to_string(T && value)
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100140{
141 std::stringstream stream;
142 stream << std::forward<T>(value);
143 return stream.str();
144}
145
Michalis Spyroue6bcb5b2019-06-07 11:47:16 +0100146/** Rounds the floating-point argument arg to an integer value in floating-point format, using the current rounding mode.
147 *
148 * @note This function acts as a convenience wrapper around std::nearbyint. The
149 * latter is missing in some Android toolchains.
150 *
151 * @param[in] value Value to be rounded.
152 *
153 * @return The rounded value.
154 */
155template <typename T>
156inline T nearbyint(T value)
157{
Michalis Spyrou748a7c82019-10-07 13:00:44 +0100158 return static_cast<T>(::nearbyint(value));
Michalis Spyroue6bcb5b2019-06-07 11:47:16 +0100159}
160
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100161/** Convert string values to float.
162 *
163 * @note This function implements the same behaviour as std::stof. The latter
164 * is missing in some Android toolchains.
165 *
166 * @param[in] str String to be converted to float.
167 *
168 * @return Float representation of @p str.
169 */
170inline float stof(const std::string &str)
171{
172 std::stringstream stream(str);
173 float value = 0.f;
174 stream >> value;
175 return value;
176}
177
178/** Round floating-point value with half value rounding away from zero.
179 *
180 * @note This function implements the same behaviour as std::round except that it doesn't
181 * support Integral type. The latter is not in the namespace std in some Android toolchains.
182 *
183 * @param[in] value floating-point value to be rounded.
184 *
185 * @return Floating-point value of rounded @p value.
186 */
187template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
188inline T round(T value)
189{
190 return ::round(value);
191}
192
193/** Truncate floating-point value.
194 *
195 * @note This function implements the same behaviour as std::truncate except that it doesn't
196 * support Integral type. The latter is not in the namespace std in some Android toolchains.
197 *
198 * @param[in] value floating-point value to be truncated.
199 *
200 * @return Floating-point value of truncated @p value.
201 */
202template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
203inline T trunc(T value)
204{
205 return ::trunc(value);
206}
207
208/** Composes a floating point value with the magnitude of @p x and the sign of @p y.
209 *
210 * @note This function implements the same behaviour as std::copysign except that it doesn't
211 * support Integral type. The latter is not in the namespace std in some Android toolchains.
212 *
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100213 * @param[in] x value that contains the magnitude to be used in constructing the result.
214 * @param[in] y value that contains the sign to be used in construct in the result.
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100215 *
216 * @return Floating-point value with magnitude of @p x and sign of @p y.
217 */
218template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
219inline T copysign(T x, T y)
220{
221 return ::copysign(x, y);
222}
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100223
Georgios Pinitas1c29ffc2019-08-01 15:03:00 +0100224/** Computes (x*y) + z as if to infinite precision and rounded only once to fit the result type.
225 *
226 * @note This function implements the same behaviour as std::fma except that it doesn't
227 * support Integral type. The latter is not in the namespace std in some Android toolchains.
228 *
229 * @param[in] x floating-point value
230 * @param[in] y floating-point value
231 * @param[in] z floating-point value
232 *
233 * @return Result floating point value equal to (x*y) + z.c
234 */
Giorgio Arenad93e2632019-10-15 11:09:33 +0100235template < typename T, typename = typename std::enable_if < std::is_floating_point<T>::value
236#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
237 || std::is_same<T, float16_t>::value
238#endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
239 >::type >
Georgios Pinitas1c29ffc2019-08-01 15:03:00 +0100240inline T fma(T x, T y, T z)
241{
242 return ::fma(x, y, z);
243}
244
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100245/** Loads the data from the given location, converts them to character string equivalents
246 * and writes the result to a character string buffer.
247 *
248 * @param[in] s Pointer to a character string to write to
249 * @param[in] n Up to buf_size - 1 characters may be written, plus the null terminator
250 * @param[in] fmt Pointer to a null-terminated multibyte string specifying how to interpret the data.
251 * @param[in] args Arguments forwarded to snprintf.
252 *
253 * @return Number of characters that would have been written for a sufficiently large buffer
254 * if successful (not including the terminating null character), or a negative value if an error occurred.
255 */
256template <typename... Ts>
257inline int snprintf(char *s, size_t n, const char *fmt, Ts &&... args)
258{
259 return ::snprintf(s, n, fmt, std::forward<Ts>(args)...);
260}
Giorgio Arenad93e2632019-10-15 11:09:33 +0100261#else /* (__ANDROID__ || BARE_METAL) */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100262/** Convert integer and float values to string.
263 *
264 * @note This function acts as a convenience wrapper around std::to_string. The
265 * latter is missing in some Android toolchains.
266 *
267 * @param[in] value Value to be converted to string.
268 *
269 * @return String representation of @p value.
270 */
271template <typename T>
Moritz Pflanzer572ade72017-07-21 17:36:33 +0100272inline std::string to_string(T &&value)
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100273{
274 return ::std::to_string(std::forward<T>(value));
275}
276
Michalis Spyroue6bcb5b2019-06-07 11:47:16 +0100277/** Rounds the floating-point argument arg to an integer value in floating-point format, using the current rounding mode.
278 *
279 * @note This function acts as a convenience wrapper around std::nearbyint. The
280 * latter is missing in some Android toolchains.
281 *
282 * @param[in] value Value to be rounded.
283 *
284 * @return The rounded value.
285 */
286template <typename T>
287inline T nearbyint(T value)
288{
Michalis Spyrou748a7c82019-10-07 13:00:44 +0100289 return static_cast<T>(std::nearbyint(value));
Michalis Spyroue6bcb5b2019-06-07 11:47:16 +0100290}
291
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100292/** Convert string values to float.
293 *
294 * @note This function acts as a convenience wrapper around std::stof. The
295 * latter is missing in some Android toolchains.
296 *
297 * @param[in] args Arguments forwarded to std::stof.
298 *
299 * @return Float representation of input string.
300 */
301template <typename... Ts>
302int stof(Ts &&... args)
303{
304 return ::std::stof(std::forward<Ts>(args)...);
305}
306
307/** Round floating-point value with half value rounding away from zero.
308 *
309 * @note This function implements the same behaviour as std::round except that it doesn't
310 * support Integral type. The latter is not in the namespace std in some Android toolchains.
311 *
312 * @param[in] value floating-point value to be rounded.
313 *
314 * @return Floating-point value of rounded @p value.
315 */
316template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
317inline T round(T value)
318{
Pablo Tello826c7692018-01-16 11:41:12 +0000319 //Workaround Valgrind's mismatches: when running from Valgrind the call to std::round(-4.500000) == -4.000000 instead of 5.00000
320 return (value < 0.f) ? static_cast<int>(value - 0.5f) : static_cast<int>(value + 0.5f);
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100321}
322
323/** Truncate floating-point value.
324 *
325 * @note This function implements the same behaviour as std::truncate except that it doesn't
326 * support Integral type. The latter is not in the namespace std in some Android toolchains.
327 *
328 * @param[in] value floating-point value to be truncated.
329 *
330 * @return Floating-point value of truncated @p value.
331 */
332template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
333inline T trunc(T value)
334{
335 return std::trunc(value);
336}
337
338/** Composes a floating point value with the magnitude of @p x and the sign of @p y.
339 *
340 * @note This function implements the same behaviour as std::copysign except that it doesn't
341 * support Integral type. The latter is not in the namespace std in some Android toolchains.
342 *
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100343 * @param[in] x value that contains the magnitude to be used in constructing the result.
344 * @param[in] y value that contains the sign to be used in construct in the result.
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100345 *
346 * @return Floating-point value with magnitude of @p x and sign of @p y.
347 */
348template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
349inline T copysign(T x, T y)
350{
351 return std::copysign(x, y);
352}
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100353
Georgios Pinitas1c29ffc2019-08-01 15:03:00 +0100354/** Computes (x*y) + z as if to infinite precision and rounded only once to fit the result type.
355 *
356 * @note This function implements the same behaviour as std::fma except that it doesn't
357 * support Integral type. The latter is not in the namespace std in some Android toolchains.
358 *
359 * @param[in] x floating-point value
360 * @param[in] y floating-point value
361 * @param[in] z floating-point value
362 *
363 * @return Result floating point value equal to (x*y) + z.
364 */
Giorgio Arenad93e2632019-10-15 11:09:33 +0100365template < typename T, typename = typename std::enable_if < std::is_floating_point<T>::value
366#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
367 || std::is_same<T, float16_t>::value
368#endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
369 >::type >
Georgios Pinitas1c29ffc2019-08-01 15:03:00 +0100370inline T fma(T x, T y, T z)
371{
372 return std::fma(x, y, z);
373}
374
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100375/** Loads the data from the given location, converts them to character string equivalents
376 * and writes the result to a character string buffer.
377 *
378 * @param[in] s Pointer to a character string to write to
379 * @param[in] n Up to buf_size - 1 characters may be written, plus the null terminator
380 * @param[in] fmt Pointer to a null-terminated multibyte string specifying how to interpret the data.
381 * @param[in] args Arguments forwarded to std::snprintf.
382 *
383 * @return Number of characters that would have been written for a sufficiently large buffer
384 * if successful (not including the terminating null character), or a negative value if an error occurred.
385 */
386template <typename... Ts>
387inline int snprintf(char *s, std::size_t n, const char *fmt, Ts &&... args)
388{
389 return std::snprintf(s, n, fmt, std::forward<Ts>(args)...);
390}
Michalis Spyrou07781ac2017-08-31 15:11:41 +0100391#endif /* (__ANDROID__ || BARE_METAL) */
Moritz Pflanzer572ade72017-07-21 17:36:33 +0100392
393inline std::string to_string(bool value)
394{
395 std::stringstream str;
396 str << std::boolalpha << value;
397 return str.str();
398}
Moritz Pflanzerbeabe3b2017-08-31 14:56:32 +0100399
400// std::align is missing in GCC 4.9
401// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57350
402inline void *align(std::size_t alignment, std::size_t size, void *&ptr, std::size_t &space)
403{
404 std::uintptr_t pn = reinterpret_cast<std::uintptr_t>(ptr);
405 std::uintptr_t aligned = (pn + alignment - 1) & -alignment;
406 std::size_t padding = aligned - pn;
407 if(space < size + padding)
408 {
409 return nullptr;
410 }
411
412 space -= padding;
413
414 return ptr = reinterpret_cast<void *>(aligned);
415}
Anthony Barbier3a6163e2018-08-10 17:36:36 +0100416// std::numeric_limits<T>::lowest
417template <typename T>
418inline T lowest()
419{
420 return std::numeric_limits<T>::lowest();
421}
422
423#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
424template <>
425inline __fp16 lowest<__fp16>()
426{
427 return std::numeric_limits<half_float::half>::lowest();
428}
429#endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
Ioan-Cristian Szabo33fd07b2017-10-26 15:42:24 +0100430
431// std::isfinite
432template <typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
433inline bool isfinite(T value)
434{
435 return std::isfinite(value);
436}
437
438inline bool isfinite(half_float::half value)
439{
440 return half_float::isfinite(value);
441}
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100442} // namespace cpp11
443
444namespace cpp14
445{
Georgios Pinitas84b51ad2017-11-07 13:24:57 +0000446/** make_unique is missing in CPP11. Re-implement it according to the standard proposal. */
Alex Gildayc357c472018-03-21 13:54:09 +0000447
448/**<Template for single object */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100449template <class T>
450struct _Unique_if
451{
Alex Gildayc357c472018-03-21 13:54:09 +0000452 typedef std::unique_ptr<T> _Single_object; /**< Single object type */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100453};
454
Alex Gildayc357c472018-03-21 13:54:09 +0000455/** Template for array */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100456template <class T>
457struct _Unique_if<T[]>
458{
Alex Gildayc357c472018-03-21 13:54:09 +0000459 typedef std::unique_ptr<T[]> _Unknown_bound; /**< Array type */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100460};
461
Alex Gildayc357c472018-03-21 13:54:09 +0000462/** Template for array with known bounds (to throw an error).
463 *
464 * @note this is intended to never be hit.
465 */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100466template <class T, size_t N>
467struct _Unique_if<T[N]>
468{
Alex Gildayc357c472018-03-21 13:54:09 +0000469 typedef void _Known_bound; /**< Should never be used */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100470};
471
Alex Gildayc357c472018-03-21 13:54:09 +0000472/** Construct a single object and return a unique pointer to it.
473 *
474 * @param[in] args Constructor arguments.
475 *
476 * @return a unique pointer to the new object.
477 */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100478template <class T, class... Args>
479typename _Unique_if<T>::_Single_object
480make_unique(Args &&... args)
481{
482 return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
483}
484
Alex Gildayc357c472018-03-21 13:54:09 +0000485/** Construct an array of objects and return a unique pointer to it.
486 *
487 * @param[in] n Array size
488 *
489 * @return a unique pointer to the new array.
490 */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100491template <class T>
492typename _Unique_if<T>::_Unknown_bound
493make_unique(size_t n)
494{
495 typedef typename std::remove_extent<T>::type U;
496 return std::unique_ptr<T>(new U[n]());
497}
498
Alex Gildayc357c472018-03-21 13:54:09 +0000499/** It is invalid to attempt to make_unique an array with known bounds. */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100500template <class T, class... Args>
501typename _Unique_if<T>::_Known_bound
502make_unique(Args &&...) = delete;
503} // namespace cpp14
504} // namespace support
505} // namespace arm_compute
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100506#endif /* ARM_COMPUTE_TEST_TOOLCHAINSUPPORT */