1 /* 2 * Copyright (c) 2017-2020 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_TEST_SCALE_FIXTURE 25 #define ARM_COMPUTE_TEST_SCALE_FIXTURE 26 27 #include "arm_compute/core/TensorShape.h" 28 #include "arm_compute/core/Types.h" 29 #include "tests/AssetsLibrary.h" 30 #include "tests/Globals.h" 31 #include "tests/IAccessor.h" 32 #include "tests/framework/Asserts.h" 33 #include "tests/framework/Fixture.h" 34 #include "tests/validation/reference/Permute.h" 35 #include "tests/validation/reference/Scale.h" 36 37 namespace arm_compute 38 { 39 namespace test 40 { 41 namespace validation 42 { 43 template <typename TensorType, typename AccessorType, typename FunctionType, typename T> 44 class ScaleValidationGenericFixture : public framework::Fixture 45 { 46 public: 47 template <typename...> setup(TensorShape shape,DataType data_type,QuantizationInfo quantization_info,DataLayout data_layout,InterpolationPolicy policy,BorderMode border_mode,SamplingPolicy sampling_policy,bool align_corners)48 void setup(TensorShape shape, DataType data_type, QuantizationInfo quantization_info, DataLayout data_layout, InterpolationPolicy policy, BorderMode border_mode, SamplingPolicy sampling_policy, 49 bool align_corners) 50 { 51 _shape = shape; 52 _policy = policy; 53 _border_mode = border_mode; 54 _sampling_policy = sampling_policy; 55 _data_type = data_type; 56 _quantization_info = quantization_info; 57 _align_corners = align_corners; 58 59 generate_scale(shape); 60 61 std::mt19937 generator(library->seed()); 62 std::uniform_int_distribution<uint8_t> distribution_u8(0, 255); 63 _constant_border_value = static_cast<T>(distribution_u8(generator)); 64 65 _target = compute_target(shape, data_layout); 66 _reference = compute_reference(shape); 67 } 68 69 protected: generate_scale(const TensorShape & shape)70 void generate_scale(const TensorShape &shape) 71 { 72 static constexpr float _min_scale{ 0.25f }; 73 static constexpr float _max_scale{ 3.f }; 74 75 constexpr float max_width{ 8192.0f }; 76 constexpr float max_height{ 6384.0f }; 77 const float min_width{ 1.f }; 78 const float min_height{ 1.f }; 79 80 std::mt19937 generator(library->seed()); 81 std::uniform_real_distribution<float> distribution_float(_min_scale, _max_scale); 82 83 auto generate = [&](size_t input_size, float min_output, float max_output) -> float 84 { 85 const float generated_scale = distribution_float(generator); 86 const float output_size = utility::clamp(static_cast<float>(input_size) * generated_scale, min_output, max_output); 87 return output_size / input_size; 88 }; 89 90 // Input shape is always given in NCHW layout. NHWC is dealt by permute in compute_target() 91 const int idx_width = get_data_layout_dimension_index(DataLayout::NCHW, DataLayoutDimension::WIDTH); 92 const int idx_height = get_data_layout_dimension_index(DataLayout::NCHW, DataLayoutDimension::HEIGHT); 93 94 _scale_x = generate(shape[idx_width], min_width, max_width); 95 _scale_y = generate(shape[idx_height], min_height, max_height); 96 } 97 98 template <typename U> fill(U && tensor)99 void fill(U &&tensor) 100 { 101 if(is_data_type_float(_data_type)) 102 { 103 library->fill_tensor_uniform(tensor, 0); 104 } 105 else if(is_data_type_quantized(tensor.data_type())) 106 { 107 std::uniform_int_distribution<> distribution(0, 100); 108 library->fill(tensor, distribution, 0); 109 } 110 else 111 { 112 // Restrict range for float to avoid any floating point issues 113 std::uniform_real_distribution<> distribution(-5.0f, 5.0f); 114 library->fill(tensor, distribution, 0); 115 } 116 } 117 compute_target(TensorShape shape,DataLayout data_layout)118 TensorType compute_target(TensorShape shape, DataLayout data_layout) 119 { 120 // Change shape in case of NHWC. 121 if(data_layout == DataLayout::NHWC) 122 { 123 permute(shape, PermutationVector(2U, 0U, 1U)); 124 } 125 126 // Create tensors 127 TensorType src = create_tensor<TensorType>(shape, _data_type, 1, _quantization_info, data_layout); 128 129 const int idx_width = get_data_layout_dimension_index(data_layout, DataLayoutDimension::WIDTH); 130 const int idx_height = get_data_layout_dimension_index(data_layout, DataLayoutDimension::HEIGHT); 131 132 TensorShape shape_scaled(shape); 133 shape_scaled.set(idx_width, shape[idx_width] * _scale_x, /* apply_dim_correction = */ false); 134 shape_scaled.set(idx_height, shape[idx_height] * _scale_y, /* apply_dim_correction = */ false); 135 TensorType dst = create_tensor<TensorType>(shape_scaled, _data_type, 1, _quantization_info, data_layout); 136 137 // Create and configure function 138 FunctionType scale; 139 140 scale.configure(&src, &dst, ScaleKernelInfo{ _policy, _border_mode, _constant_border_value, _sampling_policy, /* use_padding */ false, _align_corners }); 141 142 ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); 143 ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); 144 145 // Allocate tensors 146 src.allocator()->allocate(); 147 dst.allocator()->allocate(); 148 ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS); 149 ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS); 150 151 // Fill tensors 152 fill(AccessorType(src)); 153 154 // Compute function 155 scale.run(); 156 157 return dst; 158 } 159 compute_reference(const TensorShape & shape)160 SimpleTensor<T> compute_reference(const TensorShape &shape) 161 { 162 // Create reference 163 SimpleTensor<T> src{ shape, _data_type, 1, _quantization_info }; 164 165 // Fill reference 166 fill(src); 167 168 return reference::scale<T>(src, _scale_x, _scale_y, _policy, _border_mode, _constant_border_value, _sampling_policy, /* ceil_policy_scale */ false, _align_corners); 169 } 170 171 TensorType _target{}; 172 SimpleTensor<T> _reference{}; 173 TensorShape _shape{}; 174 InterpolationPolicy _policy{}; 175 BorderMode _border_mode{}; 176 T _constant_border_value{}; 177 SamplingPolicy _sampling_policy{}; 178 DataType _data_type{}; 179 QuantizationInfo _quantization_info{}; 180 bool _align_corners{ false }; 181 float _scale_x{ 1.f }; 182 float _scale_y{ 1.f }; 183 }; 184 185 template <typename TensorType, typename AccessorType, typename FunctionType, typename T> 186 class ScaleValidationQuantizedFixture : public ScaleValidationGenericFixture<TensorType, AccessorType, FunctionType, T> 187 { 188 public: 189 template <typename...> setup(TensorShape shape,DataType data_type,QuantizationInfo quantization_info,DataLayout data_layout,InterpolationPolicy policy,BorderMode border_mode,SamplingPolicy sampling_policy,bool align_corners)190 void setup(TensorShape shape, DataType data_type, QuantizationInfo quantization_info, DataLayout data_layout, InterpolationPolicy policy, BorderMode border_mode, SamplingPolicy sampling_policy, 191 bool align_corners) 192 { 193 ScaleValidationGenericFixture<TensorType, AccessorType, FunctionType, T>::setup(shape, 194 data_type, 195 quantization_info, 196 data_layout, 197 policy, 198 border_mode, 199 sampling_policy, 200 align_corners); 201 } 202 }; 203 template <typename TensorType, typename AccessorType, typename FunctionType, typename T> 204 class ScaleValidationFixture : public ScaleValidationGenericFixture<TensorType, AccessorType, FunctionType, T> 205 { 206 public: 207 template <typename...> setup(TensorShape shape,DataType data_type,DataLayout data_layout,InterpolationPolicy policy,BorderMode border_mode,SamplingPolicy sampling_policy,bool align_corners)208 void setup(TensorShape shape, DataType data_type, DataLayout data_layout, InterpolationPolicy policy, BorderMode border_mode, SamplingPolicy sampling_policy, bool align_corners) 209 { 210 ScaleValidationGenericFixture<TensorType, AccessorType, FunctionType, T>::setup(shape, 211 data_type, 212 QuantizationInfo(), 213 data_layout, 214 policy, 215 border_mode, 216 sampling_policy, 217 align_corners); 218 } 219 }; 220 } // namespace validation 221 } // namespace test 222 } // namespace arm_compute 223 #endif /* ARM_COMPUTE_TEST_SCALE_FIXTURE */ 224