giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 1 | /* |
Sang-Hoon Park | 5db75c3 | 2021-01-07 16:59:32 +0000 | [diff] [blame] | 2 | * Copyright (c) 2018-2021 Arm Limited. |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 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 | */ |
Michalis Spyrou | ebcebf1 | 2020-10-21 00:04:14 +0100 | [diff] [blame] | 24 | #include "src/core/NEON/kernels/NEElementwiseOperationKernel.h" |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 25 | |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 26 | #include "arm_compute/core/Helpers.h" |
| 27 | #include "arm_compute/core/IAccessWindow.h" |
Sang-Hoon Park | 68dd25f | 2020-10-19 16:00:11 +0100 | [diff] [blame] | 28 | #include "src/core/CPP/Validate.h" |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 29 | #include "src/core/NEON/kernels/elementwise/impl/elementwise_list.h" |
| 30 | #include "src/core/NEON/kernels/elementwise/impl/elementwise_quantized_list.h" |
Sang-Hoon Park | 5db75c3 | 2021-01-07 16:59:32 +0000 | [diff] [blame] | 31 | #include "src/core/SVE/kernels/elementwise/impl/elementwise_list.h" |
Sang-Hoon Park | d23a251 | 2021-01-11 22:19:49 +0000 | [diff] [blame] | 32 | #include "src/core/SVE/kernels/elementwise/impl/elementwise_quantized_list.h" |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 33 | #include "src/core/common/Registrars.h" |
Sang-Hoon Park | 68dd25f | 2020-10-19 16:00:11 +0100 | [diff] [blame] | 34 | #include "src/core/helpers/AutoConfiguration.h" |
| 35 | #include "src/core/helpers/WindowHelpers.h" |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 36 | |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 37 | #include <arm_neon.h> |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 38 | |
| 39 | namespace arm_compute |
| 40 | { |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 41 | namespace |
| 42 | { |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 43 | using ElementwiseSelector = std::add_pointer<bool(DataType)>::type; |
| 44 | using UKernelType = NEElementwiseOperationKernel::ElementwiseFunction; |
| 45 | struct ElementwiseKernel |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 46 | { |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 47 | const char *name; |
| 48 | const ElementwiseSelector is_selected; |
| 49 | UKernelType *ukernel; |
| 50 | }; |
| 51 | |
| 52 | template <DataType dt> |
| 53 | inline bool is_selected(DataType data_type) |
| 54 | { |
| 55 | return dt == data_type; |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 56 | } |
| 57 | |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 58 | template <DataType input_data_type, DataType output_data_type = input_data_type> |
| 59 | static ElementwiseKernel generate_kernel(UKernelType *ukernel) |
Michalis Spyrou | 8d4d1b8 | 2019-11-28 11:31:23 +0000 | [diff] [blame] | 60 | { |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 61 | 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 Spyrou | 8d4d1b8 | 2019-11-28 11:31:23 +0000 | [diff] [blame] | 65 | |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 66 | return { kernel_name.c_str(), is_selected<input_data_type>, ukernel }; |
George Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 67 | } |
| 68 | |
| 69 | template <ArithmeticOperation op> |
| 70 | std::function<void(const ITensor *, const ITensor *, ITensor *, const Window &)> |
Michalis Spyrou | ce0c675 | 2020-06-18 10:14:57 +0100 | [diff] [blame] | 71 | configure_arithm_func(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output) |
George Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 72 | { |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 73 | ARM_COMPUTE_UNUSED(input2, output); |
| 74 | static ElementwiseKernel kernels[] = |
George Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 75 | { |
Sang-Hoon Park | 5db75c3 | 2021-01-07 16:59:32 +0000 | [diff] [blame] | 76 | #if defined(__ARM_FEATURE_SVE) |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 77 | 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 Park | 5db75c3 | 2021-01-07 16:59:32 +0000 | [diff] [blame] | 79 | #else /* defined(__ARM_FEATURE_SVE) */ |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 80 | 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 Park | 5db75c3 | 2021-01-07 16:59:32 +0000 | [diff] [blame] | 82 | #endif /* defined(__ARM_FEATURE_SVE) */ |
Sang-Hoon Park | d23a251 | 2021-01-11 22:19:49 +0000 | [diff] [blame] | 83 | #if defined(__ARM_FEATURE_SVE2) |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 84 | 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 Park | d23a251 | 2021-01-11 22:19:49 +0000 | [diff] [blame] | 86 | #else /* defined(__ARM_FEATURE_SVE2) */ |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 87 | 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 Park | d23a251 | 2021-01-11 22:19:49 +0000 | [diff] [blame] | 89 | #endif /* defined(__ARM_FEATURE_SVE2) */ |
George Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 90 | #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC |
Sang-Hoon Park | 5db75c3 | 2021-01-07 16:59:32 +0000 | [diff] [blame] | 91 | #if defined(__ARM_FEATURE_SVE) |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 92 | generate_kernel<DataType::F16>(REGISTER_FP16_SVE((arm_compute::cpu::sve::elementwise_arithmetic_op<op, float16_t>))), |
Sang-Hoon Park | 5db75c3 | 2021-01-07 16:59:32 +0000 | [diff] [blame] | 93 | #else /* defined(__ARM_FEATURE_SVE) */ |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 94 | generate_kernel<DataType::F16>(REGISTER_FP16_NEON((arm_compute::cpu::elementwise_arithm_op<op, typename wrapper::traits::neon_vector<float16_t, 8>>))), |
Sang-Hoon Park | 5db75c3 | 2021-01-07 16:59:32 +0000 | [diff] [blame] | 95 | #endif /* defined(__ARM_FEATURE_SVE) */ |
George Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 96 | #endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */ |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 97 | generate_kernel<DataType::S16>(REGISTER_INTEGER_NEON((arm_compute::cpu::elementwise_arithm_op<op, typename wrapper::traits::neon_vector<int16_t, 8>>))), |
| 98 | }; |
George Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 99 | |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 100 | 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 Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 109 | } |
| 110 | |
| 111 | template <ComparisonOperation op> |
| 112 | std::function<void(const ITensor *input1, const ITensor *input2, ITensor *output, const Window &window)> |
Michalis Spyrou | ce0c675 | 2020-06-18 10:14:57 +0100 | [diff] [blame] | 113 | configure_comp_func(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output) |
George Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 114 | { |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 115 | ARM_COMPUTE_UNUSED(input2, output); |
| 116 | static ElementwiseKernel kernels[] = |
George Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 117 | { |
Sang-Hoon Park | 5db75c3 | 2021-01-07 16:59:32 +0000 | [diff] [blame] | 118 | #if defined(__ARM_FEATURE_SVE) |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 119 | 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 Park | 5db75c3 | 2021-01-07 16:59:32 +0000 | [diff] [blame] | 123 | #else /* defined(__ARM_FEATURE_SVE) */ |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 124 | 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 Park | 5db75c3 | 2021-01-07 16:59:32 +0000 | [diff] [blame] | 128 | #endif /* defined(__ARM_FEATURE_SVE) */ |
Sang-Hoon Park | d23a251 | 2021-01-11 22:19:49 +0000 | [diff] [blame] | 129 | #if defined(__ARM_FEATURE_SVE2) |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 130 | 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 Park | d23a251 | 2021-01-11 22:19:49 +0000 | [diff] [blame] | 132 | #else /* defined(__ARM_FEATURE_SVE2) */ |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 133 | 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 Park | d23a251 | 2021-01-11 22:19:49 +0000 | [diff] [blame] | 135 | #endif /* defined(__ARM_FEATURE_SVE2) */ |
George Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 136 | #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC |
Sang-Hoon Park | 5db75c3 | 2021-01-07 16:59:32 +0000 | [diff] [blame] | 137 | #if defined(__ARM_FEATURE_SVE) |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 138 | generate_kernel<DataType::F16, DataType::U8>(REGISTER_FP16_SVE((arm_compute::cpu::sve::elementwise_comparison_op<op, float16_t>))), |
Sang-Hoon Park | 5db75c3 | 2021-01-07 16:59:32 +0000 | [diff] [blame] | 139 | #else /* defined(__ARM_FEATURE_SVE) */ |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 140 | generate_kernel<DataType::F16, DataType::U8>(REGISTER_FP16_NEON((arm_compute::cpu::elementwise_comp_op_16<op, float16_t, float16x8_t>))), |
Sang-Hoon Park | 5db75c3 | 2021-01-07 16:59:32 +0000 | [diff] [blame] | 141 | #endif /* defined(__ARM_FEATURE_SVE) */ |
George Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 142 | #endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */ |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 143 | }; |
George Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 144 | |
Sang-Hoon Park | d2447bb | 2021-01-18 09:41:37 +0000 | [diff] [blame^] | 145 | 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 Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 154 | } |
| 155 | } // namespace |
| 156 | |
| 157 | NEElementwiseOperationKernel::NEElementwiseOperationKernel() |
| 158 | : _function(nullptr), _input1(nullptr), _input2(nullptr), _output(nullptr) |
| 159 | { |
| 160 | } |
| 161 | |
| 162 | Status NEElementwiseOperationKernel::validate_arguments_common(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output) |
| 163 | { |
George Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 164 | ARM_COMPUTE_RETURN_ERROR_ON_CPU_F16_UNSUPPORTED(&input1); |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 165 | 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 | { |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 174 | 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 | } |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 180 | |
Michalis Spyrou | ce0c675 | 2020-06-18 10:14:57 +0100 | [diff] [blame] | 181 | void NEElementwiseOperationKernel::configure_common(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output) |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 182 | { |
| 183 | ARM_COMPUTE_ERROR_ON_NULLPTR(input1, input2, output); |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 184 | |
| 185 | // Configure kernel window |
Michalis Spyrou | ce0c675 | 2020-06-18 10:14:57 +0100 | [diff] [blame] | 186 | const std::pair<TensorShape, ValidRegion> broadcast_pair = ITensorInfo::broadcast_shape_and_valid_region(*input1, *input2); |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 187 | const TensorShape &out_shape = broadcast_pair.first; |
| 188 | const ValidRegion &valid_region = broadcast_pair.second; |
| 189 | |
| 190 | // Auto initialize output if not initialized |
Michalis Spyrou | ce0c675 | 2020-06-18 10:14:57 +0100 | [diff] [blame] | 191 | auto_init_if_empty(*output, out_shape, 1, input1->data_type()); |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 192 | |
| 193 | Window win = calculate_max_window(valid_region); |
| 194 | |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 195 | INEKernel::configure(win); |
| 196 | } |
| 197 | |
Georgios Pinitas | 0499dff | 2020-07-31 22:21:38 +0100 | [diff] [blame] | 198 | void NEElementwiseOperationKernel::run_op(ITensorPack &tensors, const Window &window, const ThreadInfo &info) |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 199 | { |
George Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 200 | ARM_COMPUTE_UNUSED(info, window); |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 201 | ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this); |
| 202 | ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(INEKernel::window(), window); |
George Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 203 | ARM_COMPUTE_ERROR_ON(_function == nullptr); |
Georgios Pinitas | 0499dff | 2020-07-31 22:21:38 +0100 | [diff] [blame] | 204 | _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); |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 207 | } |
| 208 | |
| 209 | /** Arithmetic operators (min, max, squared_diff) */ |
Michalis Spyrou | ce0c675 | 2020-06-18 10:14:57 +0100 | [diff] [blame] | 210 | void NEArithmeticOperationKernel::configure(ArithmeticOperation op, const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output) |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 211 | { |
Michalis Spyrou | ce0c675 | 2020-06-18 10:14:57 +0100 | [diff] [blame] | 212 | ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(*input1, *input2, *output)); |
George Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 213 | configure_common(input1, input2, output); |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 214 | switch(op) |
| 215 | { |
| 216 | case ArithmeticOperation::MAX: |
George Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 217 | _function = configure_arithm_func<ArithmeticOperation::MAX>(input1, input2, output); |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 218 | break; |
| 219 | case ArithmeticOperation::MIN: |
George Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 220 | _function = configure_arithm_func<ArithmeticOperation::MIN>(input1, input2, output); |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 221 | break; |
| 222 | case ArithmeticOperation::SQUARED_DIFF: |
George Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 223 | _function = configure_arithm_func<ArithmeticOperation::SQUARED_DIFF>(input1, input2, output); |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 224 | break; |
giuros01 | d513436 | 2019-05-14 16:12:53 +0100 | [diff] [blame] | 225 | case ArithmeticOperation::PRELU: |
| 226 | _function = configure_arithm_func<ArithmeticOperation::PRELU>(input1, input2, output); |
| 227 | break; |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 228 | default: |
| 229 | ARM_COMPUTE_ERROR("NOT_SUPPORTED!"); |
| 230 | } |
| 231 | } |
| 232 | |
George Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 233 | Status NEArithmeticOperationKernel::validate_arguments(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output) |
| 234 | { |
Michele Di Giorgio | 1c76c1d | 2020-08-28 13:25:31 +0100 | [diff] [blame] | 235 | 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 Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 236 | // 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 | |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 244 | Status 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 Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 248 | ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(*input1, *input2, *output)); |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 249 | return Status{}; |
| 250 | } |
| 251 | |
George Wort | a1e7e28 | 2019-01-15 11:00:29 +0000 | [diff] [blame] | 252 | /** The division operator */ |
| 253 | |
Michalis Spyrou | ce0c675 | 2020-06-18 10:14:57 +0100 | [diff] [blame] | 254 | void NEDivisionOperationKernel::configure(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output) |
George Wort | a1e7e28 | 2019-01-15 11:00:29 +0000 | [diff] [blame] | 255 | { |
Michalis Spyrou | ce0c675 | 2020-06-18 10:14:57 +0100 | [diff] [blame] | 256 | ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(*input1, *input2, *output)); |
George Wort | a1e7e28 | 2019-01-15 11:00:29 +0000 | [diff] [blame] | 257 | configure_common(input1, input2, output); |
| 258 | _function = configure_arithm_func<ArithmeticOperation::DIV>(input1, input2, output); |
| 259 | } |
| 260 | |
| 261 | Status NEDivisionOperationKernel::validate_arguments(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output) |
| 262 | { |
Georgios Pinitas | 1813422 | 2020-09-03 21:00:23 +0100 | [diff] [blame] | 263 | ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&input1, 1, DataType::S32, DataType::F16, DataType::F32); |
George Wort | a1e7e28 | 2019-01-15 11:00:29 +0000 | [diff] [blame] | 264 | return NEArithmeticOperationKernel::validate_arguments(input1, input2, output); |
| 265 | } |
| 266 | |
| 267 | Status 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 Arif | 81e671e | 2019-05-13 13:33:14 +0100 | [diff] [blame] | 274 | /** The power operator */ |
Michalis Spyrou | ce0c675 | 2020-06-18 10:14:57 +0100 | [diff] [blame] | 275 | void NEPowerOperationKernel::configure(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output) |
Usama Arif | 81e671e | 2019-05-13 13:33:14 +0100 | [diff] [blame] | 276 | { |
Michalis Spyrou | ce0c675 | 2020-06-18 10:14:57 +0100 | [diff] [blame] | 277 | ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(*input1, *input2, *output)); |
Usama Arif | 81e671e | 2019-05-13 13:33:14 +0100 | [diff] [blame] | 278 | configure_common(input1, input2, output); |
| 279 | _function = configure_arithm_func<ArithmeticOperation::POWER>(input1, input2, output); |
| 280 | } |
| 281 | |
| 282 | Status 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 | |
| 288 | Status 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 Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 295 | /** Comparison operators (equal, not equal, less than, greater than, less than or equal, greater than or equal) */ |
Michalis Spyrou | ce0c675 | 2020-06-18 10:14:57 +0100 | [diff] [blame] | 296 | void NEComparisonOperationKernel::configure(ComparisonOperation op, const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output) |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 297 | { |
Michalis Spyrou | ce0c675 | 2020-06-18 10:14:57 +0100 | [diff] [blame] | 298 | ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(*input1, *input2, *output)); |
George Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 299 | 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 | |
| 325 | Status NEComparisonOperationKernel::validate_arguments(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output) |
| 326 | { |
Michele Di Giorgio | 1c76c1d | 2020-08-28 13:25:31 +0100 | [diff] [blame] | 327 | 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 Wort | d88590f | 2018-12-12 17:39:58 +0000 | [diff] [blame] | 328 | // 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 | |
| 336 | Status 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{}; |
giuros01 | 92fd943 | 2018-12-03 17:30:00 +0000 | [diff] [blame] | 342 | } |
| 343 | } // namespace arm_compute |