blob: ab915b9d72bd65297170314d2b48b01c0e5b44d1 [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 */
Sang-Hoon Park63001ac2021-01-18 14:20:27 +000024#include "src/core/cpu/kernels/CpuElementwiseKernel.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/common/Registrars.h"
Sang-Hoon Park63001ac2021-01-18 14:20:27 +000030#include "src/core/cpu/kernels/elementwise/neon/elementwise_list.h"
31#include "src/core/cpu/kernels/elementwise/neon/elementwise_quantized_list.h"
32#include "src/core/cpu/kernels/elementwise/sve/elementwise_list.h"
33#include "src/core/cpu/kernels/elementwise/sve/elementwise_quantized_list.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{
Sang-Hoon Park63001ac2021-01-18 14:20:27 +000041namespace cpu
42{
43namespace kernels
44{
giuros0192fd9432018-12-03 17:30:00 +000045namespace
46{
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000047using ElementwiseSelector = std::add_pointer<bool(DataType)>::type;
Sang-Hoon Park63001ac2021-01-18 14:20:27 +000048using UKernelType = CpuElementwiseKernel::ElementwiseFunction;
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000049struct ElementwiseKernel
giuros0192fd9432018-12-03 17:30:00 +000050{
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000051 const char *name;
52 const ElementwiseSelector is_selected;
53 UKernelType *ukernel;
54};
55
56template <DataType dt>
57inline bool is_selected(DataType data_type)
58{
59 return dt == data_type;
giuros0192fd9432018-12-03 17:30:00 +000060}
61
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000062template <DataType input_data_type, DataType output_data_type = input_data_type>
63static ElementwiseKernel generate_kernel(UKernelType *ukernel)
Michalis Spyrou8d4d1b82019-11-28 11:31:23 +000064{
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000065 std::string kernel_name("op_");
66 kernel_name += string_from_data_type(input_data_type) + "_";
67 kernel_name += string_from_data_type(input_data_type) + "_";
68 kernel_name += string_from_data_type(output_data_type);
Michalis Spyrou8d4d1b82019-11-28 11:31:23 +000069
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000070 return { kernel_name.c_str(), is_selected<input_data_type>, ukernel };
George Wortd88590f2018-12-12 17:39:58 +000071}
72
73template <ArithmeticOperation op>
74std::function<void(const ITensor *, const ITensor *, ITensor *, const Window &)>
Michalis Spyrouce0c6752020-06-18 10:14:57 +010075configure_arithm_func(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output)
George Wortd88590f2018-12-12 17:39:58 +000076{
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000077 ARM_COMPUTE_UNUSED(input2, output);
78 static ElementwiseKernel kernels[] =
George Wortd88590f2018-12-12 17:39:58 +000079 {
Sang-Hoon Park5db75c32021-01-07 16:59:32 +000080#if defined(__ARM_FEATURE_SVE)
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000081 generate_kernel<DataType::F32>(REGISTER_FP32_SVE((arm_compute::cpu::sve::elementwise_arithmetic_op<op, float32_t>))),
82 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 +000083#else /* defined(__ARM_FEATURE_SVE) */
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000084 generate_kernel<DataType::F32>(REGISTER_FP32_NEON((arm_compute::cpu::elementwise_arithm_op<op, typename wrapper::traits::neon_vector<float, 4>>))),
85 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 +000086#endif /* defined(__ARM_FEATURE_SVE) */
Sang-Hoon Parkd23a2512021-01-11 22:19:49 +000087#if defined(__ARM_FEATURE_SVE2)
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000088 generate_kernel<DataType::QASYMM8>(REGISTER_QASYMM8_SVE((arm_compute::cpu::sve::elementwise_arithmetic_quantized_op<op, uint8_t>))),
89 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 +000090#else /* defined(__ARM_FEATURE_SVE2) */
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000091 generate_kernel<DataType::QASYMM8>(REGISTER_QASYMM8_NEON((arm_compute::cpu::elementwise_arithm_op_quantized<op>))),
92 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 +000093#endif /* defined(__ARM_FEATURE_SVE2) */
George Wortd88590f2018-12-12 17:39:58 +000094#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
Sang-Hoon Park5db75c32021-01-07 16:59:32 +000095#if defined(__ARM_FEATURE_SVE)
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000096 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 +000097#else /* defined(__ARM_FEATURE_SVE) */
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000098 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 +000099#endif /* defined(__ARM_FEATURE_SVE) */
George Wortd88590f2018-12-12 17:39:58 +0000100#endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000101 generate_kernel<DataType::S16>(REGISTER_INTEGER_NEON((arm_compute::cpu::elementwise_arithm_op<op, typename wrapper::traits::neon_vector<int16_t, 8>>))),
102 };
George Wortd88590f2018-12-12 17:39:58 +0000103
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000104 for(const auto &uk : kernels)
105 {
106 if(uk.is_selected(input1->data_type()))
107 {
108 return uk.ukernel;
109 }
110 }
111
112 return nullptr;
George Wortd88590f2018-12-12 17:39:58 +0000113}
114
115template <ComparisonOperation op>
116std::function<void(const ITensor *input1, const ITensor *input2, ITensor *output, const Window &window)>
Michalis Spyrouce0c6752020-06-18 10:14:57 +0100117configure_comp_func(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output)
George Wortd88590f2018-12-12 17:39:58 +0000118{
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000119 ARM_COMPUTE_UNUSED(input2, output);
120 static ElementwiseKernel kernels[] =
George Wortd88590f2018-12-12 17:39:58 +0000121 {
Sang-Hoon Park5db75c32021-01-07 16:59:32 +0000122#if defined(__ARM_FEATURE_SVE)
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000123 generate_kernel<DataType::U8, DataType::U8>(REGISTER_INTEGER_SVE((arm_compute::cpu::sve::elementwise_comparison_op<op, uint8_t>))),
124 generate_kernel<DataType::F32, DataType::U8>(REGISTER_FP32_SVE((arm_compute::cpu::sve::elementwise_comparison_op<op, float>))),
125 generate_kernel<DataType::S16, DataType::U8>(REGISTER_INTEGER_SVE((arm_compute::cpu::sve::elementwise_comparison_op<op, int16_t>))),
126 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 +0000127#else /* defined(__ARM_FEATURE_SVE) */
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000128 generate_kernel<DataType::U8, DataType::U8>(REGISTER_INTEGER_NEON((arm_compute::cpu::elementwise_comp_op_8<op, uint8_t, uint8x16_t>))),
129 generate_kernel<DataType::F32, DataType::U8>(REGISTER_FP32_NEON((arm_compute::cpu::elementwise_comp_op_32<op, float, float32x4_t>))),
130 generate_kernel<DataType::S16, DataType::U8>(REGISTER_INTEGER_NEON((arm_compute::cpu::elementwise_comp_op_16<op, int16_t, int16x8_t>))),
131 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 +0000132#endif /* defined(__ARM_FEATURE_SVE) */
Sang-Hoon Parkd23a2512021-01-11 22:19:49 +0000133#if defined(__ARM_FEATURE_SVE2)
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000134 generate_kernel<DataType::QASYMM8_SIGNED, DataType::U8>(REGISTER_QASYMM8_SIGNED_SVE((arm_compute::cpu::sve::elementwise_comparison_quantized_op<op, int8_t>))),
135 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 +0000136#else /* defined(__ARM_FEATURE_SVE2) */
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000137 generate_kernel<DataType::QASYMM8_SIGNED, DataType::U8>(REGISTER_QASYMM8_SIGNED_NEON((arm_compute::cpu::elementwise_comp_op_quantized_signed<op>))),
138 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 +0000139#endif /* defined(__ARM_FEATURE_SVE2) */
George Wortd88590f2018-12-12 17:39:58 +0000140#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
Sang-Hoon Park5db75c32021-01-07 16:59:32 +0000141#if defined(__ARM_FEATURE_SVE)
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000142 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 +0000143#else /* defined(__ARM_FEATURE_SVE) */
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000144 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 +0000145#endif /* defined(__ARM_FEATURE_SVE) */
George Wortd88590f2018-12-12 17:39:58 +0000146#endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000147 };
George Wortd88590f2018-12-12 17:39:58 +0000148
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000149 for(const auto &uk : kernels)
150 {
151 if(uk.is_selected(input1->data_type()))
152 {
153 return uk.ukernel;
154 }
155 }
156
157 return nullptr;
George Wortd88590f2018-12-12 17:39:58 +0000158}
159} // namespace
160
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000161Status CpuElementwiseKernel::validate_arguments_common(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output)
George Wortd88590f2018-12-12 17:39:58 +0000162{
George Wortd88590f2018-12-12 17:39:58 +0000163 ARM_COMPUTE_RETURN_ERROR_ON_CPU_F16_UNSUPPORTED(&input1);
giuros0192fd9432018-12-03 17:30:00 +0000164 ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(&input1, &input2);
165
166 const TensorShape out_shape = TensorShape::broadcast_shape(input1.tensor_shape(), input2.tensor_shape());
167
168 ARM_COMPUTE_RETURN_ERROR_ON_MSG(out_shape.total_size() == 0, "Inputs are not broadcast compatible");
169
170 // Validate in case of configured output
171 if(output.total_size() > 0)
172 {
giuros0192fd9432018-12-03 17:30:00 +0000173 ARM_COMPUTE_RETURN_ERROR_ON_MSG(detail::have_different_dimensions(out_shape, output.tensor_shape(), 0),
174 "Wrong shape for output");
175 }
176
177 return Status{};
178}
giuros0192fd9432018-12-03 17:30:00 +0000179
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000180void CpuElementwiseKernel::configure_common(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output)
giuros0192fd9432018-12-03 17:30:00 +0000181{
182 ARM_COMPUTE_ERROR_ON_NULLPTR(input1, input2, output);
giuros0192fd9432018-12-03 17:30:00 +0000183
184 // Configure kernel window
Michalis Spyrouce0c6752020-06-18 10:14:57 +0100185 const std::pair<TensorShape, ValidRegion> broadcast_pair = ITensorInfo::broadcast_shape_and_valid_region(*input1, *input2);
giuros0192fd9432018-12-03 17:30:00 +0000186 const TensorShape &out_shape = broadcast_pair.first;
187 const ValidRegion &valid_region = broadcast_pair.second;
188
189 // Auto initialize output if not initialized
Michalis Spyrouce0c6752020-06-18 10:14:57 +0100190 auto_init_if_empty(*output, out_shape, 1, input1->data_type());
giuros0192fd9432018-12-03 17:30:00 +0000191
192 Window win = calculate_max_window(valid_region);
193
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000194 ICpuKernel::configure(win);
giuros0192fd9432018-12-03 17:30:00 +0000195}
196
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000197void CpuElementwiseKernel::run_op(ITensorPack &tensors, const Window &window, const ThreadInfo &info)
giuros0192fd9432018-12-03 17:30:00 +0000198{
George Wortd88590f2018-12-12 17:39:58 +0000199 ARM_COMPUTE_UNUSED(info, window);
giuros0192fd9432018-12-03 17:30:00 +0000200 ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000201 ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(ICpuKernel::window(), window);
202
203 auto src0 = tensors.get_const_tensor(TensorType::ACL_SRC_0);
204 auto src1 = tensors.get_const_tensor(TensorType::ACL_SRC_1);
205 auto dst = tensors.get_tensor(TensorType::ACL_DST);
206
207 auto function = get_implementation(src0->info(), src1->info(), dst->info());
208 ARM_COMPUTE_ERROR_ON(function == nullptr);
209 function(src0, src1, dst, window);
giuros0192fd9432018-12-03 17:30:00 +0000210}
211
212/** Arithmetic operators (min, max, squared_diff) */
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000213void CpuArithmeticKernel::configure(ArithmeticOperation op, const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output)
giuros0192fd9432018-12-03 17:30:00 +0000214{
Michalis Spyrouce0c6752020-06-18 10:14:57 +0100215 ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(*input1, *input2, *output));
George Wortd88590f2018-12-12 17:39:58 +0000216 configure_common(input1, input2, output);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000217 _op = op;
giuros0192fd9432018-12-03 17:30:00 +0000218}
219
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000220Status CpuArithmeticKernel::validate_arguments(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output)
George Wortd88590f2018-12-12 17:39:58 +0000221{
Michele Di Giorgio1c76c1d2020-08-28 13:25:31 +0100222 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 +0000223 // Validate in case of configured output
224 if(output.total_size() > 0)
225 {
226 ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(&input1, &output);
227 }
228 return validate_arguments_common(input1, input2, output);
229}
230
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000231Status CpuArithmeticKernel::validate(ArithmeticOperation op, const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output)
giuros0192fd9432018-12-03 17:30:00 +0000232{
233 ARM_COMPUTE_UNUSED(op);
234 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input1, input2, output);
George Wortd88590f2018-12-12 17:39:58 +0000235 ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(*input1, *input2, *output));
giuros0192fd9432018-12-03 17:30:00 +0000236 return Status{};
237}
238
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000239std::function<CpuElementwiseKernel::ElementwiseFunction>
240CpuArithmeticKernel::get_implementation(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output)
241{
242 switch(_op)
243 {
244 case ArithmeticOperation::MAX:
245 return configure_arithm_func<ArithmeticOperation::MAX>(input1, input2, output);
246 case ArithmeticOperation::MIN:
247 return configure_arithm_func<ArithmeticOperation::MIN>(input1, input2, output);
248 case ArithmeticOperation::SQUARED_DIFF:
249 return configure_arithm_func<ArithmeticOperation::SQUARED_DIFF>(input1, input2, output);
250 case ArithmeticOperation::PRELU:
251 return configure_arithm_func<ArithmeticOperation::PRELU>(input1, input2, output);
252 case ArithmeticOperation::DIV:
253 return configure_arithm_func<ArithmeticOperation::DIV>(input1, input2, output);
254 case ArithmeticOperation::POWER:
255 return configure_arithm_func<ArithmeticOperation::POWER>(input1, input2, output);
256 default:
257 ARM_COMPUTE_ERROR("NOT_SUPPORTED!");
258 }
259 return nullptr;
260}
261
George Worta1e7e282019-01-15 11:00:29 +0000262/** The division operator */
263
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000264void CpuDivisionKernel::configure(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output)
George Worta1e7e282019-01-15 11:00:29 +0000265{
Michalis Spyrouce0c6752020-06-18 10:14:57 +0100266 ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(*input1, *input2, *output));
George Worta1e7e282019-01-15 11:00:29 +0000267 configure_common(input1, input2, output);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000268 _op = ArithmeticOperation::DIV;
George Worta1e7e282019-01-15 11:00:29 +0000269}
270
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000271Status CpuDivisionKernel::validate_arguments(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output)
George Worta1e7e282019-01-15 11:00:29 +0000272{
Georgios Pinitas18134222020-09-03 21:00:23 +0100273 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&input1, 1, DataType::S32, DataType::F16, DataType::F32);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000274 return CpuArithmeticKernel::validate_arguments(input1, input2, output);
George Worta1e7e282019-01-15 11:00:29 +0000275}
276
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000277Status CpuDivisionKernel::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output)
George Worta1e7e282019-01-15 11:00:29 +0000278{
279 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input1, input2, output);
280 ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(*input1, *input2, *output));
281 return Status{};
282}
283
Usama Arif81e671e2019-05-13 13:33:14 +0100284/** The power operator */
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000285void CpuPowerKernel::configure(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output)
Usama Arif81e671e2019-05-13 13:33:14 +0100286{
Michalis Spyrouce0c6752020-06-18 10:14:57 +0100287 ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(*input1, *input2, *output));
Usama Arif81e671e2019-05-13 13:33:14 +0100288 configure_common(input1, input2, output);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000289 _op = ArithmeticOperation::POWER;
Usama Arif81e671e2019-05-13 13:33:14 +0100290}
291
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000292Status CpuPowerKernel::validate_arguments(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output)
Usama Arif81e671e2019-05-13 13:33:14 +0100293{
294 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&input1, 1, DataType::F16, DataType::F32);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000295 return CpuArithmeticKernel::validate_arguments(input1, input2, output);
Usama Arif81e671e2019-05-13 13:33:14 +0100296}
297
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000298Status CpuPowerKernel::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output)
Usama Arif81e671e2019-05-13 13:33:14 +0100299{
300 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input1, input2, output);
301 ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(*input1, *input2, *output));
302 return Status{};
303}
304
George Wortd88590f2018-12-12 17:39:58 +0000305/** Comparison operators (equal, not equal, less than, greater than, less than or equal, greater than or equal) */
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000306void CpuComparisonKernel::configure(ComparisonOperation op, const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output)
giuros0192fd9432018-12-03 17:30:00 +0000307{
Michalis Spyrouce0c6752020-06-18 10:14:57 +0100308 ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(*input1, *input2, *output));
George Wortd88590f2018-12-12 17:39:58 +0000309 configure_common(input1, input2, output);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000310 _op = op;
George Wortd88590f2018-12-12 17:39:58 +0000311}
312
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000313Status CpuComparisonKernel::validate_arguments(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output)
George Wortd88590f2018-12-12 17:39:58 +0000314{
Michele Di Giorgio1c76c1d2020-08-28 13:25:31 +0100315 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 +0000316 // Validate in case of configured output
317 if(output.total_size() > 0)
318 {
319 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&output, 1, DataType::U8);
320 }
321 return validate_arguments_common(input1, input2, output);
322}
323
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000324Status CpuComparisonKernel::validate(ComparisonOperation op, const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output)
George Wortd88590f2018-12-12 17:39:58 +0000325{
326 ARM_COMPUTE_UNUSED(op);
327 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input1, input2, output);
328 ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(*input1, *input2, *output));
329 return Status{};
giuros0192fd9432018-12-03 17:30:00 +0000330}
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000331
332std::function<CpuElementwiseKernel::ElementwiseFunction>
333CpuComparisonKernel::get_implementation(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output)
334{
335 switch(_op)
336 {
337 case ComparisonOperation::Equal:
338 return configure_comp_func<ComparisonOperation::Equal>(input1, input2, output);
339 case ComparisonOperation::NotEqual:
340 return configure_comp_func<ComparisonOperation::NotEqual>(input1, input2, output);
341 case ComparisonOperation::Greater:
342 return configure_comp_func<ComparisonOperation::Greater>(input1, input2, output);
343 case ComparisonOperation::GreaterEqual:
344 return configure_comp_func<ComparisonOperation::GreaterEqual>(input1, input2, output);
345 case ComparisonOperation::Less:
346 return configure_comp_func<ComparisonOperation::Less>(input1, input2, output);
347 case ComparisonOperation::LessEqual:
348 return configure_comp_func<ComparisonOperation::LessEqual>(input1, input2, output);
349 default:
350 ARM_COMPUTE_ERROR("NOT_SUPPORTED!");
351 }
352 return nullptr;
353}
354} // namespace kernels
355} // namespace cpu
giuros0192fd9432018-12-03 17:30:00 +0000356} // namespace arm_compute