blob: 648758ca070566a48ff18c1413fa4c7cad0e7b0e [file] [log] [blame]
Georgios Pinitas8795ffb2017-12-01 16:13:40 +00001/*
SiCongLi3b5981c2021-03-12 12:31:17 +00002 * Copyright (c) 2017-2021 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>
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +000031#include <limits>
Michalis Spyrou40df1e92018-02-06 16:53:47 +000032#include <numeric>
33#include <vector>
Georgios Pinitas8795ffb2017-12-01 16:13:40 +000034
35namespace arm_compute
36{
37namespace utility
38{
39/** @cond */
40template <std::size_t...>
41struct index_sequence
42{
43};
44
45template <std::size_t N, std::size_t... S>
46struct index_sequence_generator : index_sequence_generator < N - 1, N - 1, S... >
47{
48};
49
50template <std::size_t... S>
51struct index_sequence_generator<0u, S...> : index_sequence<S...>
52{
53 using type = index_sequence<S...>;
54};
55
56template <std::size_t N>
57using index_sequence_t = typename index_sequence_generator<N>::type;
Sang-Hoon Parkcecb0a72019-09-17 08:59:09 +010058
59template <typename T, std::size_t N, T val, T... vals>
60struct generate_array : generate_array < T, N - 1, val, val, vals... >
61{
62};
63
64template <typename T, T val, T... vals>
65struct generate_array<T, 0, val, vals...>
66{
67 static constexpr std::array<T, sizeof...(vals)> value{ vals... };
68};
69
Michalis Spyrou6bff1952019-10-02 17:22:11 +010070template <typename T, T val, T... vals>
Sang-Hoon Parkcecb0a72019-09-17 08:59:09 +010071constexpr std::array<T, sizeof...(vals)> generate_array<T, 0, val, vals...>::value;
Georgios Pinitas8795ffb2017-12-01 16:13:40 +000072/** @endcond */
73
74namespace detail
75{
76template <std::size_t... S,
77 typename Iterator,
78 typename T = std::array<typename std::iterator_traits<Iterator>::value_type, sizeof...(S)>>
79T make_array(Iterator first, index_sequence<S...>)
80{
81 return T{ { first[S]... } };
82}
83} // namespace detail
84
85template <std::size_t N, typename Iterator>
86std::array<typename std::iterator_traits<Iterator>::value_type, N> make_array(Iterator first, Iterator last)
87{
Michalis Spyrou6bff1952019-10-02 17:22:11 +010088 ARM_COMPUTE_UNUSED(last);
Georgios Pinitas8795ffb2017-12-01 16:13:40 +000089 return detail::make_array(first, index_sequence_t<N> {});
90}
Diego Lopez Recas490b3d82017-12-19 15:42:25 +000091
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 */
Vidhya Sudhan Loganathan5e96be72018-12-18 14:17:00 +0000100template <typename DataType, typename RangeType = DataType>
101inline DataType clamp(const DataType &n,
102 const DataType &lower = std::numeric_limits<RangeType>::lowest(),
103 const DataType &upper = std::numeric_limits<RangeType>::max())
Diego Lopez Recas490b3d82017-12-19 15:42:25 +0000104{
105 return std::max(lower, std::min(n, upper));
106}
107
108/** Base case of for_each. Does nothing. */
109template <typename F>
110inline 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 */
120template <typename F, typename T, typename... Ts>
121inline 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 */
131template <typename F, typename T>
132inline 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 */
144template <typename F, typename T, typename U, typename... Us>
145inline 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}
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +0000149
Michalis Spyrou40df1e92018-02-06 16:53:47 +0000150/** Perform an index sort of a given vector.
151 *
152 * @param[in] v Vector to sort
153 *
154 * @return Sorted index vector.
155 */
156template <typename T>
157std::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}
Isabella Gottardi88d5b222018-04-06 12:24:55 +0100170
Georgios Pinitas17b12302018-06-18 18:13:51 +0100171/** 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 */
178inline bool endswith(const std::string &str, const std::string &suffix)
Isabella Gottardi88d5b222018-04-06 12:24:55 +0100179{
Georgios Pinitas17b12302018-06-18 18:13:51 +0100180 if(str.size() < suffix.size())
Isabella Gottardi88d5b222018-04-06 12:24:55 +0100181 {
182 return false;
183 }
Georgios Pinitas17b12302018-06-18 18:13:51 +0100184 return std::equal(suffix.rbegin(), suffix.rend(), str.rbegin());
Isabella Gottardi88d5b222018-04-06 12:24:55 +0100185}
186
Georgios Pinitas17b12302018-06-18 18:13:51 +0100187/** 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 */
194inline bool check_aligned(void *ptr, const size_t alignment)
195{
196 return (reinterpret_cast<std::uintptr_t>(ptr) % alignment) == 0;
197}
Georgios Pinitas12be7ab2018-07-03 12:06:23 +0100198
199/** Convert string to lower case.
200 *
201 * @param[in] string To be converted string.
202 *
203 * @return Lower case string.
204 */
205inline 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}
SiCongLi3b5981c2021-03-12 12:31:17 +0000213
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 */
222inline 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}
Diego Lopez Recas490b3d82017-12-19 15:42:25 +0000232} // namespace utility
Georgios Pinitas8795ffb2017-12-01 16:13:40 +0000233} // namespace arm_compute
Michalis Spyrouf4643372019-11-29 16:17:13 +0000234#endif /* ARM_COMPUTE_MISC_UTILITY_H */