• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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