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