1*c217d954SCole Faust /* 2*c217d954SCole Faust * Copyright (c) 2017-2020 Arm Limited. 3*c217d954SCole Faust * 4*c217d954SCole Faust * SPDX-License-Identifier: MIT 5*c217d954SCole Faust * 6*c217d954SCole Faust * Permission is hereby granted, free of charge, to any person obtaining a copy 7*c217d954SCole Faust * of this software and associated documentation files (the "Software"), to 8*c217d954SCole Faust * deal in the Software without restriction, including without limitation the 9*c217d954SCole Faust * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10*c217d954SCole Faust * sell copies of the Software, and to permit persons to whom the Software is 11*c217d954SCole Faust * furnished to do so, subject to the following conditions: 12*c217d954SCole Faust * 13*c217d954SCole Faust * The above copyright notice and this permission notice shall be included in all 14*c217d954SCole Faust * copies or substantial portions of the Software. 15*c217d954SCole Faust * 16*c217d954SCole Faust * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17*c217d954SCole Faust * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18*c217d954SCole Faust * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19*c217d954SCole Faust * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20*c217d954SCole Faust * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21*c217d954SCole Faust * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22*c217d954SCole Faust * SOFTWARE. 23*c217d954SCole Faust */ 24*c217d954SCole Faust #ifndef ARM_COMPUTE_TEST_UTILS 25*c217d954SCole Faust #define ARM_COMPUTE_TEST_UTILS 26*c217d954SCole Faust 27*c217d954SCole Faust #include "support/StringSupport.h" 28*c217d954SCole Faust 29*c217d954SCole Faust #include <algorithm> 30*c217d954SCole Faust #include <cmath> 31*c217d954SCole Faust #include <cstddef> 32*c217d954SCole Faust #include <limits> 33*c217d954SCole Faust #include <memory> 34*c217d954SCole Faust #include <numeric> 35*c217d954SCole Faust #include <sstream> 36*c217d954SCole Faust #include <string> 37*c217d954SCole Faust #include <type_traits> 38*c217d954SCole Faust 39*c217d954SCole Faust namespace arm_compute 40*c217d954SCole Faust { 41*c217d954SCole Faust namespace test 42*c217d954SCole Faust { 43*c217d954SCole Faust namespace framework 44*c217d954SCole Faust { 45*c217d954SCole Faust /** @cond */ 46*c217d954SCole Faust namespace detail 47*c217d954SCole Faust { 48*c217d954SCole Faust template <int...> 49*c217d954SCole Faust struct sequence 50*c217d954SCole Faust { 51*c217d954SCole Faust }; 52*c217d954SCole Faust 53*c217d954SCole Faust template <int N, int... Ns> 54*c217d954SCole Faust struct sequence_generator; 55*c217d954SCole Faust 56*c217d954SCole Faust template <int... Ns> 57*c217d954SCole Faust struct sequence_generator<0, Ns...> 58*c217d954SCole Faust { 59*c217d954SCole Faust using type = sequence<Ns...>; 60*c217d954SCole Faust }; 61*c217d954SCole Faust 62*c217d954SCole Faust template <int N, int... Ns> 63*c217d954SCole Faust struct sequence_generator : sequence_generator < N - 1, N - 1, Ns... > 64*c217d954SCole Faust { 65*c217d954SCole Faust }; 66*c217d954SCole Faust 67*c217d954SCole Faust template <int N> 68*c217d954SCole Faust using sequence_t = typename sequence_generator<N>::type; 69*c217d954SCole Faust /** @endcond */ 70*c217d954SCole Faust 71*c217d954SCole Faust template <typename O, typename F, typename... As, int... S> 72*c217d954SCole Faust void apply_impl(O *obj, F &&func, const std::tuple<As...> &args, detail::sequence<S...>) 73*c217d954SCole Faust { 74*c217d954SCole Faust (obj->*func)(std::get<S>(args)...); 75*c217d954SCole Faust } 76*c217d954SCole Faust } // namespace 77*c217d954SCole Faust 78*c217d954SCole Faust template <typename O, typename F, typename... As> 79*c217d954SCole Faust void apply(O *obj, F &&func, const std::tuple<As...> &args) 80*c217d954SCole Faust { 81*c217d954SCole Faust detail::apply_impl(obj, std::forward<F>(func), args, detail::sequence_t<sizeof...(As)>()); 82*c217d954SCole Faust } 83*c217d954SCole Faust 84*c217d954SCole Faust /** Helper function to concatenate multiple strings. 85*c217d954SCole Faust * 86*c217d954SCole Faust * @param[in] first Iterator pointing to the first element to be concatenated. 87*c217d954SCole Faust * @param[in] last Iterator pointing behind the last element to be concatenated. 88*c217d954SCole Faust * @param[in] separator String used to join the elements. 89*c217d954SCole Faust * 90*c217d954SCole Faust * @return String containing all elements joined by @p separator. 91*c217d954SCole Faust */ 92*c217d954SCole Faust template <typename T, typename std::enable_if<std::is_same<typename T::value_type, std::string>::value, int>::type = 0> 93*c217d954SCole Faust std::string join(T first, T last, const std::string &separator) 94*c217d954SCole Faust { 95*c217d954SCole Faust return std::accumulate(std::next(first), last, *first, [&separator](const std::string & base, const std::string & suffix) 96*c217d954SCole Faust { 97*c217d954SCole Faust return base + separator + suffix; 98*c217d954SCole Faust }); 99*c217d954SCole Faust } 100*c217d954SCole Faust 101*c217d954SCole Faust /** Helper function to concatenate multiple values. 102*c217d954SCole Faust * 103*c217d954SCole Faust * All values are converted to std::string using the provided operation before 104*c217d954SCole Faust * being joined. 105*c217d954SCole Faust * 106*c217d954SCole Faust * The signature of op has to be equivalent to 107*c217d954SCole Faust * std::string op(const T::value_type &val). 108*c217d954SCole Faust * 109*c217d954SCole Faust * @param[in] first Iterator pointing to the first element to be concatenated. 110*c217d954SCole Faust * @param[in] last Iterator pointing behind the last element to be concatenated. 111*c217d954SCole Faust * @param[in] separator String used to join the elements. 112*c217d954SCole Faust * @param[in] op Conversion function. 113*c217d954SCole Faust * 114*c217d954SCole Faust * @return String containing all elements joined by @p separator. 115*c217d954SCole Faust */ 116*c217d954SCole Faust template <typename T, typename UnaryOp> 117*c217d954SCole Faust std::string join(T &&first, T &&last, const std::string &separator, UnaryOp &&op) 118*c217d954SCole Faust { 119*c217d954SCole Faust return std::accumulate(std::next(first), last, op(*first), [&separator, &op](const std::string & base, const typename T::value_type & suffix) 120*c217d954SCole Faust { 121*c217d954SCole Faust return base + separator + op(suffix); 122*c217d954SCole Faust }); 123*c217d954SCole Faust } 124*c217d954SCole Faust 125*c217d954SCole Faust /** Helper function to concatenate multiple values. 126*c217d954SCole Faust * 127*c217d954SCole Faust * All values are converted to std::string using std::to_string before being joined. 128*c217d954SCole Faust * 129*c217d954SCole Faust * @param[in] first Iterator pointing to the first element to be concatenated. 130*c217d954SCole Faust * @param[in] last Iterator pointing behind the last element to be concatenated. 131*c217d954SCole Faust * @param[in] separator String used to join the elements. 132*c217d954SCole Faust * 133*c217d954SCole Faust * @return String containing all elements joined by @p separator. 134*c217d954SCole Faust */ 135*c217d954SCole Faust template <typename T, typename std::enable_if<std::is_arithmetic<typename T::value_type>::value, int>::type = 0> 136*c217d954SCole Faust std::string join(T && first, T && last, const std::string &separator) 137*c217d954SCole Faust { 138*c217d954SCole Faust return join(std::forward<T>(first), std::forward<T>(last), separator, support::cpp11::to_string); 139*c217d954SCole Faust } 140*c217d954SCole Faust 141*c217d954SCole Faust /** Convert string to lower case. 142*c217d954SCole Faust * 143*c217d954SCole Faust * @param[in] string To be converted string. 144*c217d954SCole Faust * 145*c217d954SCole Faust * @return Lower case string. 146*c217d954SCole Faust */ 147*c217d954SCole Faust inline std::string tolower(std::string string) 148*c217d954SCole Faust { 149*c217d954SCole Faust std::transform(string.begin(), string.end(), string.begin(), [](unsigned char c) 150*c217d954SCole Faust { 151*c217d954SCole Faust return std::tolower(c); 152*c217d954SCole Faust }); 153*c217d954SCole Faust return string; 154*c217d954SCole Faust } 155*c217d954SCole Faust 156*c217d954SCole Faust /** Create a string with the arithmetic value in full precision. 157*c217d954SCole Faust * 158*c217d954SCole Faust * @param val Arithmetic value 159*c217d954SCole Faust * @param decimal_places How many decimal places to show 160*c217d954SCole Faust * 161*c217d954SCole Faust * @return String with the arithmetic value. 162*c217d954SCole Faust */ 163*c217d954SCole Faust template <typename T, typename std::enable_if<std::is_arithmetic<T>::value, int>::type = 0> 164*c217d954SCole Faust inline std::string arithmetic_to_string(T val, int decimal_places = 0) 165*c217d954SCole Faust { 166*c217d954SCole Faust std::stringstream ss; 167*c217d954SCole Faust ss << std::fixed; 168*c217d954SCole Faust ss.precision((decimal_places) ? decimal_places : std::numeric_limits<T>::digits10 + 1); 169*c217d954SCole Faust ss << val; 170*c217d954SCole Faust return ss.str(); 171*c217d954SCole Faust } 172*c217d954SCole Faust 173*c217d954SCole Faust /** Makes the calling thread to sleep for a specified number of seconds 174*c217d954SCole Faust * 175*c217d954SCole Faust * @param[in] seconds Amount of seconds to sleep. Will return immediately if less or equal to zero. 176*c217d954SCole Faust */ 177*c217d954SCole Faust void sleep_in_seconds(float seconds); 178*c217d954SCole Faust } // namespace framework 179*c217d954SCole Faust } // namespace test 180*c217d954SCole Faust } // namespace arm_compute 181*c217d954SCole Faust #endif /* ARM_COMPUTE_TEST_UTILS */ 182