xref: /aosp_15_r20/external/ComputeLibrary/arm_compute/core/utils/misc/Utility.h (revision c217d954acce2dbc11938adb493fc0abd69584f3)
1 /*
2  * Copyright (c) 2017-2021 Arm Limited.
3  *
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_MISC_UTILITY_H
25 #define ARM_COMPUTE_MISC_UTILITY_H
26 
27 #include "arm_compute/core/Error.h"
28 
29 #include <algorithm>
30 #include <array>
31 #include <limits>
32 #include <numeric>
33 #include <vector>
34 
35 namespace arm_compute
36 {
37 namespace utility
38 {
39 /** @cond */
40 template <std::size_t...>
41 struct index_sequence
42 {
43 };
44 
45 template <std::size_t N, std::size_t... S>
46 struct index_sequence_generator : index_sequence_generator < N - 1, N - 1, S... >
47 {
48 };
49 
50 template <std::size_t... S>
51 struct index_sequence_generator<0u, S...> : index_sequence<S...>
52 {
53     using type = index_sequence<S...>;
54 };
55 
56 template <std::size_t N>
57 using index_sequence_t = typename index_sequence_generator<N>::type;
58 
59 template <typename T, std::size_t N, T val, T... vals>
60 struct generate_array : generate_array < T, N - 1, val, val, vals... >
61 {
62 };
63 
64 template <typename T, T val, T... vals>
65 struct generate_array<T, 0, val, vals...>
66 {
67     static constexpr std::array<T, sizeof...(vals)> value{ vals... };
68 };
69 
70 template <typename T, T                  val, T... vals>
71 constexpr std::array<T, sizeof...(vals)> generate_array<T, 0, val, vals...>::value;
72 /** @endcond */
73 
74 namespace detail
75 {
76 template <std::size_t... S,
77           typename Iterator,
78           typename T = std::array<typename std::iterator_traits<Iterator>::value_type, sizeof...(S)>>
79 T make_array(Iterator first, index_sequence<S...>)
80 {
81     return T{ { first[S]... } };
82 }
83 } // namespace detail
84 
85 template <std::size_t N, typename Iterator>
86 std::array<typename std::iterator_traits<Iterator>::value_type, N> make_array(Iterator first, Iterator last)
87 {
88     ARM_COMPUTE_UNUSED(last);
89     return detail::make_array(first, index_sequence_t<N> {});
90 }
91 
92 /** Performs clamping among a lower and upper value.
93  *
94  * @param[in] n     Value to clamp.
95  * @param[in] lower Lower threshold.
96  * @param[in] upper Upper threshold.
97  *
98  *  @return Clamped value.
99  */
100 template <typename DataType, typename RangeType = DataType>
101 inline DataType clamp(const DataType &n,
102                       const DataType &lower = std::numeric_limits<RangeType>::lowest(),
103                       const DataType &upper = std::numeric_limits<RangeType>::max())
104 {
105     return std::max(lower, std::min(n, upper));
106 }
107 
108 /** Base case of for_each. Does nothing. */
109 template <typename F>
110 inline void for_each(F &&)
111 {
112 }
113 
114 /** Call the function for each of the arguments
115  *
116  * @param[in] func Function to be called
117  * @param[in] arg  Argument passed to the function
118  * @param[in] args Remaining arguments
119  */
120 template <typename F, typename T, typename... Ts>
121 inline void for_each(F &&func, T &&arg, Ts &&... args)
122 {
123     func(std::forward<T>(arg));
124     for_each(std::forward<F>(func), std::forward<Ts>(args)...);
125 }
126 
127 /** Base case of foldl.
128  *
129  * @return value.
130  */
131 template <typename F, typename T>
132 inline T &&foldl(F &&, T &&value)
133 {
134     return std::forward<T>(value);
135 }
136 
137 /** Fold left.
138  *
139  * @param[in] func    Function to be called
140  * @param[in] initial Initial value
141  * @param[in] value   Argument passed to the function
142  * @param[in] values  Remaining arguments
143  */
144 template <typename F, typename T, typename U, typename... Us>
145 inline auto foldl(F &&func, T &&initial, U &&value, Us &&... values) -> decltype(func(std::forward<T>(initial), std::forward<U>(value)))
146 {
147     return foldl(std::forward<F>(func), func(std::forward<T>(initial), std::forward<U>(value)), std::forward<Us>(values)...);
148 }
149 
150 /** Perform an index sort of a given vector.
151  *
152  * @param[in] v Vector to sort
153  *
154  * @return Sorted index vector.
155  */
156 template <typename T>
157 std::vector<size_t> sort_indices(const std::vector<T> &v)
158 {
159     std::vector<size_t> idx(v.size());
160     std::iota(idx.begin(), idx.end(), 0);
161 
162     std::sort(idx.begin(), idx.end(),
163               [&v](size_t i1, size_t i2)
164     {
165         return v[i1] < v[i2];
166     });
167 
168     return idx;
169 }
170 
171 /** Checks if a string contains a given suffix
172  *
173  * @param[in] str    Input string
174  * @param[in] suffix Suffix to check for
175  *
176  * @return True if the string ends with the given suffix else false
177  */
178 inline bool endswith(const std::string &str, const std::string &suffix)
179 {
180     if(str.size() < suffix.size())
181     {
182         return false;
183     }
184     return std::equal(suffix.rbegin(), suffix.rend(), str.rbegin());
185 }
186 
187 /** Checks if a pointer complies with a given alignment
188  *
189  * @param[in] ptr       Pointer to check
190  * @param[in] alignment Alignment value
191  *
192  * @return True if the pointer is aligned else false
193  */
194 inline bool check_aligned(void *ptr, const size_t alignment)
195 {
196     return (reinterpret_cast<std::uintptr_t>(ptr) % alignment) == 0;
197 }
198 
199 /** Convert string to lower case.
200  *
201  * @param[in] string To be converted string.
202  *
203  * @return Lower case string.
204  */
205 inline std::string tolower(std::string string)
206 {
207     std::transform(string.begin(), string.end(), string.begin(), [](unsigned char c)
208     {
209         return std::tolower(c);
210     });
211     return string;
212 }
213 
214 /** Get environment variable as a string
215  *
216  * @note Return empty string on bare-metal
217  *
218  * @param[in] env_name Name of the Environment variable to retrieve
219  *
220  * @return Environment variable content, or empty string if the variable is undefined or on bare-metal
221  */
222 inline std::string getenv(const std::string &env_name)
223 {
224 #ifdef BARE_METAL
225     ARM_COMPUTE_UNUSED(env_name);
226     return std::string{};
227 #else  // BARE_METAL
228     const auto env_chr = std::getenv(env_name.c_str());
229     return env_chr == nullptr ? std::string{} : std::string{ env_chr };
230 #endif // BARE_METAL
231 }
232 } // namespace utility
233 } // namespace arm_compute
234 #endif /* ARM_COMPUTE_MISC_UTILITY_H */
235