blob: 82d1403c56aa2b80431c0d16b613da28b8b27693 [file] [log] [blame]
Manuel Bottini053e7512018-12-28 15:05:20 +00001/*
Sheri Zhangac6499a2021-02-10 15:32:38 +00002 * Copyright (c) 2018-2021 Arm Limited.
Manuel Bottini053e7512018-12-28 15:05:20 +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/NERangeKernel.h"
Manuel Bottini053e7512018-12-28 15:05:20 +000025
26#include "arm_compute/core/Error.h"
27#include "arm_compute/core/Helpers.h"
Manuel Bottini053e7512018-12-28 15:05:20 +000028#include "arm_compute/core/ITensor.h"
Manuel Bottini053e7512018-12-28 15:05:20 +000029#include "arm_compute/core/TensorInfo.h"
30#include "arm_compute/core/Validate.h"
Georgios Pinitasddb93bb2020-10-02 16:38:59 +010031#include "src/core/NEON/NEAsymm.h"
32#include "src/core/NEON/wrapper/wrapper.h"
Yair Schwarzbaum9e8a7702021-11-08 10:58:06 +020033#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"
Yair Schwarzbaum9e8a7702021-11-08 10:58:06 +020036#include "src/cpu/kernels/range/list.h"
Manuel Bottini053e7512018-12-28 15:05:20 +000037
38namespace arm_compute
39{
40namespace
41{
Yair Schwarzbaum9e8a7702021-11-08 10:58:06 +020042struct RangeSelectorData
Manuel Bottini053e7512018-12-28 15:05:20 +000043{
Yair Schwarzbaum9e8a7702021-11-08 10:58:06 +020044 DataType dt;
45};
Manuel Bottini053e7512018-12-28 15:05:20 +000046
Yair Schwarzbaum9e8a7702021-11-08 10:58:06 +020047using RangeSelectorPtr = std::add_pointer<bool(const RangeSelectorData &data)>::type;
48using RangeUKernelPtr = std::add_pointer<void(ITensor *, float, float, const Window &)>::type;
Manuel Bottini053e7512018-12-28 15:05:20 +000049
Yair Schwarzbaum9e8a7702021-11-08 10:58:06 +020050struct RangeUKernel
51{
52 const char *name;
53 const RangeSelectorPtr is_selected;
54 RangeUKernelPtr ukernel;
55};
Michalis Spyroucd5b4a32020-02-27 15:35:53 +000056
Yair Schwarzbaum9e8a7702021-11-08 10:58:06 +020057static const RangeUKernel available_kernels[] =
58{
Manuel Bottini053e7512018-12-28 15:05:20 +000059 {
Yair Schwarzbaum9e8a7702021-11-08 10:58:06 +020060 "fp16_neon_range",
61 [](const RangeSelectorData & data) { return data.dt == DataType::F16; },
62 REGISTER_FP16_NEON(arm_compute::cpu::fp16_neon_range_function)
Manuel Bottini053e7512018-12-28 15:05:20 +000063 },
Yair Schwarzbaum9e8a7702021-11-08 10:58:06 +020064 {
65 "f32_neon_range",
66 [](const RangeSelectorData & data) { return data.dt == DataType::F32; },
67 REGISTER_FP32_NEON(arm_compute::cpu::fp32_neon_range_function)
68 },
69 {
70 "u8_neon_range",
71 [](const RangeSelectorData & data) { return data.dt == DataType::U8; },
72 REGISTER_INTEGER_NEON(arm_compute::cpu::u8_neon_range_function)
73 },
74 {
75 "u16_neon_range",
76 [](const RangeSelectorData & data) { return data.dt == DataType::U16; },
77 REGISTER_INTEGER_NEON(arm_compute::cpu::u16_neon_range_function)
78 },
79 {
80 "u32_neon_range",
81 [](const RangeSelectorData & data) { return data.dt == DataType::U32; },
82 REGISTER_INTEGER_NEON(arm_compute::cpu::u32_neon_range_function)
83 },
84 {
85 "s8_neon_range",
86 [](const RangeSelectorData & data) { return data.dt == DataType::S8; },
87 REGISTER_INTEGER_NEON(arm_compute::cpu::s8_neon_range_function)
88 },
89 {
90 "s16_neon_range",
91 [](const RangeSelectorData & data) { return data.dt == DataType::S16; },
92 REGISTER_INTEGER_NEON(arm_compute::cpu::s16_neon_range_function)
93 },
94 {
95 "s32_neon_range",
96 [](const RangeSelectorData & data) { return data.dt == DataType::S32; },
97 REGISTER_INTEGER_NEON(arm_compute::cpu::s32_neon_range_function)
98 },
99};
100
101/** Micro-kernel selector
102 *
103 * @param[in] data Selection data passed to help pick the appropriate micro-kernel
104 *
105 * @return A matching micro-kernel else nullptr
106 */
107const RangeUKernel *get_implementation(const RangeSelectorData &data)
108{
109 for(const auto &uk : available_kernels)
110 {
111 if(uk.is_selected(data))
112 {
113 return &uk;
114 }
115 }
116 return nullptr;
Manuel Bottini053e7512018-12-28 15:05:20 +0000117}
118
119Status validate_arguments(const ITensorInfo &output, const float start, const float end, const float step)
120{
Yair Schwarzbaum9e8a7702021-11-08 10:58:06 +0200121 const auto *uk = get_implementation(RangeSelectorData{ output.data_type() });
122 ARM_COMPUTE_RETURN_ERROR_ON(uk == nullptr || uk->ukernel == nullptr);
Manuel Bottini053e7512018-12-28 15:05:20 +0000123
124 ARM_COMPUTE_RETURN_ERROR_ON_MSG((start == end), "start of the requested sequence must not be equal to the end");
125 ARM_COMPUTE_RETURN_ERROR_ON_MSG(((start < end) && (step <= 0)), "step must be greater than 0 when start < end");
126 ARM_COMPUTE_RETURN_ERROR_ON_MSG(((start > end) && (step >= 0)), "step must be less than 0 when start > end");
127
Michalis Spyrouf63885b2019-01-16 14:18:09 +0000128 ARM_COMPUTE_RETURN_ERROR_ON_MSG(!check_value_range(start, output.data_type(), output.quantization_info()), "start value is outside the range of the data type");
129 ARM_COMPUTE_RETURN_ERROR_ON_MSG(!check_value_range(end, output.data_type(), output.quantization_info()), "end value is outside the range of the data type");
130 ARM_COMPUTE_RETURN_ERROR_ON_MSG(!check_value_range(step, output.data_type(), output.quantization_info()), "step value is outside the range of the data type");
Manuel Bottini053e7512018-12-28 15:05:20 +0000131
132 ARM_COMPUTE_RETURN_ERROR_ON_MSG((start == end), "start of the requested sequence must not be equal to the end");
133
134 ARM_COMPUTE_RETURN_ERROR_ON_MSG(output.num_dimensions() != 1, "Output has to be a 1-D tensor");
Michalis Spyrouf63885b2019-01-16 14:18:09 +0000135 ARM_COMPUTE_RETURN_ERROR_ON_MSG(output.tensor_shape().total_size() < num_of_elements_in_range(start, end, step), "Output tensor size is incorrect");
Manuel Bottini053e7512018-12-28 15:05:20 +0000136
137 return Status{};
138}
Manuel Bottini053e7512018-12-28 15:05:20 +0000139} // namespace
140
141NERangeKernel::NERangeKernel()
Yair Schwarzbaum9e8a7702021-11-08 10:58:06 +0200142 : _start(0), _end(1), _step(1), _output(nullptr)
Manuel Bottini053e7512018-12-28 15:05:20 +0000143{
144}
145
146void NERangeKernel::configure(ITensor *output, float start, float end, float step)
147{
148 ARM_COMPUTE_ERROR_ON_NULLPTR(output);
149
150 ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(*(output->info()), start, end, step));
151
Michalis Spyroucd5b4a32020-02-27 15:35:53 +0000152 // Auto initialize output if not initialized
153 auto_init_if_empty(*output->info(), TensorShape(num_of_elements_in_range(start, end, step)), 1, output->info()->data_type(), output->info()->quantization_info());
154
Manuel Bottini053e7512018-12-28 15:05:20 +0000155 // Configure kernel window
SiCongLib88272e2021-02-24 15:40:57 +0000156 Window win = calculate_max_window(*output->info(), Steps());
Manuel Bottini053e7512018-12-28 15:05:20 +0000157
158 _start = start;
159 _end = end;
160 _step = step;
161 _output = output;
Manuel Bottini053e7512018-12-28 15:05:20 +0000162
Michalis Spyroucd5b4a32020-02-27 15:35:53 +0000163 INEKernel::configure(win);
Manuel Bottini053e7512018-12-28 15:05:20 +0000164}
165
166Status NERangeKernel::validate(const ITensorInfo *output, float start, float end, float step)
167{
168 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(output);
169
170 ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(*output, start, end, step));
Manuel Bottini053e7512018-12-28 15:05:20 +0000171
172 return Status{};
173}
174
175void NERangeKernel::run(const Window &window, const ThreadInfo &info)
176{
177 ARM_COMPUTE_UNUSED(info);
178 ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this);
179 ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(INEKernel::window(), window);
Yair Schwarzbaum9e8a7702021-11-08 10:58:06 +0200180 const auto *uk = get_implementation(RangeSelectorData{ _output->info()->data_type() });
Manuel Bottini053e7512018-12-28 15:05:20 +0000181
Yair Schwarzbaum9e8a7702021-11-08 10:58:06 +0200182 uk->ukernel(_output, _start, _step, window);
Manuel Bottini053e7512018-12-28 15:05:20 +0000183}
Sheri Zhangac6499a2021-02-10 15:32:38 +0000184} // namespace arm_compute