blob: 22f10d74ccdd5a184a6bc7a90a63117f2c96d05b [file] [log] [blame]
Georgios Pinitas8795ffb2017-12-01 16:13:40 +00001/*
Pablo Marquez Tello732c1b22023-03-29 11:42:30 +01002 * Copyright (c) 2017-2021, 2023 Arm Limited.
Georgios Pinitas8795ffb2017-12-01 16:13:40 +00003 *
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 */
Michalis Spyrouf4643372019-11-29 16:17:13 +000024#ifndef ARM_COMPUTE_MISC_UTILITY_H
25#define ARM_COMPUTE_MISC_UTILITY_H
Georgios Pinitas8795ffb2017-12-01 16:13:40 +000026
SiCongLi3b5981c2021-03-12 12:31:17 +000027#include "arm_compute/core/Error.h"
28
Michalis Spyrou40df1e92018-02-06 16:53:47 +000029#include <algorithm>
Georgios Pinitas8795ffb2017-12-01 16:13:40 +000030#include <array>
Pablo Marquez Tello732c1b22023-03-29 11:42:30 +010031#include <cstdint>
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +000032#include <limits>
Michalis Spyrou40df1e92018-02-06 16:53:47 +000033#include <numeric>
34#include <vector>
Georgios Pinitas8795ffb2017-12-01 16:13:40 +000035
36namespace arm_compute
37{
38namespace utility
39{
40/** @cond */
41template <std::size_t...>
42struct index_sequence
43{
44};
45
46template <std::size_t N, std::size_t... S>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010047struct index_sequence_generator : index_sequence_generator<N - 1, N - 1, S...>
Georgios Pinitas8795ffb2017-12-01 16:13:40 +000048{
49};
50
51template <std::size_t... S>
52struct index_sequence_generator<0u, S...> : index_sequence<S...>
53{
54 using type = index_sequence<S...>;
55};
56
57template <std::size_t N>
58using index_sequence_t = typename index_sequence_generator<N>::type;
Sang-Hoon Parkcecb0a72019-09-17 08:59:09 +010059
60template <typename T, std::size_t N, T val, T... vals>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010061struct generate_array : generate_array<T, N - 1, val, val, vals...>
Sang-Hoon Parkcecb0a72019-09-17 08:59:09 +010062{
63};
64
65template <typename T, T val, T... vals>
66struct generate_array<T, 0, val, vals...>
67{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010068 static constexpr std::array<T, sizeof...(vals)> value{vals...};
Sang-Hoon Parkcecb0a72019-09-17 08:59:09 +010069};
70
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010071template <typename T, T val, T... vals>
Sang-Hoon Parkcecb0a72019-09-17 08:59:09 +010072constexpr std::array<T, sizeof...(vals)> generate_array<T, 0, val, vals...>::value;
Georgios Pinitas8795ffb2017-12-01 16:13:40 +000073/** @endcond */
74
75namespace detail
76{
77template <std::size_t... S,
78 typename Iterator,
79 typename T = std::array<typename std::iterator_traits<Iterator>::value_type, sizeof...(S)>>
80T make_array(Iterator first, index_sequence<S...>)
81{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010082 return T{{first[S]...}};
Georgios Pinitas8795ffb2017-12-01 16:13:40 +000083}
84} // namespace detail
85
86template <std::size_t N, typename Iterator>
87std::array<typename std::iterator_traits<Iterator>::value_type, N> make_array(Iterator first, Iterator last)
88{
Michalis Spyrou6bff1952019-10-02 17:22:11 +010089 ARM_COMPUTE_UNUSED(last);
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010090 return detail::make_array(first, index_sequence_t<N>{});
Georgios Pinitas8795ffb2017-12-01 16:13:40 +000091}
Diego Lopez Recas490b3d82017-12-19 15:42:25 +000092
93/** Performs clamping among a lower and upper value.
94 *
95 * @param[in] n Value to clamp.
96 * @param[in] lower Lower threshold.
97 * @param[in] upper Upper threshold.
98 *
99 * @return Clamped value.
100 */
Vidhya Sudhan Loganathan5e96be72018-12-18 14:17:00 +0000101template <typename DataType, typename RangeType = DataType>
102inline DataType clamp(const DataType &n,
103 const DataType &lower = std::numeric_limits<RangeType>::lowest(),
104 const DataType &upper = std::numeric_limits<RangeType>::max())
Diego Lopez Recas490b3d82017-12-19 15:42:25 +0000105{
106 return std::max(lower, std::min(n, upper));
107}
108
109/** Base case of for_each. Does nothing. */
110template <typename F>
111inline void for_each(F &&)
112{
113}
114
115/** Call the function for each of the arguments
116 *
117 * @param[in] func Function to be called
118 * @param[in] arg Argument passed to the function
119 * @param[in] args Remaining arguments
120 */
121template <typename F, typename T, typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100122inline void for_each(F &&func, T &&arg, Ts &&...args)
Diego Lopez Recas490b3d82017-12-19 15:42:25 +0000123{
124 func(std::forward<T>(arg));
125 for_each(std::forward<F>(func), std::forward<Ts>(args)...);
126}
127
128/** Base case of foldl.
129 *
130 * @return value.
131 */
132template <typename F, typename T>
133inline T &&foldl(F &&, T &&value)
134{
135 return std::forward<T>(value);
136}
137
138/** Fold left.
139 *
140 * @param[in] func Function to be called
141 * @param[in] initial Initial value
142 * @param[in] value Argument passed to the function
143 * @param[in] values Remaining arguments
144 */
145template <typename F, typename T, typename U, typename... Us>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100146inline auto foldl(F &&func, T &&initial, U &&value, Us &&...values)
147 -> decltype(func(std::forward<T>(initial), std::forward<U>(value)))
Diego Lopez Recas490b3d82017-12-19 15:42:25 +0000148{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100149 return foldl(std::forward<F>(func), func(std::forward<T>(initial), std::forward<U>(value)),
150 std::forward<Us>(values)...);
Diego Lopez Recas490b3d82017-12-19 15:42:25 +0000151}
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +0000152
Michalis Spyrou40df1e92018-02-06 16:53:47 +0000153/** Perform an index sort of a given vector.
154 *
155 * @param[in] v Vector to sort
156 *
157 * @return Sorted index vector.
158 */
159template <typename T>
160std::vector<size_t> sort_indices(const std::vector<T> &v)
161{
162 std::vector<size_t> idx(v.size());
163 std::iota(idx.begin(), idx.end(), 0);
164
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100165 std::sort(idx.begin(), idx.end(), [&v](size_t i1, size_t i2) { return v[i1] < v[i2]; });
Michalis Spyrou40df1e92018-02-06 16:53:47 +0000166
167 return idx;
168}
Isabella Gottardi88d5b222018-04-06 12:24:55 +0100169
Georgios Pinitas17b12302018-06-18 18:13:51 +0100170/** Checks if a string contains a given suffix
171 *
172 * @param[in] str Input string
173 * @param[in] suffix Suffix to check for
174 *
175 * @return True if the string ends with the given suffix else false
176 */
177inline bool endswith(const std::string &str, const std::string &suffix)
Isabella Gottardi88d5b222018-04-06 12:24:55 +0100178{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100179 if (str.size() < suffix.size())
Isabella Gottardi88d5b222018-04-06 12:24:55 +0100180 {
181 return false;
182 }
Georgios Pinitas17b12302018-06-18 18:13:51 +0100183 return std::equal(suffix.rbegin(), suffix.rend(), str.rbegin());
Isabella Gottardi88d5b222018-04-06 12:24:55 +0100184}
185
Georgios Pinitas17b12302018-06-18 18:13:51 +0100186/** Checks if a pointer complies with a given alignment
187 *
188 * @param[in] ptr Pointer to check
189 * @param[in] alignment Alignment value
190 *
191 * @return True if the pointer is aligned else false
192 */
193inline bool check_aligned(void *ptr, const size_t alignment)
194{
195 return (reinterpret_cast<std::uintptr_t>(ptr) % alignment) == 0;
196}
Georgios Pinitas12be7ab2018-07-03 12:06:23 +0100197
198/** Convert string to lower case.
199 *
200 * @param[in] string To be converted string.
201 *
202 * @return Lower case string.
203 */
204inline std::string tolower(std::string string)
205{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100206 std::transform(string.begin(), string.end(), string.begin(), [](unsigned char c) { return std::tolower(c); });
Georgios Pinitas12be7ab2018-07-03 12:06:23 +0100207 return string;
208}
SiCongLi3b5981c2021-03-12 12:31:17 +0000209
210/** Get environment variable as a string
211 *
212 * @note Return empty string on bare-metal
213 *
214 * @param[in] env_name Name of the Environment variable to retrieve
215 *
216 * @return Environment variable content, or empty string if the variable is undefined or on bare-metal
217 */
218inline std::string getenv(const std::string &env_name)
219{
220#ifdef BARE_METAL
221 ARM_COMPUTE_UNUSED(env_name);
222 return std::string{};
223#else // BARE_METAL
224 const auto env_chr = std::getenv(env_name.c_str());
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100225 return env_chr == nullptr ? std::string{} : std::string{env_chr};
SiCongLi3b5981c2021-03-12 12:31:17 +0000226#endif // BARE_METAL
227}
Diego Lopez Recas490b3d82017-12-19 15:42:25 +0000228} // namespace utility
Georgios Pinitas8795ffb2017-12-01 16:13:40 +0000229} // namespace arm_compute
Michalis Spyrouf4643372019-11-29 16:17:13 +0000230#endif /* ARM_COMPUTE_MISC_UTILITY_H */