blob: daa157ec3dad11fb7c3f9f3f01975d1365bb1e21 [file] [log] [blame]
Sheri Zhang23adc4c2021-01-05 12:48:45 +00001/*
2 * Copyright (c) 2021 Arm Limited.
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 */
Georgios Pinitas7891a732021-08-20 21:39:25 +010024#include "src/cpu/kernels/scale/neon/list.h"
Sheri Zhang23adc4c2021-01-05 12:48:45 +000025
26namespace arm_compute
27{
28namespace
29{
Sheri Zhang23adc4c2021-01-05 12:48:45 +000030void qasymm8_neon_scale_bilinear(const ITensor *src, ITensor *dst, const ITensor *offsets, const ITensor *dx, const ITensor *dy,
31 BorderMode border_mode, PixelValue constant_border_value, float sampling_offset,
32 bool align_corners, const Window &window)
33{
Manuel Bottini10b38262021-02-19 18:16:44 +000034 // Data layout is NHWC
Sheri Zhang23adc4c2021-01-05 12:48:45 +000035 // Compute the ratio between source height and destination height
Manuel Bottini10b38262021-02-19 18:16:44 +000036 const auto hr = scale_utils::calculate_resize_ratio(src->info()->dimension(2), dst->info()->dimension(2), align_corners);
Sheri Zhang23adc4c2021-01-05 12:48:45 +000037 Window win_off;
38 win_off.set(Window::DimX, Window::Dimension(0, 0, 0));
39 win_off.set(Window::DimY, Window::Dimension(0, 0, 0));
40
41 // Don't increment in X and Y direction for the input tensor
42 // A pointer to the start of this plane is needed as base for the precomputed offsets
43 Window win_in(window);
Manuel Bottini10b38262021-02-19 18:16:44 +000044 win_in.set(1, Window::Dimension(0, 0, 0));
45 win_in.set(2, Window::Dimension(0, 0, 0));
Sheri Zhang23adc4c2021-01-05 12:48:45 +000046
47 for(size_t d = Window::DimZ; d < offsets->info()->num_dimensions(); ++d)
48 {
49 win_off.set(d, Window::Dimension(0, 0, 0));
50 }
51
52 Iterator in(src, win_in);
53 Iterator out(dst, window);
54
Manuel Bottini10b38262021-02-19 18:16:44 +000055 const int32_t in_dim_w = src->info()->dimension(1);
56 const int32_t in_dim_h = src->info()->dimension(2);
57 const int32_t stride_w = src->info()->strides_in_bytes()[1];
58 const int32_t stride_h = src->info()->strides_in_bytes()[2];
Sheri Zhang23adc4c2021-01-05 12:48:45 +000059
60 const UniformQuantizationInfo iq_info = src->info()->quantization_info().uniform();
61 const UniformQuantizationInfo oq_info = dst->info()->quantization_info().uniform();
62
63 if(border_mode == BorderMode::CONSTANT)
64 {
65 const uint8_t const_border_value = static_cast<uint8_t>(constant_border_value.get<uint8_t>());
66 execute_window_loop(window, [&](const Coordinates & id)
67 {
Manuel Bottini10b38262021-02-19 18:16:44 +000068 const int32_t index_h = std::floor((id[2] + sampling_offset) * hr - sampling_offset);
69 const int32_t index_w = *(reinterpret_cast<const int32_t *>(offsets->ptr_to_element(Coordinates(id[1], id[2]))));
70 const auto dx_val = *(reinterpret_cast<const float *>(dx->ptr_to_element(Coordinates(id[1], id[2]))));
71 const auto dy_val = *(reinterpret_cast<const float *>(dy->ptr_to_element(Coordinates(id[1], id[2]))));
Sheri Zhang23adc4c2021-01-05 12:48:45 +000072 const auto pixel_row_ptr = reinterpret_cast<const uint8_t *>(in.ptr());
73
74 const auto a00 = (0 <= index_w && index_w < in_dim_w && 0 <= index_h && index_h < in_dim_h) ?
75 (*(pixel_row_ptr + index_w * stride_w + index_h * stride_h)) :
76 const_border_value;
Michalis Spyrouc89998f2021-08-26 14:11:44 +010077 const auto a01 = (-1 <= index_w && index_w + 1 < in_dim_w && 0 <= index_h && index_h < in_dim_h) ?
Sheri Zhang23adc4c2021-01-05 12:48:45 +000078 (*(pixel_row_ptr + (index_w + 1) * stride_w + index_h * stride_h)) :
79 const_border_value;
80 const auto a10 = (0 <= index_w && index_w < in_dim_w && -1 <= index_h && index_h < in_dim_h - 1) ?
81 (*(pixel_row_ptr + index_w * stride_w + (index_h + 1) * stride_h)) :
82 const_border_value;
83 const auto a11 = (-1 <= index_w && index_w < in_dim_w - 1 && -1 <= index_h && index_h < in_dim_h - 1) ?
84 (*(pixel_row_ptr + (index_w + 1) * stride_w + (index_h + 1) * stride_h)) :
85 const_border_value;
86
87 const float inp00 = Qasymm8QuantizationHelper<uint8_t>::dequantize(a00, iq_info);
88 const float inp01 = Qasymm8QuantizationHelper<uint8_t>::dequantize(a01, iq_info);
89 const float inp10 = Qasymm8QuantizationHelper<uint8_t>::dequantize(a10, iq_info);
90 const float inp11 = Qasymm8QuantizationHelper<uint8_t>::dequantize(a11, iq_info);
91 *reinterpret_cast<uint8_t *>(out.ptr()) = Qasymm8QuantizationHelper<uint8_t>::quantize(scale_helpers::delta_bilinear(inp00, inp01, inp10, inp11, dx_val, dy_val), oq_info);
92 },
93 in, out);
94 }
95 else if(border_mode == BorderMode::REPLICATE)
96 {
97 execute_window_loop(window, [&](const Coordinates & id)
98 {
Manuel Bottini10b38262021-02-19 18:16:44 +000099 const int index_h = std::floor((id[2] + sampling_offset) * hr - sampling_offset);
100 const int32_t index_w = *(reinterpret_cast<const int32_t *>(offsets->ptr_to_element(Coordinates(id[1], id[2]))));
101 const auto dx_val = *(reinterpret_cast<const float *>(dx->ptr_to_element(Coordinates(id[1], id[2]))));
102 const auto dy_val = *(reinterpret_cast<const float *>(dy->ptr_to_element(Coordinates(id[1], id[2]))));
Sheri Zhang23adc4c2021-01-05 12:48:45 +0000103 const auto pixel_row_ptr = reinterpret_cast<const uint8_t *>(in.ptr());
104
105 auto clamped_w = utility::clamp<int>(index_w, 0, in_dim_w - 1);
106 auto clamped_w1 = utility::clamp<int>(index_w + 1, 0, in_dim_w - 1);
107 auto clamped_h = utility::clamp<int>(index_h, 0, in_dim_h - 1);
108 auto clamped_h1 = utility::clamp<int>(index_h + 1, 0, in_dim_h - 1);
109
110 const auto a00 = *(pixel_row_ptr + clamped_w * stride_w + clamped_h * stride_h);
111 const auto a01 = *(pixel_row_ptr + clamped_w1 * stride_w + clamped_h * stride_h);
112 const auto a10 = *(pixel_row_ptr + clamped_w * stride_w + clamped_h1 * stride_h);
113 const auto a11 = *(pixel_row_ptr + clamped_w1 * stride_w + clamped_h1 * stride_h);
114
115 const float inp00 = Qasymm8QuantizationHelper<uint8_t>::dequantize(a00, iq_info);
116 const float inp01 = Qasymm8QuantizationHelper<uint8_t>::dequantize(a01, iq_info);
117 const float inp10 = Qasymm8QuantizationHelper<uint8_t>::dequantize(a10, iq_info);
118 const float inp11 = Qasymm8QuantizationHelper<uint8_t>::dequantize(a11, iq_info);
119 *reinterpret_cast<uint8_t *>(out.ptr()) = Qasymm8QuantizationHelper<uint8_t>::quantize(scale_helpers::delta_bilinear(inp00, inp01, inp10, inp11, dx_val, dy_val), oq_info);
120 },
121 in, out);
122 }
123 else
124 {
125 ARM_COMPUTE_ERROR("Not implemented");
126 }
127}
128}
129namespace cpu
130{
131void qasymm8_neon_scale(const ITensor *src, ITensor *dst, const ITensor *offsets, const ITensor *dx, const ITensor *dy,
132 InterpolationPolicy policy, BorderMode border_mode, PixelValue constant_border_value, float sampling_offset,
133 bool align_corners, const Window &window)
134{
135 if(policy == InterpolationPolicy::BILINEAR)
136 {
137 qasymm8_neon_scale_bilinear(src, dst, offsets, dx, dy, border_mode, constant_border_value, sampling_offset, align_corners, window);
138 }
139 else if(policy == InterpolationPolicy::NEAREST_NEIGHBOR)
140 {
Sheri Zhang360f5762021-01-20 12:20:20 +0000141 nearest_neon_scale<uint8_t>(src, dst, offsets, sampling_offset, align_corners, window);
Sheri Zhang23adc4c2021-01-05 12:48:45 +0000142 }
143}
144} // namespace cpu
145} // namespace arm_compute