blob: dc0c5b210d154c151dc3bdf2c8e43a0585bb9359 [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"
Sang-Hoon Park68dd25f2020-10-19 16:00:11 +010027#include "src/core/CPP/Validate.h"
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000028#include "src/core/common/Registrars.h"
Sang-Hoon Park63001ac2021-01-18 14:20:27 +000029#include "src/core/cpu/kernels/elementwise/neon/elementwise_list.h"
30#include "src/core/cpu/kernels/elementwise/neon/elementwise_quantized_list.h"
31#include "src/core/cpu/kernels/elementwise/sve/elementwise_list.h"
32#include "src/core/cpu/kernels/elementwise/sve/elementwise_quantized_list.h"
Sang-Hoon Park68dd25f2020-10-19 16:00:11 +010033#include "src/core/helpers/AutoConfiguration.h"
34#include "src/core/helpers/WindowHelpers.h"
giuros0192fd9432018-12-03 17:30:00 +000035
giuros0192fd9432018-12-03 17:30:00 +000036#include <arm_neon.h>
giuros0192fd9432018-12-03 17:30:00 +000037
38namespace arm_compute
39{
Sang-Hoon Park63001ac2021-01-18 14:20:27 +000040namespace cpu
41{
42namespace kernels
43{
giuros0192fd9432018-12-03 17:30:00 +000044namespace
45{
Michalis Spyrou20fca522021-06-07 14:23:57 +010046struct ElementwiseSelectorData
47{
48 DataType dt;
49 const CPUInfo &ci;
50};
51
52using ElementwiseSelector = std::add_pointer<bool(const ElementwiseSelectorData &)>::type;
Sang-Hoon Park63001ac2021-01-18 14:20:27 +000053using UKernelType = CpuElementwiseKernel::ElementwiseFunction;
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000054struct ElementwiseKernel
giuros0192fd9432018-12-03 17:30:00 +000055{
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000056 const char *name;
57 const ElementwiseSelector is_selected;
58 UKernelType *ukernel;
59};
60
George Wortd88590f2018-12-12 17:39:58 +000061template <ArithmeticOperation op>
62std::function<void(const ITensor *, const ITensor *, ITensor *, const Window &)>
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +000063configure_arithm_func(const ITensorInfo *src0, const ITensorInfo *src1, ITensorInfo *dst)
George Wortd88590f2018-12-12 17:39:58 +000064{
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +000065 ARM_COMPUTE_UNUSED(src1, dst);
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +000066 static ElementwiseKernel kernels[] =
George Wortd88590f2018-12-12 17:39:58 +000067 {
Michalis Spyrou20fca522021-06-07 14:23:57 +010068#if defined(ARM_COMPUTE_ENABLE_SVE)
69 {
70 "sve_elementwise_fp32",
71 [](const ElementwiseSelectorData & data) { return data.dt == DataType::F32 && data.ci.has_sve(); },
72 REGISTER_FP32_SVE((arm_compute::cpu::elementwise_arithmetic_op<op, float32_t>))
73 },
74 {
75 "sve_elementwise_s32",
76 [](const ElementwiseSelectorData & data) { return data.dt == DataType::S32 && data.ci.has_sve(); },
77 REGISTER_INTEGER_SVE((arm_compute::cpu::elementwise_arithmetic_op<op, int32_t>))
78 },
79 {
80 "sve_elementwise_s16",
81 [](const ElementwiseSelectorData & data) { return data.dt == DataType::S16 && data.ci.has_sve(); },
82 REGISTER_INTEGER_SVE((arm_compute::cpu::elementwise_arithmetic_op<op, int16_t>))
83 },
84#endif /* defined(ARM_COMPUTE_ENABLE_SVE) */
85#if defined(ARM_COMPUTE_ENABLE_NEON)
86 {
87 "neon_elementwise_f32",
88 [](const ElementwiseSelectorData & data) { return data.dt == DataType::F32; },
89 REGISTER_FP32_NEON((arm_compute::cpu::elementwise_arithm_op<op, typename wrapper::traits::neon_vector<float, 4>>))
90 },
91 {
92 "neon_elementwise_s32",
93 [](const ElementwiseSelectorData & data) { return data.dt == DataType::S32; },
94 REGISTER_INTEGER_NEON((arm_compute::cpu::elementwise_arithm_op<op, typename wrapper::traits::neon_vector<int32_t, 4>>))
95 },
96#endif /* defined(ARM_COMPUTE_ENABLE_NEON) */
97#if defined(ARM_COMPUTE_ENABLE_SVE2)
98 {
99 "sve2_elementwise_qu8",
100 [](const ElementwiseSelectorData & data) { return data.dt == DataType::QASYMM8 && data.ci.has_sve2(); },
101 REGISTER_QASYMM8_SVE((arm_compute::cpu::elementwise_arithmetic_quantized_op<op, uint8_t>))
102 },
103 {
104 "sve2_elementwise_qs8",
105 [](const ElementwiseSelectorData & data) { return data.dt == DataType::QASYMM8_SIGNED && data.ci.has_sve2(); },
106 REGISTER_QASYMM8_SIGNED_SVE((arm_compute::cpu::elementwise_arithmetic_quantized_op<op, int8_t>))
107 },
108#endif /* defined(ARM_COMPUTE_ENABLE_SVE2) */
109#if defined(ARM_COMPUTE_ENABLE_NEON) || defined(ARM_COMPUTE_ENABLE_SVE)
110 {
111 "neon_elementwise_qu8",
112 [](const ElementwiseSelectorData & data) { return data.dt == DataType::QASYMM8; },
113 REGISTER_QASYMM8_NEON((arm_compute::cpu::elementwise_arithm_op_quantized<op>))
114 },
115 {
116 "neon_elementwise_qs8",
117 [](const ElementwiseSelectorData & data) { return data.dt == DataType::QASYMM8_SIGNED; },
118 REGISTER_QASYMM8_SIGNED_NEON((arm_compute::cpu::elementwise_arithm_op_quantized_signed<op>))
119 },
120#endif /* defined(ARM_COMPUTE_ENABLE_NEON) || defined(ARM_COMPUTE_ENABLE_SVE) */
121#if defined(ARM_COMPUTE_ENABLE_SVE)
122 {
123 "sve_elementwise_f16",
124 [](const ElementwiseSelectorData & data) { return data.dt == DataType::F16 && data.ci.has_sve(); },
125 REGISTER_FP16_SVE((arm_compute::cpu::elementwise_arithmetic_op<op, float16_t>))
126 },
127#endif /* defined(ARM_COMPUTE_ENABLE_SVE) */
128#if defined(ARM_COMPUTE_ENABLE_NEON)
Georgios Pinitasbdcdc392021-04-22 16:42:03 +0100129#if defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)
Michalis Spyrou20fca522021-06-07 14:23:57 +0100130 {
131 "neon_elementwise_f16",
132 [](const ElementwiseSelectorData & data) { return data.dt == DataType::F16 && data.ci.has_fp16(); },
133 REGISTER_FP16_NEON((arm_compute::cpu::elementwise_arithm_op<op, typename wrapper::traits::neon_vector<float16_t, 8>>))
134 },
Georgios Pinitasbdcdc392021-04-22 16:42:03 +0100135#endif /* defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) */
Michalis Spyrou20fca522021-06-07 14:23:57 +0100136 {
137 "neon_elementwise_s16",
138 [](const ElementwiseSelectorData & data) { return data.dt == DataType::S16; },
139 REGISTER_INTEGER_NEON((arm_compute::cpu::elementwise_arithm_op<op, typename wrapper::traits::neon_vector<int16_t, 8>>))
140 },
141#endif /* defined(ARM_COMPUTE_ENABLE_NEON) */
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000142 };
George Wortd88590f2018-12-12 17:39:58 +0000143
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000144 for(const auto &uk : kernels)
145 {
Michalis Spyrou20fca522021-06-07 14:23:57 +0100146 if(uk.is_selected({ src0->data_type(), CPUInfo::get() }))
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000147 {
148 return uk.ukernel;
149 }
150 }
151
152 return nullptr;
George Wortd88590f2018-12-12 17:39:58 +0000153}
154
155template <ComparisonOperation op>
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000156std::function<void(const ITensor *, const ITensor *, ITensor *, const Window &)>
157configure_comp_func(const ITensorInfo *src0, const ITensorInfo *src1, ITensorInfo *dst)
George Wortd88590f2018-12-12 17:39:58 +0000158{
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000159 ARM_COMPUTE_UNUSED(src1, dst);
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000160 static ElementwiseKernel kernels[] =
George Wortd88590f2018-12-12 17:39:58 +0000161 {
Michalis Spyrou20fca522021-06-07 14:23:57 +0100162#if defined(ARM_COMPUTE_ENABLE_SVE)
163 {
164 "sve_comparison_u8",
165 [](const ElementwiseSelectorData & data) { return data.dt == DataType::U8 && data.ci.has_sve(); },
166 REGISTER_INTEGER_SVE((arm_compute::cpu::elementwise_comparison_op<op, uint8_t>))
167 },
168 {
169 "sve_comparison_f32",
170 [](const ElementwiseSelectorData & data) { return data.dt == DataType::F32 && data.ci.has_sve(); },
171 REGISTER_FP32_SVE((arm_compute::cpu::elementwise_comparison_op<op, float>))
172 },
173 {
174 "sve_comparison_s16",
175 [](const ElementwiseSelectorData & data) { return data.dt == DataType::S16 && data.ci.has_sve(); },
176 REGISTER_INTEGER_SVE((arm_compute::cpu::elementwise_comparison_op<op, int16_t>))
177 },
178 {
179 "sve_comparison_s32",
180 [](const ElementwiseSelectorData & data) { return data.dt == DataType::S32 && data.ci.has_sve(); },
181 REGISTER_INTEGER_SVE((arm_compute::cpu::elementwise_comparison_op<op, int32_t>))
182 },
183#endif /* defined(ARM_COMPUTE_ENABLE_SVE) */
184#if defined(ARM_COMPUTE_ENABLE_NEON)
185 {
186 "neon_comparison_u8",
187 [](const ElementwiseSelectorData & data) { return data.dt == DataType::U8; },
188 REGISTER_INTEGER_NEON((arm_compute::cpu::elementwise_comp_op_8<op, uint8_t, uint8x16_t>))
189 },
190 {
191 "neon_comparison_f32",
192 [](const ElementwiseSelectorData & data) { return data.dt == DataType::F32; },
193 REGISTER_FP32_NEON((arm_compute::cpu::elementwise_comp_op_32<op, float, float32x4_t>))
194 },
195 {
196 "neon_comparison_s16",
197 [](const ElementwiseSelectorData & data) { return data.dt == DataType::S16; },
198 REGISTER_INTEGER_NEON((arm_compute::cpu::elementwise_comp_op_16<op, int16_t, int16x8_t>))
199 },
200 {
201 "neon_comparison_s32",
202 [](const ElementwiseSelectorData & data) { return data.dt == DataType::S32; },
203 REGISTER_INTEGER_NEON((arm_compute::cpu::elementwise_comp_op_32<op, int32_t, int32x4_t>))
204 },
205#endif /* defined(ARM_COMPUTE_ENABLE_NEON) */
206#if defined(ARM_COMPUTE_ENABLE_SVE2)
207 {
208 "sve_comparison_qu8",
209 [](const ElementwiseSelectorData & data) { return data.dt == DataType::QASYMM8 && data.ci.has_sve2(); },
210 REGISTER_QASYMM8_SVE((arm_compute::cpu::elementwise_comparison_quantized_op<op, uint8_t>))
211 },
212 {
213 "sve_comparison_qs8",
214 [](const ElementwiseSelectorData & data) { return data.dt == DataType::QASYMM8_SIGNED && data.ci.has_sve2(); },
215 REGISTER_QASYMM8_SIGNED_SVE((arm_compute::cpu::elementwise_comparison_quantized_op<op, int8_t>))
216 },
217#endif /* defined(ARM_COMPUTE_ENABLE_SVE2) */
218#if defined(ARM_COMPUTE_ENABLE_NEON) || defined(ARM_COMPUTE_ENABLE_SVE)
219 {
220 "neon_comparison_qu8",
221 [](const ElementwiseSelectorData & data) { return data.dt == DataType::QASYMM8; },
222 REGISTER_QASYMM8_NEON((arm_compute::cpu::elementwise_comp_op_quantized<op>))
223 },
224 {
225 "neon_comparison_qs8",
226 [](const ElementwiseSelectorData & data) { return data.dt == DataType::QASYMM8_SIGNED; },
227 REGISTER_QASYMM8_SIGNED_NEON((arm_compute::cpu::elementwise_comp_op_quantized_signed<op>))
228 },
229#endif /* defined(ARM_COMPUTE_ENABLE_NEON) || defined(ARM_COMPUTE_ENABLE_SVE) */
230#if defined(ARM_COMPUTE_ENABLE_SVE)
231 {
232 "sve_comparison_f16",
233 [](const ElementwiseSelectorData & data) { return data.dt == DataType::F16 && data.ci.has_sve(); },
234 REGISTER_FP16_SVE((arm_compute::cpu::elementwise_comparison_op<op, float16_t>))
235 },
236#endif /* defined(ARM_COMPUTE_ENABLE_SVE) */
237#if defined(ARM_COMPUTE_ENABLE_NEON) && defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)
238 {
239 "neon_comparison_f16",
240 [](const ElementwiseSelectorData & data) { return data.dt == DataType::F16 && data.ci.has_fp16(); },
241 REGISTER_FP16_NEON((arm_compute::cpu::elementwise_comp_op_16<op, float16_t, float16x8_t>))
242 },
243#endif /* defined(ARM_COMPUTE_ENABLE_NEON) && defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) */
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000244 };
George Wortd88590f2018-12-12 17:39:58 +0000245
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000246 for(const auto &uk : kernels)
247 {
Michalis Spyrou20fca522021-06-07 14:23:57 +0100248 if(uk.is_selected({ src0->data_type(), CPUInfo::get() }))
Sang-Hoon Parkd2447bb2021-01-18 09:41:37 +0000249 {
250 return uk.ukernel;
251 }
252 }
253
254 return nullptr;
George Wortd88590f2018-12-12 17:39:58 +0000255}
256} // namespace
257
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000258Status CpuElementwiseKernel::validate_arguments_common(const ITensorInfo &src0, const ITensorInfo &src1, const ITensorInfo &dst)
George Wortd88590f2018-12-12 17:39:58 +0000259{
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000260 ARM_COMPUTE_RETURN_ERROR_ON_CPU_F16_UNSUPPORTED(&src0);
261 ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(&src0, &src1);
giuros0192fd9432018-12-03 17:30:00 +0000262
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000263 const TensorShape out_shape = TensorShape::broadcast_shape(src0.tensor_shape(), src1.tensor_shape());
giuros0192fd9432018-12-03 17:30:00 +0000264
265 ARM_COMPUTE_RETURN_ERROR_ON_MSG(out_shape.total_size() == 0, "Inputs are not broadcast compatible");
266
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000267 // Validate in case of configured dst
268 if(dst.total_size() > 0)
giuros0192fd9432018-12-03 17:30:00 +0000269 {
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000270 ARM_COMPUTE_RETURN_ERROR_ON_MSG(detail::have_different_dimensions(out_shape, dst.tensor_shape(), 0),
giuros0192fd9432018-12-03 17:30:00 +0000271 "Wrong shape for output");
272 }
273
274 return Status{};
275}
giuros0192fd9432018-12-03 17:30:00 +0000276
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000277void CpuElementwiseKernel::configure_common(const ITensorInfo *src0, const ITensorInfo *src1, ITensorInfo *dst)
giuros0192fd9432018-12-03 17:30:00 +0000278{
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000279 ARM_COMPUTE_ERROR_ON_NULLPTR(src0, src1, dst);
giuros0192fd9432018-12-03 17:30:00 +0000280
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000281 // If any of shapes is dynamic, expect a configured window and dst at run-time.
282 if(src0->is_dynamic() || src1->is_dynamic())
283 {
284 return;
285 }
giuros0192fd9432018-12-03 17:30:00 +0000286
Sang-Hoon Parkd0b7b4b2021-03-09 10:47:30 +0000287 auto shape_and_window = compute_output_shape_and_window(src0->tensor_shape(), src1->tensor_shape());
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000288 auto_init_if_empty(*dst, shape_and_window.first, 1, src0->data_type());
289 ICpuKernel::configure(shape_and_window.second);
giuros0192fd9432018-12-03 17:30:00 +0000290}
291
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000292void CpuElementwiseKernel::run_op(ITensorPack &tensors, const Window &window, const ThreadInfo &info)
giuros0192fd9432018-12-03 17:30:00 +0000293{
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000294 ARM_COMPUTE_UNUSED(info);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000295
296 auto src0 = tensors.get_const_tensor(TensorType::ACL_SRC_0);
297 auto src1 = tensors.get_const_tensor(TensorType::ACL_SRC_1);
298 auto dst = tensors.get_tensor(TensorType::ACL_DST);
299
300 auto function = get_implementation(src0->info(), src1->info(), dst->info());
301 ARM_COMPUTE_ERROR_ON(function == nullptr);
302 function(src0, src1, dst, window);
giuros0192fd9432018-12-03 17:30:00 +0000303}
304
305/** Arithmetic operators (min, max, squared_diff) */
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000306void CpuArithmeticKernel::configure(ArithmeticOperation op, const ITensorInfo *src0, const ITensorInfo *src1, ITensorInfo *dst)
giuros0192fd9432018-12-03 17:30:00 +0000307{
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000308 ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(*src0, *src1, *dst));
309 configure_common(src0, src1, dst);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000310 _op = op;
giuros0192fd9432018-12-03 17:30:00 +0000311}
312
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000313Status CpuArithmeticKernel::validate_arguments(const ITensorInfo &src0, const ITensorInfo &src1, const ITensorInfo &dst)
George Wortd88590f2018-12-12 17:39:58 +0000314{
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000315 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&src0, 1, DataType::QASYMM8, DataType::QASYMM8_SIGNED, DataType::S16, DataType::F16, DataType::S32, DataType::F32);
316 // Validate in case of configured dst
317 if(dst.total_size() > 0)
George Wortd88590f2018-12-12 17:39:58 +0000318 {
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000319 ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(&src0, &dst);
George Wortd88590f2018-12-12 17:39:58 +0000320 }
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000321 return validate_arguments_common(src0, src1, dst);
George Wortd88590f2018-12-12 17:39:58 +0000322}
323
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000324Status CpuArithmeticKernel::validate(ArithmeticOperation op, const ITensorInfo *src0, const ITensorInfo *src1, const ITensorInfo *dst)
giuros0192fd9432018-12-03 17:30:00 +0000325{
326 ARM_COMPUTE_UNUSED(op);
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000327 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src0, src1, dst);
328 ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(*src0, *src1, *dst));
giuros0192fd9432018-12-03 17:30:00 +0000329 return Status{};
330}
331
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000332std::function<CpuElementwiseKernel::ElementwiseFunction>
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000333CpuArithmeticKernel::get_implementation(const ITensorInfo *src0, const ITensorInfo *src1, ITensorInfo *dst)
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000334{
335 switch(_op)
336 {
337 case ArithmeticOperation::MAX:
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000338 return configure_arithm_func<ArithmeticOperation::MAX>(src0, src1, dst);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000339 case ArithmeticOperation::MIN:
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000340 return configure_arithm_func<ArithmeticOperation::MIN>(src0, src1, dst);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000341 case ArithmeticOperation::SQUARED_DIFF:
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000342 return configure_arithm_func<ArithmeticOperation::SQUARED_DIFF>(src0, src1, dst);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000343 case ArithmeticOperation::PRELU:
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000344 return configure_arithm_func<ArithmeticOperation::PRELU>(src0, src1, dst);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000345 case ArithmeticOperation::DIV:
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000346 return configure_arithm_func<ArithmeticOperation::DIV>(src0, src1, dst);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000347 case ArithmeticOperation::POWER:
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000348 return configure_arithm_func<ArithmeticOperation::POWER>(src0, src1, dst);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000349 default:
350 ARM_COMPUTE_ERROR("NOT_SUPPORTED!");
351 }
352 return nullptr;
353}
354
George Worta1e7e282019-01-15 11:00:29 +0000355/** The division operator */
356
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000357void CpuDivisionKernel::configure(const ITensorInfo *src0, const ITensorInfo *src1, ITensorInfo *dst)
George Worta1e7e282019-01-15 11:00:29 +0000358{
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000359 ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(*src0, *src1, *dst));
360 configure_common(src0, src1, dst);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000361 _op = ArithmeticOperation::DIV;
George Worta1e7e282019-01-15 11:00:29 +0000362}
363
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000364Status CpuDivisionKernel::validate_arguments(const ITensorInfo &src0, const ITensorInfo &src1, const ITensorInfo &dst)
George Worta1e7e282019-01-15 11:00:29 +0000365{
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000366 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&src0, 1, DataType::S32, DataType::F16, DataType::F32);
367 return CpuArithmeticKernel::validate_arguments(src0, src1, dst);
George Worta1e7e282019-01-15 11:00:29 +0000368}
369
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000370Status CpuDivisionKernel::validate(const ITensorInfo *src0, const ITensorInfo *src1, const ITensorInfo *dst)
George Worta1e7e282019-01-15 11:00:29 +0000371{
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000372 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src0, src1, dst);
373 ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(*src0, *src1, *dst));
George Worta1e7e282019-01-15 11:00:29 +0000374 return Status{};
375}
376
Usama Arif81e671e2019-05-13 13:33:14 +0100377/** The power operator */
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000378void CpuPowerKernel::configure(const ITensorInfo *src0, const ITensorInfo *src1, ITensorInfo *dst)
Usama Arif81e671e2019-05-13 13:33:14 +0100379{
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000380 ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(*src0, *src1, *dst));
381 configure_common(src0, src1, dst);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000382 _op = ArithmeticOperation::POWER;
Usama Arif81e671e2019-05-13 13:33:14 +0100383}
384
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000385Status CpuPowerKernel::validate_arguments(const ITensorInfo &src0, const ITensorInfo &src1, const ITensorInfo &dst)
Usama Arif81e671e2019-05-13 13:33:14 +0100386{
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000387 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&src0, 1, DataType::F16, DataType::F32);
388 return CpuArithmeticKernel::validate_arguments(src0, src1, dst);
Usama Arif81e671e2019-05-13 13:33:14 +0100389}
390
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000391Status CpuPowerKernel::validate(const ITensorInfo *src0, const ITensorInfo *src1, const ITensorInfo *dst)
Usama Arif81e671e2019-05-13 13:33:14 +0100392{
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000393 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src0, src1, dst);
394 ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(*src0, *src1, *dst));
Usama Arif81e671e2019-05-13 13:33:14 +0100395 return Status{};
396}
397
George Wortd88590f2018-12-12 17:39:58 +0000398/** Comparison operators (equal, not equal, less than, greater than, less than or equal, greater than or equal) */
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000399void CpuComparisonKernel::configure(ComparisonOperation op, const ITensorInfo *src0, const ITensorInfo *src1, ITensorInfo *dst)
giuros0192fd9432018-12-03 17:30:00 +0000400{
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000401 ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(*src0, *src1, *dst));
402 configure_common(src0, src1, dst);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000403 _op = op;
George Wortd88590f2018-12-12 17:39:58 +0000404}
405
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000406Status CpuComparisonKernel::validate_arguments(const ITensorInfo &src0, const ITensorInfo &src1, const ITensorInfo &dst)
George Wortd88590f2018-12-12 17:39:58 +0000407{
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000408 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&src0, 1, DataType::U8, DataType::QASYMM8, DataType::QASYMM8_SIGNED, DataType::S16, DataType::F16, DataType::S32, DataType::F32);
409 // Validate in case of configured dst
410 if(dst.total_size() > 0)
George Wortd88590f2018-12-12 17:39:58 +0000411 {
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000412 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&dst, 1, DataType::U8);
George Wortd88590f2018-12-12 17:39:58 +0000413 }
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000414 return validate_arguments_common(src0, src1, dst);
George Wortd88590f2018-12-12 17:39:58 +0000415}
416
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000417Status CpuComparisonKernel::validate(ComparisonOperation op, const ITensorInfo *src0, const ITensorInfo *src1, const ITensorInfo *dst)
George Wortd88590f2018-12-12 17:39:58 +0000418{
419 ARM_COMPUTE_UNUSED(op);
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000420 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src0, src1, dst);
421 ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(*src0, *src1, *dst));
George Wortd88590f2018-12-12 17:39:58 +0000422 return Status{};
giuros0192fd9432018-12-03 17:30:00 +0000423}
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000424
425std::function<CpuElementwiseKernel::ElementwiseFunction>
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000426CpuComparisonKernel::get_implementation(const ITensorInfo *src0, const ITensorInfo *src1, ITensorInfo *dst)
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000427{
428 switch(_op)
429 {
430 case ComparisonOperation::Equal:
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000431 return configure_comp_func<ComparisonOperation::Equal>(src0, src1, dst);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000432 case ComparisonOperation::NotEqual:
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000433 return configure_comp_func<ComparisonOperation::NotEqual>(src0, src1, dst);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000434 case ComparisonOperation::Greater:
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000435 return configure_comp_func<ComparisonOperation::Greater>(src0, src1, dst);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000436 case ComparisonOperation::GreaterEqual:
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000437 return configure_comp_func<ComparisonOperation::GreaterEqual>(src0, src1, dst);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000438 case ComparisonOperation::Less:
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000439 return configure_comp_func<ComparisonOperation::Less>(src0, src1, dst);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000440 case ComparisonOperation::LessEqual:
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000441 return configure_comp_func<ComparisonOperation::LessEqual>(src0, src1, dst);
Sang-Hoon Park63001ac2021-01-18 14:20:27 +0000442 default:
443 ARM_COMPUTE_ERROR("NOT_SUPPORTED!");
444 }
445 return nullptr;
446}
447} // namespace kernels
448} // namespace cpu
giuros0192fd9432018-12-03 17:30:00 +0000449} // namespace arm_compute