blob: e79084a6291f26d9569fe98c0283358b68d4b7e6 [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
SiCongLi410e21e2020-12-11 15:07:53 +000043#ifndef M_PI
44#define M_PI (3.14159265358979323846)
45#endif // M_PI
46
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010047namespace arm_compute
48{
49namespace support
50{
51namespace cpp11
52{
Michalis Spyrou07781ac2017-08-31 15:11:41 +010053#if(__ANDROID__ || BARE_METAL)
Michalis Spyroue6bcb5b2019-06-07 11:47:16 +010054template <typename T>
55inline T nearbyint(T value)
56{
Michalis Spyrou748a7c82019-10-07 13:00:44 +010057 return static_cast<T>(::nearbyint(value));
Michalis Spyroue6bcb5b2019-06-07 11:47:16 +010058}
59
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010060/** Round floating-point value with half value rounding away from zero.
61 *
62 * @note This function implements the same behaviour as std::round except that it doesn't
63 * support Integral type. The latter is not in the namespace std in some Android toolchains.
64 *
65 * @param[in] value floating-point value to be rounded.
66 *
67 * @return Floating-point value of rounded @p value.
68 */
69template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
70inline T round(T value)
71{
72 return ::round(value);
73}
74
75/** Truncate floating-point value.
76 *
77 * @note This function implements the same behaviour as std::truncate except that it doesn't
78 * support Integral type. The latter is not in the namespace std in some Android toolchains.
79 *
80 * @param[in] value floating-point value to be truncated.
81 *
82 * @return Floating-point value of truncated @p value.
83 */
84template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
85inline T trunc(T value)
86{
87 return ::trunc(value);
88}
89
90/** Composes a floating point value with the magnitude of @p x and the sign of @p y.
91 *
92 * @note This function implements the same behaviour as std::copysign except that it doesn't
93 * support Integral type. The latter is not in the namespace std in some Android toolchains.
94 *
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +010095 * @param[in] x value that contains the magnitude to be used in constructing the result.
96 * @param[in] y value that contains the sign to be used in construct in the result.
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010097 *
98 * @return Floating-point value with magnitude of @p x and sign of @p y.
99 */
100template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
101inline T copysign(T x, T y)
102{
103 return ::copysign(x, y);
104}
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100105
Georgios Pinitas1c29ffc2019-08-01 15:03:00 +0100106/** Computes (x*y) + z as if to infinite precision and rounded only once to fit the result type.
107 *
108 * @note This function implements the same behaviour as std::fma except that it doesn't
109 * support Integral type. The latter is not in the namespace std in some Android toolchains.
110 *
111 * @param[in] x floating-point value
112 * @param[in] y floating-point value
113 * @param[in] z floating-point value
114 *
115 * @return Result floating point value equal to (x*y) + z.c
116 */
Giorgio Arenad93e2632019-10-15 11:09:33 +0100117template < typename T, typename = typename std::enable_if < std::is_floating_point<T>::value
118#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
119 || std::is_same<T, float16_t>::value
120#endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
121 >::type >
Georgios Pinitas1c29ffc2019-08-01 15:03:00 +0100122inline T fma(T x, T y, T z)
123{
124 return ::fma(x, y, z);
125}
126
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100127/** Loads the data from the given location, converts them to character string equivalents
128 * and writes the result to a character string buffer.
129 *
130 * @param[in] s Pointer to a character string to write to
131 * @param[in] n Up to buf_size - 1 characters may be written, plus the null terminator
132 * @param[in] fmt Pointer to a null-terminated multibyte string specifying how to interpret the data.
133 * @param[in] args Arguments forwarded to snprintf.
134 *
135 * @return Number of characters that would have been written for a sufficiently large buffer
136 * if successful (not including the terminating null character), or a negative value if an error occurred.
137 */
138template <typename... Ts>
139inline int snprintf(char *s, size_t n, const char *fmt, Ts &&... args)
140{
141 return ::snprintf(s, n, fmt, std::forward<Ts>(args)...);
142}
Giorgio Arenad93e2632019-10-15 11:09:33 +0100143#else /* (__ANDROID__ || BARE_METAL) */
Michalis Spyroue6bcb5b2019-06-07 11:47:16 +0100144/** Rounds the floating-point argument arg to an integer value in floating-point format, using the current rounding mode.
145 *
146 * @note This function acts as a convenience wrapper around std::nearbyint. The
147 * latter is missing in some Android toolchains.
148 *
149 * @param[in] value Value to be rounded.
150 *
151 * @return The rounded value.
152 */
153template <typename T>
154inline T nearbyint(T value)
155{
Michalis Spyrou748a7c82019-10-07 13:00:44 +0100156 return static_cast<T>(std::nearbyint(value));
Michalis Spyroue6bcb5b2019-06-07 11:47:16 +0100157}
158
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100159/** Round floating-point value with half value rounding away from zero.
160 *
161 * @note This function implements the same behaviour as std::round except that it doesn't
162 * support Integral type. The latter is not in the namespace std in some Android toolchains.
163 *
164 * @param[in] value floating-point value to be rounded.
165 *
166 * @return Floating-point value of rounded @p value.
167 */
168template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
169inline T round(T value)
170{
Pablo Tello826c7692018-01-16 11:41:12 +0000171 //Workaround Valgrind's mismatches: when running from Valgrind the call to std::round(-4.500000) == -4.000000 instead of 5.00000
172 return (value < 0.f) ? static_cast<int>(value - 0.5f) : static_cast<int>(value + 0.5f);
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100173}
174
175/** Truncate floating-point value.
176 *
177 * @note This function implements the same behaviour as std::truncate except that it doesn't
178 * support Integral type. The latter is not in the namespace std in some Android toolchains.
179 *
180 * @param[in] value floating-point value to be truncated.
181 *
182 * @return Floating-point value of truncated @p value.
183 */
184template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
185inline T trunc(T value)
186{
187 return std::trunc(value);
188}
189
190/** Composes a floating point value with the magnitude of @p x and the sign of @p y.
191 *
192 * @note This function implements the same behaviour as std::copysign except that it doesn't
193 * support Integral type. The latter is not in the namespace std in some Android toolchains.
194 *
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100195 * @param[in] x value that contains the magnitude to be used in constructing the result.
196 * @param[in] y value that contains the sign to be used in construct in the result.
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100197 *
198 * @return Floating-point value with magnitude of @p x and sign of @p y.
199 */
200template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
201inline T copysign(T x, T y)
202{
203 return std::copysign(x, y);
204}
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100205
Georgios Pinitas1c29ffc2019-08-01 15:03:00 +0100206/** Computes (x*y) + z as if to infinite precision and rounded only once to fit the result type.
207 *
208 * @note This function implements the same behaviour as std::fma except that it doesn't
209 * support Integral type. The latter is not in the namespace std in some Android toolchains.
210 *
211 * @param[in] x floating-point value
212 * @param[in] y floating-point value
213 * @param[in] z floating-point value
214 *
215 * @return Result floating point value equal to (x*y) + z.
216 */
Giorgio Arenad93e2632019-10-15 11:09:33 +0100217template < typename T, typename = typename std::enable_if < std::is_floating_point<T>::value
218#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
219 || std::is_same<T, float16_t>::value
220#endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
221 >::type >
Georgios Pinitas1c29ffc2019-08-01 15:03:00 +0100222inline T fma(T x, T y, T z)
223{
224 return std::fma(x, y, z);
225}
226
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100227/** Loads the data from the given location, converts them to character string equivalents
228 * and writes the result to a character string buffer.
229 *
230 * @param[in] s Pointer to a character string to write to
231 * @param[in] n Up to buf_size - 1 characters may be written, plus the null terminator
232 * @param[in] fmt Pointer to a null-terminated multibyte string specifying how to interpret the data.
233 * @param[in] args Arguments forwarded to std::snprintf.
234 *
235 * @return Number of characters that would have been written for a sufficiently large buffer
236 * if successful (not including the terminating null character), or a negative value if an error occurred.
237 */
238template <typename... Ts>
239inline int snprintf(char *s, std::size_t n, const char *fmt, Ts &&... args)
240{
241 return std::snprintf(s, n, fmt, std::forward<Ts>(args)...);
242}
Michalis Spyrou07781ac2017-08-31 15:11:41 +0100243#endif /* (__ANDROID__ || BARE_METAL) */
Moritz Pflanzer572ade72017-07-21 17:36:33 +0100244
Anthony Barbier3a6163e2018-08-10 17:36:36 +0100245// std::numeric_limits<T>::lowest
246template <typename T>
247inline T lowest()
248{
249 return std::numeric_limits<T>::lowest();
250}
251
252#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
253template <>
254inline __fp16 lowest<__fp16>()
255{
256 return std::numeric_limits<half_float::half>::lowest();
257}
258#endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
Ioan-Cristian Szabo33fd07b2017-10-26 15:42:24 +0100259
Georgios Pinitase8291ac2020-02-26 09:58:13 +0000260template <>
261inline bfloat16 lowest<bfloat16>()
262{
263 return bfloat16::lowest();
264}
265
Ioan-Cristian Szabo33fd07b2017-10-26 15:42:24 +0100266// std::isfinite
267template <typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
268inline bool isfinite(T value)
269{
270 return std::isfinite(value);
271}
272
273inline bool isfinite(half_float::half value)
274{
275 return half_float::isfinite(value);
276}
Georgios Pinitase8291ac2020-02-26 09:58:13 +0000277
278inline bool isfinite(bfloat16 value)
279{
280 return std::isfinite(float(value));
281}
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100282} // namespace cpp11
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100283} // namespace support
284} // namespace arm_compute
Matthew Bentham758b5ba2020-03-05 23:37:48 +0000285#endif /* ARM_COMPUTE_SUPPORT_TOOLCHAINSUPPORT */