blob: accbb643c206916ef4889bde9a33c57f9af9b8e4 [file] [log] [blame]
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +01001/*
Matthew Bentham7d9a78e2023-05-31 13:18:33 +00002 * Copyright (c) 2017-2023 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 */
Gunes Bayirdda691c2023-12-22 10:51:36 +000024#ifndef ACL_SUPPORT_TOOLCHAINSUPPORT_H
25#define ACL_SUPPORT_TOOLCHAINSUPPORT_H
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010026
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010027#include "support/Bfloat16.h"
28#include "support/Half.h"
29
Pablo Tello65f99822018-05-24 11:40:15 +010030#include <cassert>
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010031#include <cmath>
32#include <cstddef>
33#include <limits>
34#include <memory>
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010035#include <sstream>
36#include <string>
37#include <type_traits>
38
SiCongLi410e21e2020-12-11 15:07:53 +000039#ifndef M_PI
40#define M_PI (3.14159265358979323846)
41#endif // M_PI
42
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010043namespace arm_compute
44{
Matthew Bentham7d9a78e2023-05-31 13:18:33 +000045#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
46typedef __fp16 float16_t;
47#endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
48
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010049namespace support
50{
51namespace cpp11
52{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +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
Giorgio Arena433ea492021-05-26 15:32:50 +010075/** Round floating-point value with half value rounding away from zero and cast to long
76 *
77 * @note This function implements the same behaviour as std::lround 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 rounded.
81 *
82 * @return Floating-point value of rounded @p value casted to long
83 */
84template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
85inline long lround(T value)
86{
87 return ::lround(value);
88}
89
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +010090/** Truncate floating-point value.
91 *
92 * @note This function implements the same behaviour as std::truncate except that it doesn't
93 * support Integral type. The latter is not in the namespace std in some Android toolchains.
94 *
95 * @param[in] value floating-point value to be truncated.
96 *
97 * @return Floating-point value of truncated @p value.
98 */
99template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
100inline T trunc(T value)
101{
102 return ::trunc(value);
103}
104
105/** Composes a floating point value with the magnitude of @p x and the sign of @p y.
106 *
107 * @note This function implements the same behaviour as std::copysign except that it doesn't
108 * support Integral type. The latter is not in the namespace std in some Android toolchains.
109 *
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100110 * @param[in] x value that contains the magnitude to be used in constructing the result.
111 * @param[in] y value that contains the sign to be used in construct in the result.
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100112 *
113 * @return Floating-point value with magnitude of @p x and sign of @p y.
114 */
115template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
116inline T copysign(T x, T y)
117{
118 return ::copysign(x, y);
119}
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100120
Georgios Pinitas1c29ffc2019-08-01 15:03:00 +0100121/** Computes (x*y) + z as if to infinite precision and rounded only once to fit the result type.
122 *
123 * @note This function implements the same behaviour as std::fma except that it doesn't
124 * support Integral type. The latter is not in the namespace std in some Android toolchains.
125 *
126 * @param[in] x floating-point value
127 * @param[in] y floating-point value
128 * @param[in] z floating-point value
129 *
130 * @return Result floating point value equal to (x*y) + z.c
131 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100132template <typename T,
133 typename = typename std::enable_if<std::is_floating_point<T>::value
Giorgio Arenad93e2632019-10-15 11:09:33 +0100134#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100135 || std::is_same<T, float16_t>::value
Giorgio Arenad93e2632019-10-15 11:09:33 +0100136#endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100137 >::type>
Georgios Pinitas1c29ffc2019-08-01 15:03:00 +0100138inline T fma(T x, T y, T z)
139{
140 return ::fma(x, y, z);
141}
142
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100143/** Loads the data from the given location, converts them to character string equivalents
144 * and writes the result to a character string buffer.
145 *
146 * @param[in] s Pointer to a character string to write to
ramelg01b2eba7f2021-12-23 08:32:08 +0000147 * @param[in] n Up to buf_size - 1 characters may be written, plus the null ending character
148 * @param[in] fmt Pointer to a null-ended multibyte string specifying how to interpret the data.
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100149 * @param[in] args Arguments forwarded to snprintf.
150 *
151 * @return Number of characters that would have been written for a sufficiently large buffer
ramelg01b2eba7f2021-12-23 08:32:08 +0000152 * if successful (not including the ending null character), or a negative value if an error occurred.
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100153 */
154template <typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100155inline int snprintf(char *s, size_t n, const char *fmt, Ts &&...args)
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100156{
157 return ::snprintf(s, n, fmt, std::forward<Ts>(args)...);
158}
Giorgio Arenad93e2632019-10-15 11:09:33 +0100159#else /* (__ANDROID__ || BARE_METAL) */
Michalis Spyroue6bcb5b2019-06-07 11:47:16 +0100160/** Rounds the floating-point argument arg to an integer value in floating-point format, using the current rounding mode.
161 *
162 * @note This function acts as a convenience wrapper around std::nearbyint. The
163 * latter is missing in some Android toolchains.
164 *
165 * @param[in] value Value to be rounded.
166 *
167 * @return The rounded value.
168 */
169template <typename T>
170inline T nearbyint(T value)
171{
Michalis Spyrou748a7c82019-10-07 13:00:44 +0100172 return static_cast<T>(std::nearbyint(value));
Michalis Spyroue6bcb5b2019-06-07 11:47:16 +0100173}
174
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100175/** Round floating-point value with half value rounding away from zero.
176 *
177 * @note This function implements the same behaviour as std::round 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 rounded.
181 *
182 * @return Floating-point value of rounded @p value.
183 */
184template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
185inline T round(T value)
186{
Gunes Bayirdda691c2023-12-22 10:51:36 +0000187 return std::round(value);
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100188}
189
Giorgio Arena433ea492021-05-26 15:32:50 +0100190/** Round floating-point value with half value rounding away from zero and cast to long
191 *
192 * @note This function implements the same behaviour as std::lround except that it doesn't
193 * support Integral type. The latter is not in the namespace std in some Android toolchains.
194 *
195 * @param[in] value floating-point value to be rounded.
196 *
197 * @return Floating-point value of rounded @p value casted to long
198 */
199template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
200inline long lround(T value)
201{
202 return std::lround(value);
203}
204
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100205/** Truncate floating-point value.
206 *
207 * @note This function implements the same behaviour as std::truncate except that it doesn't
208 * support Integral type. The latter is not in the namespace std in some Android toolchains.
209 *
210 * @param[in] value floating-point value to be truncated.
211 *
212 * @return Floating-point value of truncated @p value.
213 */
214template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
215inline T trunc(T value)
216{
217 return std::trunc(value);
218}
219
220/** Composes a floating point value with the magnitude of @p x and the sign of @p y.
221 *
222 * @note This function implements the same behaviour as std::copysign except that it doesn't
223 * support Integral type. The latter is not in the namespace std in some Android toolchains.
224 *
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100225 * @param[in] x value that contains the magnitude to be used in constructing the result.
226 * @param[in] y value that contains the sign to be used in construct in the result.
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100227 *
228 * @return Floating-point value with magnitude of @p x and sign of @p y.
229 */
230template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
231inline T copysign(T x, T y)
232{
233 return std::copysign(x, y);
234}
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100235
Georgios Pinitas1c29ffc2019-08-01 15:03:00 +0100236/** Computes (x*y) + z as if to infinite precision and rounded only once to fit the result type.
237 *
238 * @note This function implements the same behaviour as std::fma except that it doesn't
239 * support Integral type. The latter is not in the namespace std in some Android toolchains.
240 *
241 * @param[in] x floating-point value
242 * @param[in] y floating-point value
243 * @param[in] z floating-point value
244 *
245 * @return Result floating point value equal to (x*y) + z.
246 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100247template <typename T,
248 typename = typename std::enable_if<std::is_floating_point<T>::value
Giorgio Arenad93e2632019-10-15 11:09:33 +0100249#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100250 || std::is_same<T, float16_t>::value
Giorgio Arenad93e2632019-10-15 11:09:33 +0100251#endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100252 >::type>
Georgios Pinitas1c29ffc2019-08-01 15:03:00 +0100253inline T fma(T x, T y, T z)
254{
255 return std::fma(x, y, z);
256}
257
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100258/** Loads the data from the given location, converts them to character string equivalents
259 * and writes the result to a character string buffer.
260 *
261 * @param[in] s Pointer to a character string to write to
ramelg01b2eba7f2021-12-23 08:32:08 +0000262 * @param[in] n Up to buf_size - 1 characters may be written, plus the null ending character
263 * @param[in] fmt Pointer to a null-ended multibyte string specifying how to interpret the data.
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100264 * @param[in] args Arguments forwarded to std::snprintf.
265 *
266 * @return Number of characters that would have been written for a sufficiently large buffer
ramelg01b2eba7f2021-12-23 08:32:08 +0000267 * if successful (not including the ending null character), or a negative value if an error occurred.
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100268 */
269template <typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100270inline int snprintf(char *s, std::size_t n, const char *fmt, Ts &&...args)
Georgios Pinitas7d3d1b92017-10-12 17:34:20 +0100271{
272 return std::snprintf(s, n, fmt, std::forward<Ts>(args)...);
273}
Michalis Spyrou07781ac2017-08-31 15:11:41 +0100274#endif /* (__ANDROID__ || BARE_METAL) */
Moritz Pflanzer572ade72017-07-21 17:36:33 +0100275
Anthony Barbier3a6163e2018-08-10 17:36:36 +0100276// std::numeric_limits<T>::lowest
277template <typename T>
278inline T lowest()
279{
280 return std::numeric_limits<T>::lowest();
281}
282
283#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
284template <>
285inline __fp16 lowest<__fp16>()
286{
287 return std::numeric_limits<half_float::half>::lowest();
288}
289#endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
Ioan-Cristian Szabo33fd07b2017-10-26 15:42:24 +0100290
Georgios Pinitase8291ac2020-02-26 09:58:13 +0000291template <>
292inline bfloat16 lowest<bfloat16>()
293{
294 return bfloat16::lowest();
295}
296
Ioan-Cristian Szabo33fd07b2017-10-26 15:42:24 +0100297// std::isfinite
298template <typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
299inline bool isfinite(T value)
300{
Pablo Tello29cab362022-03-10 17:05:34 +0000301 return std::isfinite(static_cast<double>(value));
Ioan-Cristian Szabo33fd07b2017-10-26 15:42:24 +0100302}
303
304inline bool isfinite(half_float::half value)
305{
306 return half_float::isfinite(value);
307}
Georgios Pinitase8291ac2020-02-26 09:58:13 +0000308
309inline bool isfinite(bfloat16 value)
310{
311 return std::isfinite(float(value));
312}
SiCongLib99e54e2022-01-05 12:18:03 +0000313
314// std::signbit
315template <typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
316inline bool signbit(T value)
317{
Pablo Tello29cab362022-03-10 17:05:34 +0000318 return std::signbit(static_cast<double>(value));
SiCongLib99e54e2022-01-05 12:18:03 +0000319}
320
321inline bool signbit(half_float::half value)
322{
323 return half_float::signbit(value);
324}
325
326inline bool signbit(bfloat16 value)
327{
328 return std::signbit(float(value));
329}
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100330} // namespace cpp11
Moritz Pflanzerd0ae8b82017-06-29 14:51:57 +0100331} // namespace support
332} // namespace arm_compute
Gunes Bayirdda691c2023-12-22 10:51:36 +0000333#endif // ACL_SUPPORT_TOOLCHAINSUPPORT_H