Compute Library
 20.02.1
ToolchainSupport.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017-2019 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 <cassert>
29 #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 
38 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
39 #include <arm_neon.h>
40 #endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
41 
42 #include "support/Half.h"
43 
44 namespace arm_compute
45 {
46 namespace support
47 {
48 namespace cpp11
49 {
50 enum 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  */
67 inline 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;
78 
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 
89  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  */
103 inline 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;
114 
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 
125  return value;
126 }
127 
128 #if(__ANDROID__ || BARE_METAL)
129 /** 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  */
139 inline std::string to_string(T && value)
140 {
141  std::stringstream stream;
142  stream << std::forward<T>(value);
143  return stream.str();
144 }
145 
146 /** 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  */
155 template <typename T>
156 inline T nearbyint(T value)
157 {
158  return static_cast<T>(::nearbyint(value));
159 }
160 
161 /** 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  */
170 inline 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  */
187 template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
188 inline 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  */
202 template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
203 inline 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  *
213  * @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.
215  *
216  * @return Floating-point value with magnitude of @p x and sign of @p y.
217  */
218 template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
219 inline T copysign(T x, T y)
220 {
221  return ::copysign(x, y);
222 }
223 
224 /** 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  */
235 template < 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 >
240 inline T fma(T x, T y, T z)
241 {
242  return ::fma(x, y, z);
243 }
244 
245 /** 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  */
256 template <typename... Ts>
257 inline int snprintf(char *s, size_t n, const char *fmt, Ts &&... args)
258 {
259  return ::snprintf(s, n, fmt, std::forward<Ts>(args)...);
260 }
261 #else /* (__ANDROID__ || BARE_METAL) */
262 /** 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  */
271 template <typename T>
272 inline std::string to_string(T &&value)
273 {
274  return ::std::to_string(std::forward<T>(value));
275 }
276 
277 /** 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  */
286 template <typename T>
287 inline T nearbyint(T value)
288 {
289  return static_cast<T>(std::nearbyint(value));
290 }
291 
292 /** 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  */
301 template <typename... Ts>
302 int 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  */
316 template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
317 inline T round(T value)
318 {
319  //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);
321 }
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  */
332 template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
333 inline 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  *
343  * @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.
345  *
346  * @return Floating-point value with magnitude of @p x and sign of @p y.
347  */
348 template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
349 inline T copysign(T x, T y)
350 {
351  return std::copysign(x, y);
352 }
353 
354 /** 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  */
365 template < 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 >
370 inline T fma(T x, T y, T z)
371 {
372  return std::fma(x, y, z);
373 }
374 
375 /** 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  */
386 template <typename... Ts>
387 inline 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 }
391 #endif /* (__ANDROID__ || BARE_METAL) */
392 
393 inline std::string to_string(bool value)
394 {
395  std::stringstream str;
396  str << std::boolalpha << value;
397  return str.str();
398 }
399 
400 // std::align is missing in GCC 4.9
401 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57350
402 inline 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 }
416 // std::numeric_limits<T>::lowest
417 template <typename T>
418 inline T lowest()
419 {
421 }
422 
423 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
424 template <>
425 inline __fp16 lowest<__fp16>()
426 {
428 }
429 #endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
430 
431 // std::isfinite
432 template <typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
433 inline bool isfinite(T value)
434 {
435  return std::isfinite(value);
436 }
437 
438 inline bool isfinite(half_float::half value)
439 {
440  return half_float::isfinite(value);
441 }
442 } // namespace cpp11
443 
444 namespace cpp14
445 {
446 /** make_unique is missing in CPP11. Re-implement it according to the standard proposal. */
447 
448 /**<Template for single object */
449 template <class T>
451 {
452  typedef std::unique_ptr<T> _Single_object; /**< Single object type */
453 };
454 
455 /** Template for array */
456 template <class T>
457 struct _Unique_if<T[]>
458 {
459  typedef std::unique_ptr<T[]> _Unknown_bound; /**< Array type */
460 };
461 
462 /** Template for array with known bounds (to throw an error).
463  *
464  * @note this is intended to never be hit.
465  */
466 template <class T, size_t N>
467 struct _Unique_if<T[N]>
468 {
469  typedef void _Known_bound; /**< Should never be used */
470 };
471 
472 /** 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  */
478 template <class T, class... Args>
480 make_unique(Args &&... args)
481 {
482  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
483 }
484 
485 /** 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  */
491 template <class T>
492 typename _Unique_if<T>::_Unknown_bound
493 make_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 
499 /** It is invalid to attempt to make_unique an array with known bounds. */
500 template <class T, class... Args>
501 typename _Unique_if<T>::_Known_bound
502 make_unique(Args &&...) = delete;
503 } // namespace cpp14
504 } // namespace support
505 } // namespace arm_compute
506 #endif /* ARM_COMPUTE_TEST_TOOLCHAINSUPPORT */
unsigned long stoul(const std::string &str, std::size_t *pos=0, NumericBase base=NumericBase::BASE_10)
Convert string values to unsigned long.
std::string to_string(bool value)
T trunc(T value)
Truncate floating-point value.
T copysign(T x, T y)
Composes a floating point value with the magnitude of x and the sign of y.
T nearbyint(T value)
Rounds the floating-point argument arg to an integer value in floating-point format,...
std::string to_string(T &&value)
Convert integer and float values to string.
half_float::half half
16-bit floating point type
Definition: Types.h:45
make_unique is missing in CPP11.
Copyright (c) 2017-2020 ARM Limited.
std::unique_ptr< T > _Single_object
Single object type.
_Unique_if< T >::_Single_object make_unique(Args &&... args)
Construct a single object and return a unique pointer to it.
void * align(std::size_t alignment, std::size_t size, void *&ptr, std::size_t &space)
int stoi(const std::string &str, std::size_t *pos=0, NumericBase base=NumericBase::BASE_10)
Convert string values to integer.
T fma(T x, T y, T z)
Computes (x*y) + z as if to infinite precision and rounded only once to fit the result type.
T round(T value)
Round floating-point value with half value rounding away from zero.
int stof(Ts &&... args)
Convert string values to float.
std::unique_ptr< T[]> _Unknown_bound
Array type.
bool isfinite(half_float::half value)
int snprintf(char *s, std::size_t n, const char *fmt, Ts &&... args)
Loads the data from the given location, converts them to character string equivalents and writes the ...