blob: f30a417a0916c4c374e628b6971b3641e0cd0100 [file] [log] [blame]
/*
* Copyright (c) 2017-2018 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef __ARM_COMPUTE_MISC_UTILITY_H__
#define __ARM_COMPUTE_MISC_UTILITY_H__
#include <algorithm>
#include <array>
#include <limits>
#include <numeric>
#include <vector>
namespace arm_compute
{
namespace utility
{
/** @cond */
template <std::size_t...>
struct index_sequence
{
};
template <std::size_t N, std::size_t... S>
struct index_sequence_generator : index_sequence_generator < N - 1, N - 1, S... >
{
};
template <std::size_t... S>
struct index_sequence_generator<0u, S...> : index_sequence<S...>
{
using type = index_sequence<S...>;
};
template <std::size_t N>
using index_sequence_t = typename index_sequence_generator<N>::type;
/** @endcond */
namespace detail
{
template <std::size_t... S,
typename Iterator,
typename T = std::array<typename std::iterator_traits<Iterator>::value_type, sizeof...(S)>>
T make_array(Iterator first, index_sequence<S...>)
{
return T{ { first[S]... } };
}
} // namespace detail
template <std::size_t N, typename Iterator>
std::array<typename std::iterator_traits<Iterator>::value_type, N> make_array(Iterator first, Iterator last)
{
return detail::make_array(first, index_sequence_t<N> {});
}
/** Performs clamping among a lower and upper value.
*
* @param[in] n Value to clamp.
* @param[in] lower Lower threshold.
* @param[in] upper Upper threshold.
*
* @return Clamped value.
*/
template <typename T>
inline T clamp(const T &n, const T &lower, const T &upper)
{
return std::max(lower, std::min(n, upper));
}
/** Base case of for_each. Does nothing. */
template <typename F>
inline void for_each(F &&)
{
}
/** Call the function for each of the arguments
*
* @param[in] func Function to be called
* @param[in] arg Argument passed to the function
* @param[in] args Remaining arguments
*/
template <typename F, typename T, typename... Ts>
inline void for_each(F &&func, T &&arg, Ts &&... args)
{
func(std::forward<T>(arg));
for_each(std::forward<F>(func), std::forward<Ts>(args)...);
}
/** Base case of foldl.
*
* @return value.
*/
template <typename F, typename T>
inline T &&foldl(F &&, T &&value)
{
return std::forward<T>(value);
}
/** Fold left.
*
* @param[in] func Function to be called
* @param[in] initial Initial value
* @param[in] value Argument passed to the function
* @param[in] values Remaining arguments
*/
template <typename F, typename T, typename U, typename... Us>
inline auto foldl(F &&func, T &&initial, U &&value, Us &&... values) -> decltype(func(std::forward<T>(initial), std::forward<U>(value)))
{
return foldl(std::forward<F>(func), func(std::forward<T>(initial), std::forward<U>(value)), std::forward<Us>(values)...);
}
/** Type cast with saturation.
*
* @param[in] val Value of type U to cast.
*
* @return Original value clamped to numeric limits of T and converted to type T.
*
* @warning Numeric limits of T must be representable without loss in type U.
*/
template <typename T, typename U>
T saturate_cast(U val)
{
const auto low = static_cast<U>(std::numeric_limits<T>::lowest());
const auto high = static_cast<U>(std::numeric_limits<T>::max());
return static_cast<T>(clamp(val, low, high));
}
/** Perform an index sort of a given vector.
*
* @param[in] v Vector to sort
*
* @return Sorted index vector.
*/
template <typename T>
std::vector<size_t> sort_indices(const std::vector<T> &v)
{
std::vector<size_t> idx(v.size());
std::iota(idx.begin(), idx.end(), 0);
std::sort(idx.begin(), idx.end(),
[&v](size_t i1, size_t i2)
{
return v[i1] < v[i2];
});
return idx;
}
inline bool endswith(const std::string &filename, const std::string &suffix)
{
if(filename.size() < suffix.size())
{
return false;
}
return std::equal(suffix.rbegin(), suffix.rend(), filename.rbegin());
}
} // namespace utility
} // namespace arm_compute
#endif /* __ARM_COMPUTE_MISC_UTILITY_H__ */