1*c217d954SCole Faust /* 2*c217d954SCole Faust * Copyright (c) 2017-2022 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_VALIDATION_HELPERS_H 25*c217d954SCole Faust #define ARM_COMPUTE_TEST_VALIDATION_HELPERS_H 26*c217d954SCole Faust 27*c217d954SCole Faust #include "arm_compute/core/Types.h" 28*c217d954SCole Faust #include "arm_compute/core/Utils.h" 29*c217d954SCole Faust #include "support/Half.h" 30*c217d954SCole Faust #include "tests/Globals.h" 31*c217d954SCole Faust #include "tests/SimpleTensor.h" 32*c217d954SCole Faust 33*c217d954SCole Faust #include <math.h> 34*c217d954SCole Faust #include <random> 35*c217d954SCole Faust #include <type_traits> 36*c217d954SCole Faust #include <utility> 37*c217d954SCole Faust 38*c217d954SCole Faust namespace arm_compute 39*c217d954SCole Faust { 40*c217d954SCole Faust namespace test 41*c217d954SCole Faust { 42*c217d954SCole Faust namespace validation 43*c217d954SCole Faust { 44*c217d954SCole Faust template <typename T> 45*c217d954SCole Faust struct is_floating_point : public std::is_floating_point<T> 46*c217d954SCole Faust { 47*c217d954SCole Faust }; 48*c217d954SCole Faust 49*c217d954SCole Faust template <> 50*c217d954SCole Faust struct is_floating_point<half> : public std::true_type 51*c217d954SCole Faust { 52*c217d954SCole Faust }; 53*c217d954SCole Faust 54*c217d954SCole Faust /** Helper function to get the testing range for each activation layer. 55*c217d954SCole Faust * 56*c217d954SCole Faust * @param[in] activation Activation function to test. 57*c217d954SCole Faust * @param[in] data_type Data type. 58*c217d954SCole Faust * 59*c217d954SCole Faust * @return A pair containing the lower upper testing bounds for a given function. 60*c217d954SCole Faust */ 61*c217d954SCole Faust template <typename T> 62*c217d954SCole Faust std::pair<T, T> get_activation_layer_test_bounds(ActivationLayerInfo::ActivationFunction activation, DataType data_type) 63*c217d954SCole Faust { 64*c217d954SCole Faust std::pair<T, T> bounds; 65*c217d954SCole Faust 66*c217d954SCole Faust switch(data_type) 67*c217d954SCole Faust { 68*c217d954SCole Faust case DataType::F16: 69*c217d954SCole Faust { 70*c217d954SCole Faust using namespace half_float::literal; 71*c217d954SCole Faust 72*c217d954SCole Faust switch(activation) 73*c217d954SCole Faust { 74*c217d954SCole Faust case ActivationLayerInfo::ActivationFunction::TANH: 75*c217d954SCole Faust case ActivationLayerInfo::ActivationFunction::SQUARE: 76*c217d954SCole Faust case ActivationLayerInfo::ActivationFunction::LOGISTIC: 77*c217d954SCole Faust case ActivationLayerInfo::ActivationFunction::SOFT_RELU: 78*c217d954SCole Faust // Reduce range as exponent overflows 79*c217d954SCole Faust bounds = std::make_pair(-2._h, 2._h); 80*c217d954SCole Faust break; 81*c217d954SCole Faust case ActivationLayerInfo::ActivationFunction::SQRT: 82*c217d954SCole Faust // Reduce range as sqrt should take a non-negative number 83*c217d954SCole Faust bounds = std::make_pair(0._h, 128._h); 84*c217d954SCole Faust break; 85*c217d954SCole Faust default: 86*c217d954SCole Faust bounds = std::make_pair(-255._h, 255._h); 87*c217d954SCole Faust break; 88*c217d954SCole Faust } 89*c217d954SCole Faust break; 90*c217d954SCole Faust } 91*c217d954SCole Faust case DataType::F32: 92*c217d954SCole Faust switch(activation) 93*c217d954SCole Faust { 94*c217d954SCole Faust case ActivationLayerInfo::ActivationFunction::SOFT_RELU: 95*c217d954SCole Faust // Reduce range as exponent overflows 96*c217d954SCole Faust bounds = std::make_pair(-40.f, 40.f); 97*c217d954SCole Faust break; 98*c217d954SCole Faust case ActivationLayerInfo::ActivationFunction::SQRT: 99*c217d954SCole Faust // Reduce range as sqrt should take a non-negative number 100*c217d954SCole Faust bounds = std::make_pair(0.f, 255.f); 101*c217d954SCole Faust break; 102*c217d954SCole Faust default: 103*c217d954SCole Faust bounds = std::make_pair(-255.f, 255.f); 104*c217d954SCole Faust break; 105*c217d954SCole Faust } 106*c217d954SCole Faust break; 107*c217d954SCole Faust default: 108*c217d954SCole Faust ARM_COMPUTE_ERROR("Unsupported data type"); 109*c217d954SCole Faust } 110*c217d954SCole Faust 111*c217d954SCole Faust return bounds; 112*c217d954SCole Faust } 113*c217d954SCole Faust 114*c217d954SCole Faust /** Calculate output tensor shape give a vector of input tensor to concatenate 115*c217d954SCole Faust * 116*c217d954SCole Faust * @param[in] input_shapes Shapes of the tensors to concatenate across depth. 117*c217d954SCole Faust * 118*c217d954SCole Faust * @return The shape of output concatenated tensor. 119*c217d954SCole Faust */ 120*c217d954SCole Faust TensorShape calculate_depth_concatenate_shape(const std::vector<TensorShape> &input_shapes); 121*c217d954SCole Faust 122*c217d954SCole Faust /** Calculate output tensor shape for the concatenate operation along a given axis 123*c217d954SCole Faust * 124*c217d954SCole Faust * @param[in] input_shapes Shapes of the tensors to concatenate across width. 125*c217d954SCole Faust * @param[in] axis Axis to use for the concatenate operation 126*c217d954SCole Faust * 127*c217d954SCole Faust * @return The shape of output concatenated tensor. 128*c217d954SCole Faust */ 129*c217d954SCole Faust TensorShape calculate_concatenate_shape(const std::vector<TensorShape> &input_shapes, size_t axis); 130*c217d954SCole Faust 131*c217d954SCole Faust /** Convert an asymmetric quantized simple tensor into float using tensor quantization information. 132*c217d954SCole Faust * 133*c217d954SCole Faust * @param[in] src Quantized tensor. 134*c217d954SCole Faust * 135*c217d954SCole Faust * @return Float tensor. 136*c217d954SCole Faust */ 137*c217d954SCole Faust template <typename T> 138*c217d954SCole Faust SimpleTensor<float> convert_from_asymmetric(const SimpleTensor<T> &src); 139*c217d954SCole Faust 140*c217d954SCole Faust /** Convert float simple tensor into quantized using specified quantization information. 141*c217d954SCole Faust * 142*c217d954SCole Faust * @param[in] src Float tensor. 143*c217d954SCole Faust * @param[in] quantization_info Quantification information. 144*c217d954SCole Faust * 145*c217d954SCole Faust * @return Quantized tensor. 146*c217d954SCole Faust */ 147*c217d954SCole Faust template <typename T> 148*c217d954SCole Faust SimpleTensor<T> convert_to_asymmetric(const SimpleTensor<float> &src, const QuantizationInfo &quantization_info); 149*c217d954SCole Faust 150*c217d954SCole Faust /** Convert quantized simple tensor into float using tensor quantization information. 151*c217d954SCole Faust * 152*c217d954SCole Faust * @param[in] src Quantized tensor. 153*c217d954SCole Faust * 154*c217d954SCole Faust * @return Float tensor. 155*c217d954SCole Faust */ 156*c217d954SCole Faust template <typename T> 157*c217d954SCole Faust SimpleTensor<float> convert_from_symmetric(const SimpleTensor<T> &src); 158*c217d954SCole Faust 159*c217d954SCole Faust /** Convert float simple tensor into quantized using specified quantization information. 160*c217d954SCole Faust * 161*c217d954SCole Faust * @param[in] src Float tensor. 162*c217d954SCole Faust * @param[in] quantization_info Quantification information. 163*c217d954SCole Faust * 164*c217d954SCole Faust * @return Quantized tensor. 165*c217d954SCole Faust */ 166*c217d954SCole Faust template <typename T> 167*c217d954SCole Faust SimpleTensor<T> convert_to_symmetric(const SimpleTensor<float> &src, const QuantizationInfo &quantization_info); 168*c217d954SCole Faust 169*c217d954SCole Faust /** Matrix multiply between 2 float simple tensors 170*c217d954SCole Faust * 171*c217d954SCole Faust * @param[in] a Input tensor A 172*c217d954SCole Faust * @param[in] b Input tensor B 173*c217d954SCole Faust * @param[out] out Output tensor 174*c217d954SCole Faust * 175*c217d954SCole Faust */ 176*c217d954SCole Faust template <typename T> 177*c217d954SCole Faust void matrix_multiply(const SimpleTensor<T> &a, const SimpleTensor<T> &b, SimpleTensor<T> &out); 178*c217d954SCole Faust 179*c217d954SCole Faust /** Transpose matrix 180*c217d954SCole Faust * 181*c217d954SCole Faust * @param[in] in Input tensor 182*c217d954SCole Faust * @param[out] out Output tensor 183*c217d954SCole Faust * 184*c217d954SCole Faust */ 185*c217d954SCole Faust template <typename T> 186*c217d954SCole Faust void transpose_matrix(const SimpleTensor<T> &in, SimpleTensor<T> &out); 187*c217d954SCole Faust 188*c217d954SCole Faust /** Get a 2D tile from a tensor 189*c217d954SCole Faust * 190*c217d954SCole Faust * @note In case of out-of-bound reads, the tile will be filled with zeros 191*c217d954SCole Faust * 192*c217d954SCole Faust * @param[in] in Input tensor 193*c217d954SCole Faust * @param[out] tile Tile 194*c217d954SCole Faust * @param[in] coord Coordinates 195*c217d954SCole Faust */ 196*c217d954SCole Faust template <typename T> 197*c217d954SCole Faust void get_tile(const SimpleTensor<T> &in, SimpleTensor<T> &tile, const Coordinates &coord); 198*c217d954SCole Faust 199*c217d954SCole Faust /** Fill with zeros the input tensor in the area defined by anchor and shape 200*c217d954SCole Faust * 201*c217d954SCole Faust * @param[in] in Input tensor to fill with zeros 202*c217d954SCole Faust * @param[out] anchor Starting point of the zeros area 203*c217d954SCole Faust * @param[in] shape Ending point of the zeros area 204*c217d954SCole Faust */ 205*c217d954SCole Faust template <typename T> 206*c217d954SCole Faust void zeros(SimpleTensor<T> &in, const Coordinates &anchor, const TensorShape &shape); 207*c217d954SCole Faust 208*c217d954SCole Faust /** Helper function to compute quantized min and max bounds 209*c217d954SCole Faust * 210*c217d954SCole Faust * @param[in] quant_info Quantization info to be used for conversion 211*c217d954SCole Faust * @param[in] min Floating point minimum value to be quantized 212*c217d954SCole Faust * @param[in] max Floating point maximum value to be quantized 213*c217d954SCole Faust */ 214*c217d954SCole Faust std::pair<int, int> get_quantized_bounds(const QuantizationInfo &quant_info, float min, float max); 215*c217d954SCole Faust 216*c217d954SCole Faust /** Helper function to compute asymmetric quantized signed min and max bounds 217*c217d954SCole Faust * 218*c217d954SCole Faust * @param[in] quant_info Quantization info to be used for conversion 219*c217d954SCole Faust * @param[in] min Floating point minimum value to be quantized 220*c217d954SCole Faust * @param[in] max Floating point maximum value to be quantized 221*c217d954SCole Faust */ 222*c217d954SCole Faust std::pair<int, int> get_quantized_qasymm8_signed_bounds(const QuantizationInfo &quant_info, float min, float max); 223*c217d954SCole Faust 224*c217d954SCole Faust /** Helper function to compute symmetric quantized min and max bounds 225*c217d954SCole Faust * 226*c217d954SCole Faust * @param[in] quant_info Quantization info to be used for conversion 227*c217d954SCole Faust * @param[in] min Floating point minimum value to be quantized 228*c217d954SCole Faust * @param[in] max Floating point maximum value to be quantized 229*c217d954SCole Faust * @param[in] channel_id Channel id for per channel quantization info. 230*c217d954SCole Faust */ 231*c217d954SCole Faust std::pair<int, int> get_symm_quantized_per_channel_bounds(const QuantizationInfo &quant_info, float min, float max, size_t channel_id = 0); 232*c217d954SCole Faust 233*c217d954SCole Faust /** Add random padding along the X axis (between 1 and 16 columns per side) to all the input tensors. 234*c217d954SCole Faust * This is used in our validation suite in order to simulate implicit padding addition after configuring, but before allocating. 235*c217d954SCole Faust * 236*c217d954SCole Faust * @param[in] tensors List of tensors to add padding to 237*c217d954SCole Faust * @param[in] data_layout (Optional) Data layout of the operator 238*c217d954SCole Faust * @param[in] only_right_pad (Optional) Only right padding testing, in case of cl image padding 239*c217d954SCole Faust * 240*c217d954SCole Faust * @note This function adds padding to the input tensors only if data_layout == DataLayout::NHWC 241*c217d954SCole Faust */ 242*c217d954SCole Faust void add_padding_x(std::initializer_list<ITensor *> tensors, const DataLayout &data_layout = DataLayout::NHWC, bool only_right_pad = false); 243*c217d954SCole Faust 244*c217d954SCole Faust /** Add random padding along the Y axis (between 1 and 4 rows per side) to all the input tensors. 245*c217d954SCole Faust * This is used in our validation suite in order to simulate implicit padding addition after configuring, but before allocating. 246*c217d954SCole Faust * 247*c217d954SCole Faust * @param[in] tensors List of tensors to add padding to 248*c217d954SCole Faust * @param[in] data_layout (Optional) Data layout of the operator 249*c217d954SCole Faust * 250*c217d954SCole Faust * @note This function adds padding to the input tensors only if data_layout == DataLayout::NHWC 251*c217d954SCole Faust */ 252*c217d954SCole Faust void add_padding_y(std::initializer_list<ITensor *> tensors, const DataLayout &data_layout = DataLayout::NHWC); 253*c217d954SCole Faust } // namespace validation 254*c217d954SCole Faust } // namespace test 255*c217d954SCole Faust } // namespace arm_compute 256*c217d954SCole Faust #endif /* ARM_COMPUTE_TEST_VALIDATION_HELPERS_H */ 257