blob: f30a417a0916c4c374e628b6971b3641e0cd0100 [file] [log] [blame]
Georgios Pinitas8795ffb2017-12-01 16:13:40 +00001/*
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +00002 * Copyright (c) 2017-2018 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 */
24#ifndef __ARM_COMPUTE_MISC_UTILITY_H__
25#define __ARM_COMPUTE_MISC_UTILITY_H__
26
Michalis Spyrou40df1e92018-02-06 16:53:47 +000027#include <algorithm>
Georgios Pinitas8795ffb2017-12-01 16:13:40 +000028#include <array>
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +000029#include <limits>
Michalis Spyrou40df1e92018-02-06 16:53:47 +000030#include <numeric>
31#include <vector>
Georgios Pinitas8795ffb2017-12-01 16:13:40 +000032
33namespace arm_compute
34{
35namespace utility
36{
37/** @cond */
38template <std::size_t...>
39struct index_sequence
40{
41};
42
43template <std::size_t N, std::size_t... S>
44struct index_sequence_generator : index_sequence_generator < N - 1, N - 1, S... >
45{
46};
47
48template <std::size_t... S>
49struct index_sequence_generator<0u, S...> : index_sequence<S...>
50{
51 using type = index_sequence<S...>;
52};
53
54template <std::size_t N>
55using index_sequence_t = typename index_sequence_generator<N>::type;
56/** @endcond */
57
58namespace detail
59{
60template <std::size_t... S,
61 typename Iterator,
62 typename T = std::array<typename std::iterator_traits<Iterator>::value_type, sizeof...(S)>>
63T make_array(Iterator first, index_sequence<S...>)
64{
65 return T{ { first[S]... } };
66}
67} // namespace detail
68
69template <std::size_t N, typename Iterator>
70std::array<typename std::iterator_traits<Iterator>::value_type, N> make_array(Iterator first, Iterator last)
71{
72 return detail::make_array(first, index_sequence_t<N> {});
73}
Diego Lopez Recas490b3d82017-12-19 15:42:25 +000074
75/** Performs clamping among a lower and upper value.
76 *
77 * @param[in] n Value to clamp.
78 * @param[in] lower Lower threshold.
79 * @param[in] upper Upper threshold.
80 *
81 * @return Clamped value.
82 */
83template <typename T>
84inline T clamp(const T &n, const T &lower, const T &upper)
85{
86 return std::max(lower, std::min(n, upper));
87}
88
89/** Base case of for_each. Does nothing. */
90template <typename F>
91inline void for_each(F &&)
92{
93}
94
95/** Call the function for each of the arguments
96 *
97 * @param[in] func Function to be called
98 * @param[in] arg Argument passed to the function
99 * @param[in] args Remaining arguments
100 */
101template <typename F, typename T, typename... Ts>
102inline void for_each(F &&func, T &&arg, Ts &&... args)
103{
104 func(std::forward<T>(arg));
105 for_each(std::forward<F>(func), std::forward<Ts>(args)...);
106}
107
108/** Base case of foldl.
109 *
110 * @return value.
111 */
112template <typename F, typename T>
113inline T &&foldl(F &&, T &&value)
114{
115 return std::forward<T>(value);
116}
117
118/** Fold left.
119 *
120 * @param[in] func Function to be called
121 * @param[in] initial Initial value
122 * @param[in] value Argument passed to the function
123 * @param[in] values Remaining arguments
124 */
125template <typename F, typename T, typename U, typename... Us>
126inline auto foldl(F &&func, T &&initial, U &&value, Us &&... values) -> decltype(func(std::forward<T>(initial), std::forward<U>(value)))
127{
128 return foldl(std::forward<F>(func), func(std::forward<T>(initial), std::forward<U>(value)), std::forward<Us>(values)...);
129}
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +0000130
131/** Type cast with saturation.
132 *
133 * @param[in] val Value of type U to cast.
134 *
135 * @return Original value clamped to numeric limits of T and converted to type T.
136 *
137 * @warning Numeric limits of T must be representable without loss in type U.
138 */
139template <typename T, typename U>
140T saturate_cast(U val)
141{
142 const auto low = static_cast<U>(std::numeric_limits<T>::lowest());
143 const auto high = static_cast<U>(std::numeric_limits<T>::max());
144 return static_cast<T>(clamp(val, low, high));
145}
Michalis Spyrou40df1e92018-02-06 16:53:47 +0000146
147/** Perform an index sort of a given vector.
148 *
149 * @param[in] v Vector to sort
150 *
151 * @return Sorted index vector.
152 */
153template <typename T>
154std::vector<size_t> sort_indices(const std::vector<T> &v)
155{
156 std::vector<size_t> idx(v.size());
157 std::iota(idx.begin(), idx.end(), 0);
158
159 std::sort(idx.begin(), idx.end(),
160 [&v](size_t i1, size_t i2)
161 {
162 return v[i1] < v[i2];
163 });
164
165 return idx;
166}
Isabella Gottardi88d5b222018-04-06 12:24:55 +0100167
168inline bool endswith(const std::string &filename, const std::string &suffix)
169{
170 if(filename.size() < suffix.size())
171 {
172 return false;
173 }
174 return std::equal(suffix.rbegin(), suffix.rend(), filename.rbegin());
175}
176
Diego Lopez Recas490b3d82017-12-19 15:42:25 +0000177} // namespace utility
Georgios Pinitas8795ffb2017-12-01 16:13:40 +0000178} // namespace arm_compute
179#endif /* __ARM_COMPUTE_MISC_UTILITY_H__ */