blob: cb156f39c75903d72267ea55f3984f1cc447c495 [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 */
72inline int stoi(const std::string &str)
73{
74 std::stringstream stream(str);
75 int value = 0;
76 stream >> value;
77 return value;
78}
79
80/** Convert string values to unsigned long.
81 *
82 * @note This function implements the same behaviour as std::stoul. The latter
83 * is missing in some Android toolchains.
84 *
85 * @param[in] str String to be converted to unsigned long.
86 *
87 * @return Unsigned long representation of @p str.
88 */
89inline unsigned long stoul(const std::string &str)
90{
91 std::stringstream stream(str);
92 unsigned long value = 0;
93 stream >> value;
94 return value;
95}
96
97/** Convert string values to float.
98 *
99 * @note This function implements the same behaviour as std::stof. The latter
100 * is missing in some Android toolchains.
101 *
102 * @param[in] str String to be converted to float.
103 *
104 * @return Float representation of @p str.
105 */
106inline float stof(const std::string &str)
107{
108 std::stringstream stream(str);
109 float value = 0.f;
110 stream >> value;
111 return value;
112}
113
114/** Round floating-point value with half value rounding away from zero.
115 *
116 * @note This function implements the same behaviour as std::round except that it doesn't
117 * support Integral type. The latter is not in the namespace std in some Android toolchains.
118 *
119 * @param[in] value floating-point value to be rounded.
120 *
121 * @return Floating-point value of rounded @p value.
122 */
123template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
124inline T round(T value)
125{
126 return ::round(value);
127}
128
129/** Truncate floating-point value.
130 *
131 * @note This function implements the same behaviour as std::truncate except that it doesn't
132 * support Integral type. The latter is not in the namespace std in some Android toolchains.
133 *
134 * @param[in] value floating-point value to be truncated.
135 *
136 * @return Floating-point value of truncated @p value.
137 */
138template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
139inline T trunc(T value)
140{
141 return ::trunc(value);
142}
143
144/** Composes a floating point value with the magnitude of @p x and the sign of @p y.
145 *
146 * @note This function implements the same behaviour as std::copysign except that it doesn't
147 * support Integral type. The latter is not in the namespace std in some Android toolchains.
148 *
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100149 * @param[in] x value that contains the magnitude to be used in constructing the result.
150 * @param[in] y value that contains the sign to be used in construct in the result.
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100151 *
152 * @return Floating-point value with magnitude of @p x and sign of @p y.
153 */
154template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
155inline T copysign(T x, T y)
156{
157 return ::copysign(x, y);
158}
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100159
160/** Loads the data from the given location, converts them to character string equivalents
161 * and writes the result to a character string buffer.
162 *
163 * @param[in] s Pointer to a character string to write to
164 * @param[in] n Up to buf_size - 1 characters may be written, plus the null terminator
165 * @param[in] fmt Pointer to a null-terminated multibyte string specifying how to interpret the data.
166 * @param[in] args Arguments forwarded to snprintf.
167 *
168 * @return Number of characters that would have been written for a sufficiently large buffer
169 * if successful (not including the terminating null character), or a negative value if an error occurred.
170 */
171template <typename... Ts>
172inline int snprintf(char *s, size_t n, const char *fmt, Ts &&... args)
173{
174 return ::snprintf(s, n, fmt, std::forward<Ts>(args)...);
175}
Michalis Spyrou07781ac2017-08-31 15:11:41 +0100176#else /* (__ANDROID__ || BARE_METAL) */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100177/** Convert integer and float values to string.
178 *
179 * @note This function acts as a convenience wrapper around std::to_string. The
180 * latter is missing in some Android toolchains.
181 *
182 * @param[in] value Value to be converted to string.
183 *
184 * @return String representation of @p value.
185 */
186template <typename T>
Moritz Pflanzer572ade72017-07-21 17:36:33 +0100187inline std::string to_string(T &&value)
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100188{
189 return ::std::to_string(std::forward<T>(value));
190}
191
192/** Convert string values to integer.
193 *
194 * @note This function acts as a convenience wrapper around std::stoi. The
195 * latter is missing in some Android toolchains.
196 *
197 * @param[in] args Arguments forwarded to std::stoi.
198 *
199 * @return Integer representation of input string.
200 */
201template <typename... Ts>
202int stoi(Ts &&... args)
203{
204 return ::std::stoi(std::forward<Ts>(args)...);
205}
206
207/** Convert string values to unsigned long.
208 *
209 * @note This function acts as a convenience wrapper around std::stoul. The
210 * latter is missing in some Android toolchains.
211 *
212 * @param[in] args Arguments forwarded to std::stoul.
213 *
214 * @return Unsigned long representation of input string.
215 */
216template <typename... Ts>
217int stoul(Ts &&... args)
218{
219 return ::std::stoul(std::forward<Ts>(args)...);
220}
221
222/** Convert string values to float.
223 *
224 * @note This function acts as a convenience wrapper around std::stof. The
225 * latter is missing in some Android toolchains.
226 *
227 * @param[in] args Arguments forwarded to std::stof.
228 *
229 * @return Float representation of input string.
230 */
231template <typename... Ts>
232int stof(Ts &&... args)
233{
234 return ::std::stof(std::forward<Ts>(args)...);
235}
236
237/** Round floating-point value with half value rounding away from zero.
238 *
239 * @note This function implements the same behaviour as std::round except that it doesn't
240 * support Integral type. The latter is not in the namespace std in some Android toolchains.
241 *
242 * @param[in] value floating-point value to be rounded.
243 *
244 * @return Floating-point value of rounded @p value.
245 */
246template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
247inline T round(T value)
248{
Pablo Tello826c7692018-01-16 11:41:12 +0000249 //Workaround Valgrind's mismatches: when running from Valgrind the call to std::round(-4.500000) == -4.000000 instead of 5.00000
250 return (value < 0.f) ? static_cast<int>(value - 0.5f) : static_cast<int>(value + 0.5f);
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100251}
252
253/** Truncate floating-point value.
254 *
255 * @note This function implements the same behaviour as std::truncate except that it doesn't
256 * support Integral type. The latter is not in the namespace std in some Android toolchains.
257 *
258 * @param[in] value floating-point value to be truncated.
259 *
260 * @return Floating-point value of truncated @p value.
261 */
262template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
263inline T trunc(T value)
264{
265 return std::trunc(value);
266}
267
268/** Composes a floating point value with the magnitude of @p x and the sign of @p y.
269 *
270 * @note This function implements the same behaviour as std::copysign except that it doesn't
271 * support Integral type. The latter is not in the namespace std in some Android toolchains.
272 *
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100273 * @param[in] x value that contains the magnitude to be used in constructing the result.
274 * @param[in] y value that contains the sign to be used in construct in the result.
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100275 *
276 * @return Floating-point value with magnitude of @p x and sign of @p y.
277 */
278template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
279inline T copysign(T x, T y)
280{
281 return std::copysign(x, y);
282}
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100283
284/** Loads the data from the given location, converts them to character string equivalents
285 * and writes the result to a character string buffer.
286 *
287 * @param[in] s Pointer to a character string to write to
288 * @param[in] n Up to buf_size - 1 characters may be written, plus the null terminator
289 * @param[in] fmt Pointer to a null-terminated multibyte string specifying how to interpret the data.
290 * @param[in] args Arguments forwarded to std::snprintf.
291 *
292 * @return Number of characters that would have been written for a sufficiently large buffer
293 * if successful (not including the terminating null character), or a negative value if an error occurred.
294 */
295template <typename... Ts>
296inline int snprintf(char *s, std::size_t n, const char *fmt, Ts &&... args)
297{
298 return std::snprintf(s, n, fmt, std::forward<Ts>(args)...);
299}
Michalis Spyrou07781ac2017-08-31 15:11:41 +0100300#endif /* (__ANDROID__ || BARE_METAL) */
Moritz Pflanzer572ade72017-07-21 17:36:33 +0100301
302inline std::string to_string(bool value)
303{
304 std::stringstream str;
305 str << std::boolalpha << value;
306 return str.str();
307}
Moritz Pflanzerbeabe3b2017-08-31 14:56:32 +0100308
309// std::align is missing in GCC 4.9
310// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57350
311inline void *align(std::size_t alignment, std::size_t size, void *&ptr, std::size_t &space)
312{
313 std::uintptr_t pn = reinterpret_cast<std::uintptr_t>(ptr);
314 std::uintptr_t aligned = (pn + alignment - 1) & -alignment;
315 std::size_t padding = aligned - pn;
316 if(space < size + padding)
317 {
318 return nullptr;
319 }
320
321 space -= padding;
322
323 return ptr = reinterpret_cast<void *>(aligned);
324}
Ioan-Cristian Szabo33fd07b2017-10-26 15:42:24 +0100325
326// std::isfinite
327template <typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
328inline bool isfinite(T value)
329{
330 return std::isfinite(value);
331}
332
333inline bool isfinite(half_float::half value)
334{
335 return half_float::isfinite(value);
336}
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100337} // namespace cpp11
338
339namespace cpp14
340{
Georgios Pinitas84b51ad2017-11-07 13:24:57 +0000341/** make_unique is missing in CPP11. Re-implement it according to the standard proposal. */
Alex Gildayc357c472018-03-21 13:54:09 +0000342
343/**<Template for single object */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100344template <class T>
345struct _Unique_if
346{
Alex Gildayc357c472018-03-21 13:54:09 +0000347 typedef std::unique_ptr<T> _Single_object; /**< Single object type */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100348};
349
Alex Gildayc357c472018-03-21 13:54:09 +0000350/** Template for array */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100351template <class T>
352struct _Unique_if<T[]>
353{
Alex Gildayc357c472018-03-21 13:54:09 +0000354 typedef std::unique_ptr<T[]> _Unknown_bound; /**< Array type */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100355};
356
Alex Gildayc357c472018-03-21 13:54:09 +0000357/** Template for array with known bounds (to throw an error).
358 *
359 * @note this is intended to never be hit.
360 */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100361template <class T, size_t N>
362struct _Unique_if<T[N]>
363{
Alex Gildayc357c472018-03-21 13:54:09 +0000364 typedef void _Known_bound; /**< Should never be used */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100365};
366
Alex Gildayc357c472018-03-21 13:54:09 +0000367/** Construct a single object and return a unique pointer to it.
368 *
369 * @param[in] args Constructor arguments.
370 *
371 * @return a unique pointer to the new object.
372 */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100373template <class T, class... Args>
374typename _Unique_if<T>::_Single_object
375make_unique(Args &&... args)
376{
377 return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
378}
379
Alex Gildayc357c472018-03-21 13:54:09 +0000380/** Construct an array of objects and return a unique pointer to it.
381 *
382 * @param[in] n Array size
383 *
384 * @return a unique pointer to the new array.
385 */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100386template <class T>
387typename _Unique_if<T>::_Unknown_bound
388make_unique(size_t n)
389{
390 typedef typename std::remove_extent<T>::type U;
391 return std::unique_ptr<T>(new U[n]());
392}
393
Alex Gildayc357c472018-03-21 13:54:09 +0000394/** It is invalid to attempt to make_unique an array with known bounds. */
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100395template <class T, class... Args>
396typename _Unique_if<T>::_Known_bound
397make_unique(Args &&...) = delete;
398} // namespace cpp14
399} // namespace support
400} // namespace arm_compute
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100401#endif /* ARM_COMPUTE_TEST_TOOLCHAINSUPPORT */