blob: 8bf7f988c2c44b70464d6e62ef278175a71053b1 [file] [log] [blame]
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +01001/*
Michele Di Giorgiod9eaf612020-07-08 11:12:57 +01002 * Copyright (c) 2017-2020 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 */
Matthew Bentham758b5ba2020-03-05 23:37:48 +000024#ifndef ARM_COMPUTE_SUPPORT_TOOLCHAINSUPPORT
25#define ARM_COMPUTE_SUPPORT_TOOLCHAINSUPPORT
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010026
Pablo Tello65f99822018-05-24 11:40:15 +010027#include <cassert>
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010028#include <cmath>
29#include <cstddef>
30#include <limits>
31#include <memory>
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010032#include <sstream>
33#include <string>
34#include <type_traits>
35
Giorgio Arenad93e2632019-10-15 11:09:33 +010036#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
37#include <arm_neon.h>
38#endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
39
Georgios Pinitase8291ac2020-02-26 09:58:13 +000040#include "support/Bfloat16.h"
Ioan-Cristian Szabo33fd07b2017-10-26 15:42:24 +010041#include "support/Half.h"
42
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010043namespace arm_compute
44{
45namespace support
46{
47namespace cpp11
48{
Michalis Spyrou07781ac2017-08-31 15:11:41 +010049#if(__ANDROID__ || BARE_METAL)
Michalis Spyroue6bcb5b2019-06-07 11:47:16 +010050template <typename T>
51inline T nearbyint(T value)
52{
Michalis Spyrou748a7c82019-10-07 13:00:44 +010053 return static_cast<T>(::nearbyint(value));
Michalis Spyroue6bcb5b2019-06-07 11:47:16 +010054}
55
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010056/** Round floating-point value with half value rounding away from zero.
57 *
58 * @note This function implements the same behaviour as std::round except that it doesn't
59 * support Integral type. The latter is not in the namespace std in some Android toolchains.
60 *
61 * @param[in] value floating-point value to be rounded.
62 *
63 * @return Floating-point value of rounded @p value.
64 */
65template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
66inline T round(T value)
67{
68 return ::round(value);
69}
70
71/** Truncate floating-point value.
72 *
73 * @note This function implements the same behaviour as std::truncate except that it doesn't
74 * support Integral type. The latter is not in the namespace std in some Android toolchains.
75 *
76 * @param[in] value floating-point value to be truncated.
77 *
78 * @return Floating-point value of truncated @p value.
79 */
80template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
81inline T trunc(T value)
82{
83 return ::trunc(value);
84}
85
86/** Composes a floating point value with the magnitude of @p x and the sign of @p y.
87 *
88 * @note This function implements the same behaviour as std::copysign except that it doesn't
89 * support Integral type. The latter is not in the namespace std in some Android toolchains.
90 *
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +010091 * @param[in] x value that contains the magnitude to be used in constructing the result.
92 * @param[in] y value that contains the sign to be used in construct in the result.
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010093 *
94 * @return Floating-point value with magnitude of @p x and sign of @p y.
95 */
96template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
97inline T copysign(T x, T y)
98{
99 return ::copysign(x, y);
100}
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100101
Georgios Pinitas1c29ffc2019-08-01 15:03:00 +0100102/** Computes (x*y) + z as if to infinite precision and rounded only once to fit the result type.
103 *
104 * @note This function implements the same behaviour as std::fma except that it doesn't
105 * support Integral type. The latter is not in the namespace std in some Android toolchains.
106 *
107 * @param[in] x floating-point value
108 * @param[in] y floating-point value
109 * @param[in] z floating-point value
110 *
111 * @return Result floating point value equal to (x*y) + z.c
112 */
Giorgio Arenad93e2632019-10-15 11:09:33 +0100113template < typename T, typename = typename std::enable_if < std::is_floating_point<T>::value
114#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
115 || std::is_same<T, float16_t>::value
116#endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
117 >::type >
Georgios Pinitas1c29ffc2019-08-01 15:03:00 +0100118inline T fma(T x, T y, T z)
119{
120 return ::fma(x, y, z);
121}
122
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100123/** Loads the data from the given location, converts them to character string equivalents
124 * and writes the result to a character string buffer.
125 *
126 * @param[in] s Pointer to a character string to write to
127 * @param[in] n Up to buf_size - 1 characters may be written, plus the null terminator
128 * @param[in] fmt Pointer to a null-terminated multibyte string specifying how to interpret the data.
129 * @param[in] args Arguments forwarded to snprintf.
130 *
131 * @return Number of characters that would have been written for a sufficiently large buffer
132 * if successful (not including the terminating null character), or a negative value if an error occurred.
133 */
134template <typename... Ts>
135inline int snprintf(char *s, size_t n, const char *fmt, Ts &&... args)
136{
137 return ::snprintf(s, n, fmt, std::forward<Ts>(args)...);
138}
Giorgio Arenad93e2632019-10-15 11:09:33 +0100139#else /* (__ANDROID__ || BARE_METAL) */
Michalis Spyroue6bcb5b2019-06-07 11:47:16 +0100140/** Rounds the floating-point argument arg to an integer value in floating-point format, using the current rounding mode.
141 *
142 * @note This function acts as a convenience wrapper around std::nearbyint. The
143 * latter is missing in some Android toolchains.
144 *
145 * @param[in] value Value to be rounded.
146 *
147 * @return The rounded value.
148 */
149template <typename T>
150inline T nearbyint(T value)
151{
Michalis Spyrou748a7c82019-10-07 13:00:44 +0100152 return static_cast<T>(std::nearbyint(value));
Michalis Spyroue6bcb5b2019-06-07 11:47:16 +0100153}
154
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100155/** Round floating-point value with half value rounding away from zero.
156 *
157 * @note This function implements the same behaviour as std::round except that it doesn't
158 * support Integral type. The latter is not in the namespace std in some Android toolchains.
159 *
160 * @param[in] value floating-point value to be rounded.
161 *
162 * @return Floating-point value of rounded @p value.
163 */
164template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
165inline T round(T value)
166{
Pablo Tello826c7692018-01-16 11:41:12 +0000167 //Workaround Valgrind's mismatches: when running from Valgrind the call to std::round(-4.500000) == -4.000000 instead of 5.00000
168 return (value < 0.f) ? static_cast<int>(value - 0.5f) : static_cast<int>(value + 0.5f);
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100169}
170
171/** Truncate floating-point value.
172 *
173 * @note This function implements the same behaviour as std::truncate except that it doesn't
174 * support Integral type. The latter is not in the namespace std in some Android toolchains.
175 *
176 * @param[in] value floating-point value to be truncated.
177 *
178 * @return Floating-point value of truncated @p value.
179 */
180template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
181inline T trunc(T value)
182{
183 return std::trunc(value);
184}
185
186/** Composes a floating point value with the magnitude of @p x and the sign of @p y.
187 *
188 * @note This function implements the same behaviour as std::copysign except that it doesn't
189 * support Integral type. The latter is not in the namespace std in some Android toolchains.
190 *
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100191 * @param[in] x value that contains the magnitude to be used in constructing the result.
192 * @param[in] y value that contains the sign to be used in construct in the result.
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100193 *
194 * @return Floating-point value with magnitude of @p x and sign of @p y.
195 */
196template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
197inline T copysign(T x, T y)
198{
199 return std::copysign(x, y);
200}
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100201
Georgios Pinitas1c29ffc2019-08-01 15:03:00 +0100202/** Computes (x*y) + z as if to infinite precision and rounded only once to fit the result type.
203 *
204 * @note This function implements the same behaviour as std::fma except that it doesn't
205 * support Integral type. The latter is not in the namespace std in some Android toolchains.
206 *
207 * @param[in] x floating-point value
208 * @param[in] y floating-point value
209 * @param[in] z floating-point value
210 *
211 * @return Result floating point value equal to (x*y) + z.
212 */
Giorgio Arenad93e2632019-10-15 11:09:33 +0100213template < typename T, typename = typename std::enable_if < std::is_floating_point<T>::value
214#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
215 || std::is_same<T, float16_t>::value
216#endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
217 >::type >
Georgios Pinitas1c29ffc2019-08-01 15:03:00 +0100218inline T fma(T x, T y, T z)
219{
220 return std::fma(x, y, z);
221}
222
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100223/** Loads the data from the given location, converts them to character string equivalents
224 * and writes the result to a character string buffer.
225 *
226 * @param[in] s Pointer to a character string to write to
227 * @param[in] n Up to buf_size - 1 characters may be written, plus the null terminator
228 * @param[in] fmt Pointer to a null-terminated multibyte string specifying how to interpret the data.
229 * @param[in] args Arguments forwarded to std::snprintf.
230 *
231 * @return Number of characters that would have been written for a sufficiently large buffer
232 * if successful (not including the terminating null character), or a negative value if an error occurred.
233 */
234template <typename... Ts>
235inline int snprintf(char *s, std::size_t n, const char *fmt, Ts &&... args)
236{
237 return std::snprintf(s, n, fmt, std::forward<Ts>(args)...);
238}
Michalis Spyrou07781ac2017-08-31 15:11:41 +0100239#endif /* (__ANDROID__ || BARE_METAL) */
Moritz Pflanzer572ade72017-07-21 17:36:33 +0100240
Anthony Barbier3a6163e2018-08-10 17:36:36 +0100241// std::numeric_limits<T>::lowest
242template <typename T>
243inline T lowest()
244{
245 return std::numeric_limits<T>::lowest();
246}
247
248#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
249template <>
250inline __fp16 lowest<__fp16>()
251{
252 return std::numeric_limits<half_float::half>::lowest();
253}
254#endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
Ioan-Cristian Szabo33fd07b2017-10-26 15:42:24 +0100255
Georgios Pinitase8291ac2020-02-26 09:58:13 +0000256template <>
257inline bfloat16 lowest<bfloat16>()
258{
259 return bfloat16::lowest();
260}
261
Ioan-Cristian Szabo33fd07b2017-10-26 15:42:24 +0100262// std::isfinite
263template <typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
264inline bool isfinite(T value)
265{
266 return std::isfinite(value);
267}
268
269inline bool isfinite(half_float::half value)
270{
271 return half_float::isfinite(value);
272}
Georgios Pinitase8291ac2020-02-26 09:58:13 +0000273
274inline bool isfinite(bfloat16 value)
275{
276 return std::isfinite(float(value));
277}
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100278} // namespace cpp11
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100279} // namespace support
280} // namespace arm_compute
Matthew Bentham758b5ba2020-03-05 23:37:48 +0000281#endif /* ARM_COMPUTE_SUPPORT_TOOLCHAINSUPPORT */