blob: fd61c72f223d8e7812e40d67c5db744af5731bff [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
2 * Copyright (c) 2017 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#include "Globals.h"
25#include "NEON/Helper.h"
26#include "NEON/NEAccessor.h"
Moritz Pflanzer5b512292017-06-21 15:54:07 +010027#include "PaddingCalculator.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010028#include "TensorLibrary.h"
29#include "TypePrinter.h"
30#include "Utils.h"
31#include "validation/Datasets.h"
32#include "validation/Reference.h"
33#include "validation/Validation.h"
34
35#include "arm_compute/core/Helpers.h"
36#include "arm_compute/core/Types.h"
37#include "arm_compute/runtime/NEON/functions/NEPixelWiseMultiplication.h"
38#include "arm_compute/runtime/Tensor.h"
39#include "arm_compute/runtime/TensorAllocator.h"
40
41#include "boost_wrapper.h"
42
43#include <random>
44#include <string>
45
46using namespace arm_compute;
47using namespace arm_compute::test;
48using namespace arm_compute::test::neon;
49using namespace arm_compute::test::validation;
50
51namespace
52{
53/** Compute Neon arithmetic addition function.
54 *
55 * @param[in] shape Shape of the input and output tensors.
56 * @param[in] dt_in0 Data type of first input tensor.
57 * @param[in] dt_in1 Data type of second input tensor.
58 * @param[in] dt_out Data type of the output tensor.
59 * @param[in] scale Non-negative scale.
60 * @param[in] convert_policy Overflow policy of the operation.
61 * @param[in] rounding_policy Rounding policy of the operation.
62 * @param[in] fixed_point_position Fixed point position that expresses the number of bits for the fractional part of the number.
63 *
64 * @return Computed output tensor.
65 */
66Tensor compute_pixel_wise_multiplication(const TensorShape &shape, DataType dt_in0, DataType dt_in1, DataType dt_out, float scale, ConvertPolicy convert_policy, RoundingPolicy rounding_policy,
67 int fixed_point_position = 0)
68{
69 // Create tensors
70 Tensor src1 = create_tensor(shape, dt_in0, 1, fixed_point_position);
71 Tensor src2 = create_tensor(shape, dt_in1, 1, fixed_point_position);
72 Tensor dst = create_tensor(shape, dt_out, 1, fixed_point_position);
73
74 // Create and configure function
75 NEPixelWiseMultiplication multiply;
76 multiply.configure(&src1, &src2, &dst, scale, convert_policy, rounding_policy);
77
78 // Allocate tensors
79 src1.allocator()->allocate();
80 src2.allocator()->allocate();
81 dst.allocator()->allocate();
82
83 BOOST_TEST(!src1.info()->is_resizable());
84 BOOST_TEST(!src2.info()->is_resizable());
85 BOOST_TEST(!dst.info()->is_resizable());
86
87 // Fill tensors
88 library->fill_tensor_uniform(NEAccessor(src1), 0);
89 library->fill_tensor_uniform(NEAccessor(src2), 1);
90
91 // Compute function
92 multiply.run();
93
94 return dst;
95}
96
97void validate_configuration(const Tensor &src1, const Tensor &src2, Tensor &dst, TensorShape shape, float scale, ConvertPolicy convert_policy, RoundingPolicy rounding_policy)
98{
99 BOOST_TEST(src1.info()->is_resizable());
100 BOOST_TEST(src2.info()->is_resizable());
101 BOOST_TEST(dst.info()->is_resizable());
102
103 // Create and configure function
104 NEPixelWiseMultiplication multiply;
105 multiply.configure(&src1, &src2, &dst, scale, convert_policy, rounding_policy);
106
107 // Validate valid region
108 const ValidRegion valid_region = shape_to_valid_region(shape);
109 validate(src1.info()->valid_region(), valid_region);
110 validate(src2.info()->valid_region(), valid_region);
111 validate(dst.info()->valid_region(), valid_region);
112
113 // Validate padding
Moritz Pflanzer2509fba2017-06-23 14:15:03 +0100114 const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding();
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100115 validate(src1.info()->padding(), padding);
116 validate(src2.info()->padding(), padding);
117 validate(dst.info()->padding(), padding);
118}
119} // namespace
120
121#ifndef DOXYGEN_SKIP_THIS
122BOOST_AUTO_TEST_SUITE(NEON)
123BOOST_AUTO_TEST_SUITE(PixelWiseMultiplication)
124
125BOOST_AUTO_TEST_SUITE(U8)
126
127BOOST_AUTO_TEST_SUITE(Scale255)
128BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly"))
129BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * (1.f / 255.f) * ConvertPolicies()
130 * RoundingPolicy::TO_NEAREST_UP,
131 shape, scale, convert_policy, rounding_policy)
132{
133 // Create tensors
134 Tensor src1 = create_tensor(shape, DataType::U8);
135 Tensor src2 = create_tensor(shape, DataType::U8);
136 Tensor dst = create_tensor(shape, DataType::U8);
137
138 validate_configuration(src1, src2, dst, shape, scale, convert_policy, rounding_policy);
139}
140
141BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit"))
142BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * (1.f / 255.f) * ConvertPolicies() * RoundingPolicy::TO_NEAREST_UP,
143 shape, scale, convert_policy, rounding_policy)
144{
145 // Compute function
146 Tensor dst = compute_pixel_wise_multiplication(shape, DataType::U8, DataType::U8, DataType::U8, scale, convert_policy,
147 rounding_policy);
148
149 // Compute reference
150 RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, DataType::U8, DataType::U8,
151 DataType::U8, scale, convert_policy, rounding_policy);
152
153 // Validate output
154 // Allow tolerance value of 1.f to counteract imprecision due to 32-bit float conversion
155 validate(NEAccessor(dst), ref_dst, 1.f, 0.f, std::numeric_limits<uint8_t>::max());
156}
157BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly"))
158BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * (1.f / 255.f) * ConvertPolicies() * RoundingPolicy::TO_NEAREST_UP,
159 shape, scale, convert_policy, rounding_policy)
160{
161 // Compute function
162 Tensor dst = compute_pixel_wise_multiplication(shape, DataType::U8, DataType::U8, DataType::U8, scale, convert_policy,
163 rounding_policy);
164
165 // Compute reference
166 RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, DataType::U8, DataType::U8,
167 DataType::U8, scale, convert_policy, rounding_policy);
168
169 // Validate output
170 // Allow tolerance value of 1.f to counteract imprecision due to 32-bit float conversion
171 validate(NEAccessor(dst), ref_dst, 1.f, 0.f, std::numeric_limits<uint8_t>::max());
172}
173BOOST_AUTO_TEST_SUITE_END()
174
175BOOST_AUTO_TEST_SUITE(ScaleOther)
176BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly"))
177BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ 1.f, 1.f / 32768.f })
178 * ConvertPolicies()
179 * RoundingPolicy::TO_ZERO,
180 shape, scale, convert_policy, rounding_policy)
181{
182 // Create tensors
183 Tensor src1 = create_tensor(shape, DataType::U8);
184 Tensor src2 = create_tensor(shape, DataType::U8);
185 Tensor dst = create_tensor(shape, DataType::U8);
186
187 validate_configuration(src1, src2, dst, shape, scale, convert_policy, rounding_policy);
188}
189
190BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit"))
191BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ 1.f, 1.f / 32768.f }) * ConvertPolicies()
192 * RoundingPolicy::TO_ZERO,
193 shape, scale, convert_policy, rounding_policy)
194{
195 // Compute function
196 Tensor dst = compute_pixel_wise_multiplication(shape, DataType::U8, DataType::U8, DataType::U8, scale, convert_policy,
197 rounding_policy);
198
199 // Compute reference
200 RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, DataType::U8, DataType::U8,
201 DataType::U8, scale, convert_policy, rounding_policy);
202
203 // Validate output
204 validate(NEAccessor(dst), ref_dst);
205}
206BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly"))
207BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ 1.f, 1.f / 32768.f }) * ConvertPolicies()
208 * RoundingPolicy::TO_ZERO,
209 shape, scale, convert_policy, rounding_policy)
210{
211 // Compute function
212 Tensor dst = compute_pixel_wise_multiplication(shape, DataType::U8, DataType::U8, DataType::U8, scale, convert_policy,
213 rounding_policy);
214
215 // Compute reference
216 RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, DataType::U8, DataType::U8,
217 DataType::U8, scale, convert_policy, rounding_policy);
218
219 // Validate output
220 validate(NEAccessor(dst), ref_dst);
221}
222BOOST_AUTO_TEST_SUITE_END()
223BOOST_AUTO_TEST_SUITE_END()
224
225BOOST_AUTO_TEST_SUITE(S16)
226BOOST_AUTO_TEST_SUITE(Scale255)
227BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly"))
228BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * (1.f / 255.f) * ConvertPolicies()
229 * RoundingPolicy::TO_NEAREST_UP,
230 shape, dt, scale, convert_policy, rounding_policy)
231{
232 // Create tensors
233 Tensor src1 = create_tensor(shape, dt);
234 Tensor src2 = create_tensor(shape, DataType::S16);
235 Tensor dst = create_tensor(shape, DataType::S16);
236
237 validate_configuration(src1, src2, dst, shape, scale, convert_policy, rounding_policy);
238}
239BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit"))
240BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * (1.f / 255.f) * ConvertPolicies()
241 * RoundingPolicy::TO_NEAREST_UP,
242 shape, dt, scale, convert_policy, rounding_policy)
243{
244 // Compute function
245 Tensor dst = compute_pixel_wise_multiplication(shape, dt, DataType::S16, DataType::S16, scale, convert_policy, rounding_policy);
246
247 // Compute reference
248 RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, dt, DataType::S16, DataType::S16, scale, convert_policy, rounding_policy);
249
250 // Validate output
251 // Allow tolerance value of 2.f to counteract imprecision due to 32-bit float conversion
252 validate(NEAccessor(dst), ref_dst, 2.f, 0.f, std::numeric_limits<int16_t>::max());
253}
254BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly"))
255BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * (1.f / 255.f) * ConvertPolicies()
256 * RoundingPolicy::TO_NEAREST_UP,
257 shape, dt, scale, convert_policy, rounding_policy)
258{
259 // Compute function
260 Tensor dst = compute_pixel_wise_multiplication(shape, dt, DataType::S16, DataType::S16, scale, convert_policy, rounding_policy);
261
262 // Compute reference
263 RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, dt, DataType::S16, DataType::S16,
264 scale, convert_policy, rounding_policy);
265
266 // Validate output
267 // Allow tolerance value of 2.f to counteract imprecision due to 32-bit float conversion
268 validate(NEAccessor(dst), ref_dst, 2.f, 0.f, std::numeric_limits<int16_t>::max());
269}
270BOOST_AUTO_TEST_SUITE_END()
271
272BOOST_AUTO_TEST_SUITE(ScaleOther)
273BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly"))
274BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * boost::unit_test::data::make({ 1.f, 1.f / 32768.f })
275 * ConvertPolicies()
276 * RoundingPolicy::TO_ZERO,
277 shape, dt, scale, convert_policy, rounding_policy)
278{
279 // Create tensors
280 Tensor src1 = create_tensor(shape, dt);
281 Tensor src2 = create_tensor(shape, DataType::S16);
282 Tensor dst = create_tensor(shape, DataType::S16);
283
284 validate_configuration(src1, src2, dst, shape, scale, convert_policy, rounding_policy);
285}
286BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit"))
287BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * boost::unit_test::data::make({ 1.f, 1.f / 32768.f }) * ConvertPolicies()
288 * RoundingPolicy::TO_ZERO,
289 shape, dt, scale, convert_policy, rounding_policy)
290{
291 // Compute function
292 Tensor dst = compute_pixel_wise_multiplication(shape, dt, DataType::S16, DataType::S16, scale, convert_policy, rounding_policy);
293
294 // Compute reference
295 RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, dt, DataType::S16, DataType::S16, scale, convert_policy, rounding_policy);
296
297 // Validate output
298 validate(NEAccessor(dst), ref_dst);
299}
300BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly"))
301BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * boost::unit_test::data::make({ 1.f, 1.f / 32768.f }) * ConvertPolicies()
302 * RoundingPolicy::TO_ZERO,
303 shape, dt, scale, convert_policy, rounding_policy)
304{
305 // Compute function
306 Tensor dst = compute_pixel_wise_multiplication(shape, dt, DataType::S16, DataType::S16, scale, convert_policy, rounding_policy);
307
308 // Compute reference
309 RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, dt, DataType::S16, DataType::S16,
310 scale, convert_policy, rounding_policy);
311
312 // Validate output
313 validate(NEAccessor(dst), ref_dst);
314}
315BOOST_AUTO_TEST_SUITE_END()
316BOOST_AUTO_TEST_SUITE_END()
317
318BOOST_AUTO_TEST_SUITE(F32)
319BOOST_AUTO_TEST_SUITE(Scale255)
320BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly"))
321BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * (1.f / 255.f) * ConvertPolicies()
322 * RoundingPolicy::TO_NEAREST_UP,
323 shape, scale, convert_policy, rounding_policy)
324{
325 // Create tensors
326 Tensor src1 = create_tensor(shape, DataType::F32);
327 Tensor src2 = create_tensor(shape, DataType::F32);
328 Tensor dst = create_tensor(shape, DataType::F32);
329
330 validate_configuration(src1, src2, dst, shape, scale, convert_policy, rounding_policy);
331}
332BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit"))
333BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * (1.f / 255.f) * ConvertPolicies()
334 * RoundingPolicy::TO_NEAREST_UP,
335 shape, scale, convert_policy, rounding_policy)
336{
337 // Compute function
338 Tensor dst = compute_pixel_wise_multiplication(shape, DataType::F32, DataType::F32, DataType::F32, scale, convert_policy, rounding_policy);
339
340 // Compute reference
341 RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, DataType::F32, DataType::F32, DataType::F32, scale, convert_policy, rounding_policy);
342
343 // Validate output
344 // Allow tolerance value of 1.f to counteract imprecision due to 32-bit float conversion
345 validate(NEAccessor(dst), ref_dst, 1.f, 0.f, std::numeric_limits<int16_t>::max());
346}
347BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly"))
348BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * (1.f / 255.f) * ConvertPolicies()
349 * RoundingPolicy::TO_NEAREST_UP,
350 shape, scale, convert_policy, rounding_policy)
351{
352 // Compute function
353 Tensor dst = compute_pixel_wise_multiplication(shape, DataType::F32, DataType::F32, DataType::F32, scale, convert_policy, rounding_policy);
354
355 // Compute reference
356 RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, DataType::F32, DataType::F32, DataType::F32,
357 scale, convert_policy, rounding_policy);
358
359 // Validate output
360 // Allow tolerance value of 1.f to counteract imprecision due to 32-bit float conversion
361 validate(NEAccessor(dst), ref_dst, 1.f, 0.f, std::numeric_limits<int16_t>::max());
362}
363BOOST_AUTO_TEST_SUITE_END()
364
365BOOST_AUTO_TEST_SUITE(ScaleOther)
366BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly"))
367BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ 1.f, 1.f / 32768.f })
368 * ConvertPolicies()
369 * RoundingPolicy::TO_ZERO,
370 shape, scale, convert_policy, rounding_policy)
371{
372 // Create tensors
373 Tensor src1 = create_tensor(shape, DataType::F32);
374 Tensor src2 = create_tensor(shape, DataType::F32);
375 Tensor dst = create_tensor(shape, DataType::F32);
376
377 validate_configuration(src1, src2, dst, shape, scale, convert_policy, rounding_policy);
378}
379BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit"))
380BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ 1.f, 1.f / 32768.f }) * ConvertPolicies()
381 * RoundingPolicy::TO_ZERO,
382 shape, scale, convert_policy, rounding_policy)
383{
384 // Compute function
385 Tensor dst = compute_pixel_wise_multiplication(shape, DataType::F32, DataType::F32, DataType::F32, scale, convert_policy, rounding_policy);
386
387 // Compute reference
388 RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, DataType::F32, DataType::F32, DataType::F32, scale, convert_policy, rounding_policy);
389
390 // Validate output
391 validate(NEAccessor(dst), ref_dst);
392}
393BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly"))
394BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ 1.f, 1.f / 32768.f }) * ConvertPolicies()
395 * RoundingPolicy::TO_ZERO,
396 shape, scale, convert_policy, rounding_policy)
397{
398 // Compute function
399 Tensor dst = compute_pixel_wise_multiplication(shape, DataType::F32, DataType::F32, DataType::F32, scale, convert_policy, rounding_policy);
400
401 // Compute reference
402 RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, DataType::F32, DataType::F32, DataType::F32,
403 scale, convert_policy, rounding_policy);
404
405 // Validate output
406 validate(NEAccessor(dst), ref_dst);
407}
408BOOST_AUTO_TEST_SUITE_END()
409BOOST_AUTO_TEST_SUITE_END()
410
411BOOST_AUTO_TEST_SUITE(QS8)
412BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit"))
413BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * DataType::QS8 *ConvertPolicies() * RoundingPolicy::TO_ZERO * boost::unit_test::data::xrange<int>(1, 7),
414 shape, dt, convert_policy, rounding_policy, fixed_point_position)
415{
416 // Compute function
417 Tensor dst = compute_pixel_wise_multiplication(shape, dt, dt, dt, 1.f, convert_policy, rounding_policy, fixed_point_position);
418
419 // Compute reference
420 RawTensor ref_dst = Reference::compute_reference_fixed_point_pixel_wise_multiplication(shape, dt, dt, dt, 1.f, fixed_point_position, convert_policy, rounding_policy);
421
422 // Validate output
423 validate(NEAccessor(dst), ref_dst);
424}
425BOOST_AUTO_TEST_SUITE_END()
426
427BOOST_AUTO_TEST_SUITE_END()
428BOOST_AUTO_TEST_SUITE_END()
429#endif