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