blob: b250465e14f347da2dd47db35edf2f74055c706b [file] [log] [blame]
giuros0192fd9432018-12-03 17:30:00 +00001/*
Sang-Hoon Park5db75c32021-01-07 16:59:32 +00002 * Copyright (c) 2018-2021 Arm Limited.
giuros0192fd9432018-12-03 17:30:00 +00003 *
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 */
Michalis Spyrouebcebf12020-10-21 00:04:14 +010024#include "src/core/NEON/kernels/NEElementwiseOperationKernel.h"
giuros0192fd9432018-12-03 17:30:00 +000025
giuros0192fd9432018-12-03 17:30:00 +000026#include "arm_compute/core/Helpers.h"
27#include "arm_compute/core/IAccessWindow.h"
Sang-Hoon Park68dd25f2020-10-19 16:00:11 +010028#include "src/core/CPP/Validate.h"
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000029#include "src/core/NEON/kernels/elementwise/impl/elementwise_list.h"
30#include "src/core/NEON/kernels/elementwise/impl/elementwise_quantized_list.h"
Sang-Hoon Park5db75c32021-01-07 16:59:32 +000031#include "src/core/SVE/kernels/elementwise/impl/elementwise_list.h"
Sang-Hoon Parkd23a2512021-01-11 22:19:49 +000032#include "src/core/SVE/kernels/elementwise/impl/elementwise_quantized_list.h"
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000033#include "src/core/common/Registrars.h"
Sang-Hoon Park68dd25f2020-10-19 16:00:11 +010034#include "src/core/helpers/AutoConfiguration.h"
35#include "src/core/helpers/WindowHelpers.h"
giuros0192fd9432018-12-03 17:30:00 +000036
giuros0192fd9432018-12-03 17:30:00 +000037#include <arm_neon.h>
giuros0192fd9432018-12-03 17:30:00 +000038
39namespace arm_compute
40{
giuros0192fd9432018-12-03 17:30:00 +000041namespace
42{
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000043using ElementwiseSelector = std::add_pointer<bool(DataType)>::type;
44using UKernelType = NEElementwiseOperationKernel::ElementwiseFunction;
45struct ElementwiseKernel
giuros0192fd9432018-12-03 17:30:00 +000046{
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000047 const char *name;
48 const ElementwiseSelector is_selected;
49 UKernelType *ukernel;
50};
51
52template <DataType dt>
53inline bool is_selected(DataType data_type)
54{
55 return dt == data_type;
giuros0192fd9432018-12-03 17:30:00 +000056}
57
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000058template <DataType input_data_type, DataType output_data_type = input_data_type>
59static ElementwiseKernel generate_kernel(UKernelType *ukernel)
Michalis Spyrou8d4d1b82019-11-28 11:31:23 +000060{
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000061 std::string kernel_name("op_");
62 kernel_name += string_from_data_type(input_data_type) + "_";
63 kernel_name += string_from_data_type(input_data_type) + "_";
64 kernel_name += string_from_data_type(output_data_type);
Michalis Spyrou8d4d1b82019-11-28 11:31:23 +000065
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000066 return { kernel_name.c_str(), is_selected<input_data_type>, ukernel };
George Wortd88590f2018-12-12 17:39:58 +000067}
68
69template <ArithmeticOperation op>
70std::function<void(const ITensor *, const ITensor *, ITensor *, const Window &)>
Michalis Spyrouce0c6752020-06-18 10:14:57 +010071configure_arithm_func(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output)
George Wortd88590f2018-12-12 17:39:58 +000072{
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000073 ARM_COMPUTE_UNUSED(input2, output);
74 static ElementwiseKernel kernels[] =
George Wortd88590f2018-12-12 17:39:58 +000075 {
Sang-Hoon Park5db75c32021-01-07 16:59:32 +000076#if defined(__ARM_FEATURE_SVE)
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000077 generate_kernel<DataType::F32>(REGISTER_FP32_SVE((arm_compute::cpu::sve::elementwise_arithmetic_op<op, float32_t>))),
78 generate_kernel<DataType::S32>(REGISTER_INTEGER_SVE((arm_compute::cpu::sve::elementwise_arithmetic_op<op, int32_t>))),
Sang-Hoon Park5db75c32021-01-07 16:59:32 +000079#else /* defined(__ARM_FEATURE_SVE) */
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000080 generate_kernel<DataType::F32>(REGISTER_FP32_NEON((arm_compute::cpu::elementwise_arithm_op<op, typename wrapper::traits::neon_vector<float, 4>>))),
81 generate_kernel<DataType::S32>(REGISTER_INTEGER_NEON((arm_compute::cpu::elementwise_arithm_op<op, typename wrapper::traits::neon_vector<int32_t, 4>>))),
Sang-Hoon Park5db75c32021-01-07 16:59:32 +000082#endif /* defined(__ARM_FEATURE_SVE) */
Sang-Hoon Parkd23a2512021-01-11 22:19:49 +000083#if defined(__ARM_FEATURE_SVE2)
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000084 generate_kernel<DataType::QASYMM8>(REGISTER_QASYMM8_SVE((arm_compute::cpu::sve::elementwise_arithmetic_quantized_op<op, uint8_t>))),
85 generate_kernel<DataType::QASYMM8_SIGNED>(REGISTER_QASYMM8_SIGNED_SVE((arm_compute::cpu::sve::elementwise_arithmetic_quantized_op<op, int8_t>))),
Sang-Hoon Parkd23a2512021-01-11 22:19:49 +000086#else /* defined(__ARM_FEATURE_SVE2) */
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000087 generate_kernel<DataType::QASYMM8>(REGISTER_QASYMM8_NEON((arm_compute::cpu::elementwise_arithm_op_quantized<op>))),
88 generate_kernel<DataType::QASYMM8_SIGNED>(REGISTER_QASYMM8_SIGNED_NEON((arm_compute::cpu::elementwise_arithm_op_quantized_signed<op>))),
Sang-Hoon Parkd23a2512021-01-11 22:19:49 +000089#endif /* defined(__ARM_FEATURE_SVE2) */
George Wortd88590f2018-12-12 17:39:58 +000090#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
Sang-Hoon Park5db75c32021-01-07 16:59:32 +000091#if defined(__ARM_FEATURE_SVE)
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000092 generate_kernel<DataType::F16>(REGISTER_FP16_SVE((arm_compute::cpu::sve::elementwise_arithmetic_op<op, float16_t>))),
Sang-Hoon Park5db75c32021-01-07 16:59:32 +000093#else /* defined(__ARM_FEATURE_SVE) */
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000094 generate_kernel<DataType::F16>(REGISTER_FP16_NEON((arm_compute::cpu::elementwise_arithm_op<op, typename wrapper::traits::neon_vector<float16_t, 8>>))),
Sang-Hoon Park5db75c32021-01-07 16:59:32 +000095#endif /* defined(__ARM_FEATURE_SVE) */
George Wortd88590f2018-12-12 17:39:58 +000096#endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000097 generate_kernel<DataType::S16>(REGISTER_INTEGER_NEON((arm_compute::cpu::elementwise_arithm_op<op, typename wrapper::traits::neon_vector<int16_t, 8>>))),
98 };
George Wortd88590f2018-12-12 17:39:58 +000099
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000100 for(const auto &uk : kernels)
101 {
102 if(uk.is_selected(input1->data_type()))
103 {
104 return uk.ukernel;
105 }
106 }
107
108 return nullptr;
George Wortd88590f2018-12-12 17:39:58 +0000109}
110
111template <ComparisonOperation op>
112std::function<void(const ITensor *input1, const ITensor *input2, ITensor *output, const Window &window)>
Michalis Spyrouce0c6752020-06-18 10:14:57 +0100113configure_comp_func(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output)
George Wortd88590f2018-12-12 17:39:58 +0000114{
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000115 ARM_COMPUTE_UNUSED(input2, output);
116 static ElementwiseKernel kernels[] =
George Wortd88590f2018-12-12 17:39:58 +0000117 {
Sang-Hoon Park5db75c32021-01-07 16:59:32 +0000118#if defined(__ARM_FEATURE_SVE)
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000119 generate_kernel<DataType::U8, DataType::U8>(REGISTER_INTEGER_SVE((arm_compute::cpu::sve::elementwise_comparison_op<op, uint8_t>))),
120 generate_kernel<DataType::F32, DataType::U8>(REGISTER_FP32_SVE((arm_compute::cpu::sve::elementwise_comparison_op<op, float>))),
121 generate_kernel<DataType::S16, DataType::U8>(REGISTER_INTEGER_SVE((arm_compute::cpu::sve::elementwise_comparison_op<op, int16_t>))),
122 generate_kernel<DataType::S32, DataType::U8>(REGISTER_INTEGER_SVE((arm_compute::cpu::sve::elementwise_comparison_op<op, int32_t>))),
Sang-Hoon Park5db75c32021-01-07 16:59:32 +0000123#else /* defined(__ARM_FEATURE_SVE) */
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000124 generate_kernel<DataType::U8, DataType::U8>(REGISTER_INTEGER_NEON((arm_compute::cpu::elementwise_comp_op_8<op, uint8_t, uint8x16_t>))),
125 generate_kernel<DataType::F32, DataType::U8>(REGISTER_FP32_NEON((arm_compute::cpu::elementwise_comp_op_32<op, float, float32x4_t>))),
126 generate_kernel<DataType::S16, DataType::U8>(REGISTER_INTEGER_NEON((arm_compute::cpu::elementwise_comp_op_16<op, int16_t, int16x8_t>))),
127 generate_kernel<DataType::S32, DataType::U8>(REGISTER_INTEGER_NEON((arm_compute::cpu::elementwise_comp_op_32<op, int32_t, int32x4_t>))),
Sang-Hoon Park5db75c32021-01-07 16:59:32 +0000128#endif /* defined(__ARM_FEATURE_SVE) */
Sang-Hoon Parkd23a2512021-01-11 22:19:49 +0000129#if defined(__ARM_FEATURE_SVE2)
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000130 generate_kernel<DataType::QASYMM8_SIGNED, DataType::U8>(REGISTER_QASYMM8_SIGNED_SVE((arm_compute::cpu::sve::elementwise_comparison_quantized_op<op, int8_t>))),
131 generate_kernel<DataType::QASYMM8, DataType::U8>(REGISTER_QASYMM8_SVE((arm_compute::cpu::sve::elementwise_comparison_quantized_op<op, uint8_t>))),
Sang-Hoon Parkd23a2512021-01-11 22:19:49 +0000132#else /* defined(__ARM_FEATURE_SVE2) */
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000133 generate_kernel<DataType::QASYMM8_SIGNED, DataType::U8>(REGISTER_QASYMM8_SIGNED_NEON((arm_compute::cpu::elementwise_comp_op_quantized_signed<op>))),
134 generate_kernel<DataType::QASYMM8, DataType::U8>(REGISTER_QASYMM8_NEON((arm_compute::cpu::elementwise_comp_op_quantized<op>))),
Sang-Hoon Parkd23a2512021-01-11 22:19:49 +0000135#endif /* defined(__ARM_FEATURE_SVE2) */
George Wortd88590f2018-12-12 17:39:58 +0000136#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
Sang-Hoon Park5db75c32021-01-07 16:59:32 +0000137#if defined(__ARM_FEATURE_SVE)
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000138 generate_kernel<DataType::F16, DataType::U8>(REGISTER_FP16_SVE((arm_compute::cpu::sve::elementwise_comparison_op<op, float16_t>))),
Sang-Hoon Park5db75c32021-01-07 16:59:32 +0000139#else /* defined(__ARM_FEATURE_SVE) */
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000140 generate_kernel<DataType::F16, DataType::U8>(REGISTER_FP16_NEON((arm_compute::cpu::elementwise_comp_op_16<op, float16_t, float16x8_t>))),
Sang-Hoon Park5db75c32021-01-07 16:59:32 +0000141#endif /* defined(__ARM_FEATURE_SVE) */
George Wortd88590f2018-12-12 17:39:58 +0000142#endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000143 };
George Wortd88590f2018-12-12 17:39:58 +0000144
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000145 for(const auto &uk : kernels)
146 {
147 if(uk.is_selected(input1->data_type()))
148 {
149 return uk.ukernel;
150 }
151 }
152
153 return nullptr;
George Wortd88590f2018-12-12 17:39:58 +0000154}
155} // namespace
156
157NEElementwiseOperationKernel::NEElementwiseOperationKernel()
158 : _function(nullptr), _input1(nullptr), _input2(nullptr), _output(nullptr)
159{
160}
161
162Status NEElementwiseOperationKernel::validate_arguments_common(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output)
163{
George Wortd88590f2018-12-12 17:39:58 +0000164 ARM_COMPUTE_RETURN_ERROR_ON_CPU_F16_UNSUPPORTED(&input1);
giuros0192fd9432018-12-03 17:30:00 +0000165 ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(&input1, &input2);
166
167 const TensorShape out_shape = TensorShape::broadcast_shape(input1.tensor_shape(), input2.tensor_shape());
168
169 ARM_COMPUTE_RETURN_ERROR_ON_MSG(out_shape.total_size() == 0, "Inputs are not broadcast compatible");
170
171 // Validate in case of configured output
172 if(output.total_size() > 0)
173 {
giuros0192fd9432018-12-03 17:30:00 +0000174 ARM_COMPUTE_RETURN_ERROR_ON_MSG(detail::have_different_dimensions(out_shape, output.tensor_shape(), 0),
175 "Wrong shape for output");
176 }
177
178 return Status{};
179}
giuros0192fd9432018-12-03 17:30:00 +0000180
Michalis Spyrouce0c6752020-06-18 10:14:57 +0100181void NEElementwiseOperationKernel::configure_common(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output)
giuros0192fd9432018-12-03 17:30:00 +0000182{
183 ARM_COMPUTE_ERROR_ON_NULLPTR(input1, input2, output);
giuros0192fd9432018-12-03 17:30:00 +0000184
185 // Configure kernel window
Michalis Spyrouce0c6752020-06-18 10:14:57 +0100186 const std::pair<TensorShape, ValidRegion> broadcast_pair = ITensorInfo::broadcast_shape_and_valid_region(*input1, *input2);
giuros0192fd9432018-12-03 17:30:00 +0000187 const TensorShape &out_shape = broadcast_pair.first;
188 const ValidRegion &valid_region = broadcast_pair.second;
189
190 // Auto initialize output if not initialized
Michalis Spyrouce0c6752020-06-18 10:14:57 +0100191 auto_init_if_empty(*output, out_shape, 1, input1->data_type());
giuros0192fd9432018-12-03 17:30:00 +0000192
193 Window win = calculate_max_window(valid_region);
194
giuros0192fd9432018-12-03 17:30:00 +0000195 INEKernel::configure(win);
196}
197
Georgios Pinitas0499dff2020-07-31 22:21:38 +0100198void NEElementwiseOperationKernel::run_op(ITensorPack &tensors, const Window &window, const ThreadInfo &info)
giuros0192fd9432018-12-03 17:30:00 +0000199{
George Wortd88590f2018-12-12 17:39:58 +0000200 ARM_COMPUTE_UNUSED(info, window);
giuros0192fd9432018-12-03 17:30:00 +0000201 ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this);
202 ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(INEKernel::window(), window);
George Wortd88590f2018-12-12 17:39:58 +0000203 ARM_COMPUTE_ERROR_ON(_function == nullptr);
Georgios Pinitas0499dff2020-07-31 22:21:38 +0100204 _function(tensors.get_const_tensor(TensorType::ACL_SRC_0),
205 tensors.get_const_tensor(TensorType::ACL_SRC_1),
206 tensors.get_tensor(TensorType::ACL_DST), window);
giuros0192fd9432018-12-03 17:30:00 +0000207}
208
209/** Arithmetic operators (min, max, squared_diff) */
Michalis Spyrouce0c6752020-06-18 10:14:57 +0100210void NEArithmeticOperationKernel::configure(ArithmeticOperation op, const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output)
giuros0192fd9432018-12-03 17:30:00 +0000211{
Michalis Spyrouce0c6752020-06-18 10:14:57 +0100212 ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(*input1, *input2, *output));
George Wortd88590f2018-12-12 17:39:58 +0000213 configure_common(input1, input2, output);
giuros0192fd9432018-12-03 17:30:00 +0000214 switch(op)
215 {
216 case ArithmeticOperation::MAX:
George Wortd88590f2018-12-12 17:39:58 +0000217 _function = configure_arithm_func<ArithmeticOperation::MAX>(input1, input2, output);
giuros0192fd9432018-12-03 17:30:00 +0000218 break;
219 case ArithmeticOperation::MIN:
George Wortd88590f2018-12-12 17:39:58 +0000220 _function = configure_arithm_func<ArithmeticOperation::MIN>(input1, input2, output);
giuros0192fd9432018-12-03 17:30:00 +0000221 break;
222 case ArithmeticOperation::SQUARED_DIFF:
George Wortd88590f2018-12-12 17:39:58 +0000223 _function = configure_arithm_func<ArithmeticOperation::SQUARED_DIFF>(input1, input2, output);
giuros0192fd9432018-12-03 17:30:00 +0000224 break;
giuros01d5134362019-05-14 16:12:53 +0100225 case ArithmeticOperation::PRELU:
226 _function = configure_arithm_func<ArithmeticOperation::PRELU>(input1, input2, output);
227 break;
giuros0192fd9432018-12-03 17:30:00 +0000228 default:
229 ARM_COMPUTE_ERROR("NOT_SUPPORTED!");
230 }
231}
232
George Wortd88590f2018-12-12 17:39:58 +0000233Status NEArithmeticOperationKernel::validate_arguments(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output)
234{
Michele Di Giorgio1c76c1d2020-08-28 13:25:31 +0100235 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&input1, 1, DataType::QASYMM8, DataType::QASYMM8_SIGNED, DataType::S16, DataType::F16, DataType::S32, DataType::F32);
George Wortd88590f2018-12-12 17:39:58 +0000236 // Validate in case of configured output
237 if(output.total_size() > 0)
238 {
239 ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(&input1, &output);
240 }
241 return validate_arguments_common(input1, input2, output);
242}
243
giuros0192fd9432018-12-03 17:30:00 +0000244Status NEArithmeticOperationKernel::validate(ArithmeticOperation op, const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output)
245{
246 ARM_COMPUTE_UNUSED(op);
247 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input1, input2, output);
George Wortd88590f2018-12-12 17:39:58 +0000248 ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(*input1, *input2, *output));
giuros0192fd9432018-12-03 17:30:00 +0000249 return Status{};
250}
251
George Worta1e7e282019-01-15 11:00:29 +0000252/** The division operator */
253
Michalis Spyrouce0c6752020-06-18 10:14:57 +0100254void NEDivisionOperationKernel::configure(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output)
George Worta1e7e282019-01-15 11:00:29 +0000255{
Michalis Spyrouce0c6752020-06-18 10:14:57 +0100256 ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(*input1, *input2, *output));
George Worta1e7e282019-01-15 11:00:29 +0000257 configure_common(input1, input2, output);
258 _function = configure_arithm_func<ArithmeticOperation::DIV>(input1, input2, output);
259}
260
261Status NEDivisionOperationKernel::validate_arguments(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output)
262{
Georgios Pinitas18134222020-09-03 21:00:23 +0100263 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&input1, 1, DataType::S32, DataType::F16, DataType::F32);
George Worta1e7e282019-01-15 11:00:29 +0000264 return NEArithmeticOperationKernel::validate_arguments(input1, input2, output);
265}
266
267Status NEDivisionOperationKernel::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output)
268{
269 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input1, input2, output);
270 ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(*input1, *input2, *output));
271 return Status{};
272}
273
Usama Arif81e671e2019-05-13 13:33:14 +0100274/** The power operator */
Michalis Spyrouce0c6752020-06-18 10:14:57 +0100275void NEPowerOperationKernel::configure(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output)
Usama Arif81e671e2019-05-13 13:33:14 +0100276{
Michalis Spyrouce0c6752020-06-18 10:14:57 +0100277 ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(*input1, *input2, *output));
Usama Arif81e671e2019-05-13 13:33:14 +0100278 configure_common(input1, input2, output);
279 _function = configure_arithm_func<ArithmeticOperation::POWER>(input1, input2, output);
280}
281
282Status NEPowerOperationKernel::validate_arguments(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output)
283{
284 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&input1, 1, DataType::F16, DataType::F32);
285 return NEArithmeticOperationKernel::validate_arguments(input1, input2, output);
286}
287
288Status NEPowerOperationKernel::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output)
289{
290 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input1, input2, output);
291 ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(*input1, *input2, *output));
292 return Status{};
293}
294
George Wortd88590f2018-12-12 17:39:58 +0000295/** Comparison operators (equal, not equal, less than, greater than, less than or equal, greater than or equal) */
Michalis Spyrouce0c6752020-06-18 10:14:57 +0100296void NEComparisonOperationKernel::configure(ComparisonOperation op, const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output)
giuros0192fd9432018-12-03 17:30:00 +0000297{
Michalis Spyrouce0c6752020-06-18 10:14:57 +0100298 ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(*input1, *input2, *output));
George Wortd88590f2018-12-12 17:39:58 +0000299 configure_common(input1, input2, output);
300 switch(op)
301 {
302 case ComparisonOperation::Equal:
303 _function = configure_comp_func<ComparisonOperation::Equal>(input1, input2, output);
304 break;
305 case ComparisonOperation::NotEqual:
306 _function = configure_comp_func<ComparisonOperation::NotEqual>(input1, input2, output);
307 break;
308 case ComparisonOperation::Greater:
309 _function = configure_comp_func<ComparisonOperation::Greater>(input1, input2, output);
310 break;
311 case ComparisonOperation::GreaterEqual:
312 _function = configure_comp_func<ComparisonOperation::GreaterEqual>(input1, input2, output);
313 break;
314 case ComparisonOperation::Less:
315 _function = configure_comp_func<ComparisonOperation::Less>(input1, input2, output);
316 break;
317 case ComparisonOperation::LessEqual:
318 _function = configure_comp_func<ComparisonOperation::LessEqual>(input1, input2, output);
319 break;
320 default:
321 ARM_COMPUTE_ERROR("NOT_SUPPORTED!");
322 }
323}
324
325Status NEComparisonOperationKernel::validate_arguments(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output)
326{
Michele Di Giorgio1c76c1d2020-08-28 13:25:31 +0100327 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&input1, 1, DataType::U8, DataType::QASYMM8, DataType::QASYMM8_SIGNED, DataType::S16, DataType::F16, DataType::S32, DataType::F32);
George Wortd88590f2018-12-12 17:39:58 +0000328 // Validate in case of configured output
329 if(output.total_size() > 0)
330 {
331 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&output, 1, DataType::U8);
332 }
333 return validate_arguments_common(input1, input2, output);
334}
335
336Status NEComparisonOperationKernel::validate(ComparisonOperation op, const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output)
337{
338 ARM_COMPUTE_UNUSED(op);
339 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input1, input2, output);
340 ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(*input1, *input2, *output));
341 return Status{};
giuros0192fd9432018-12-03 17:30:00 +0000342}
343} // namespace arm_compute