Compute Library
 21.11
list.h
Go to the documentation of this file.
1 /*
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  */
24 #ifndef SRC_CORE_NEON_KERNELS_SCALE_LIST_H
25 #define SRC_CORE_NEON_KERNELS_SCALE_LIST_H
26 
30 #include "src/core/NEON/NEMath.h"
34 #include "support/Rounding.h"
35 
36 namespace arm_compute
37 {
38 namespace cpu
39 {
40 #define DECLARE_SCALE_KERNEL(func_name) \
41  void func_name(const ITensor *src, ITensor *dst, const ITensor *offsets, const ITensor *dx, const ITensor *dy, \
42  InterpolationPolicy policy, BorderMode border_mode, PixelValue constant_border_value, float sampling_offset, \
43  bool align_corners, const Window &window)
44 
49 
50 #undef DECLARE_SCALE_KERNEL
51 
52 template <typename T>
53 void nearest_neon_scale(const ITensor *src, ITensor *dst, const ITensor *offsets, float sampling_offset,
54  bool align_corners, const Window &window)
55 {
56  ARM_COMPUTE_UNUSED(offsets);
57 
58  // Compute the ratio between source and destination dimensions
59  const float scale_x = scale_utils::calculate_resize_ratio(src->info()->dimension(1), dst->info()->dimension(1), align_corners);
60  const float scale_y = scale_utils::calculate_resize_ratio(src->info()->dimension(2), dst->info()->dimension(2), align_corners);
61 
62  const int in_stride_y = src->info()->strides_in_bytes()[1];
63  const int in_stride_z = src->info()->strides_in_bytes()[2];
64  const int in_stride_w = src->info()->strides_in_bytes()[3];
65  const int out_stride_y = dst->info()->strides_in_bytes()[1];
66  const int out_stride_z = dst->info()->strides_in_bytes()[2];
67  const int out_stride_w = dst->info()->strides_in_bytes()[3];
68  const int out_dim_ch = dst->info()->dimension(0);
69  const int step_cout = 16 / sizeof(T);
70 
71  Window window_execution = window;
72  window_execution.set(Window::DimX, Window::Dimension(0, 1, 1));
73  Window win_in_out(window);
74  win_in_out.set(Window::DimY, Window::Dimension(0, 0, 0));
75  win_in_out.set(Window::DimZ, Window::Dimension(0, 0, 0));
76  Iterator in(src, win_in_out);
77  Iterator out(dst, win_in_out);
78 
79  const int xo_start = window_execution.y().start();
80  const int xo_end = window_execution.y().end();
81  const int xo_step = window_execution.y().step();
82  const int yo_start = window_execution.z().start();
83  const int yo_end = window_execution.z().end();
84  const int yo_step = window_execution.z().step();
85  const int bo_start = window_execution[3].start();
86  const int bo_end = window_execution[3].end();
87  const int bo_step = window_execution[3].step();
88 
89  for(int bo = bo_start; bo < bo_end; bo += bo_step)
90  {
91  const uint8_t *in_ptr_base = in.ptr() + bo * in_stride_w;
92  uint8_t *out_ptr_base = out.ptr() + bo * out_stride_w;
93 
94  for(int yo = yo_start; yo < yo_end; yo += yo_step)
95  {
96  // Floating-point coordinate
97  float yi_f = ((yo + sampling_offset) * scale_y);
98  int yi = 0;
99  if(align_corners)
100  {
102  }
103  else
104  {
105  yi = static_cast<int>(std::floor(yi_f));
106  }
107 
108  for(int xo = xo_start; xo < xo_end; xo += xo_step)
109  {
110  // Floating-point coordinate
111  float xi_f = ((xo + sampling_offset) * scale_x);
112  int xi = 0;
113  if(align_corners)
114  {
116  }
117  else
118  {
119  xi = static_cast<int>(std::floor(xi_f));
120  }
121 
122  const uint8_t *in_ptr = in_ptr_base + xi * in_stride_y + yi * in_stride_z;
123  uint8_t *out_ptr = out_ptr_base + xo * out_stride_y + yo * out_stride_z;
124 
125  int cout = 0;
126  for(; cout <= (out_dim_ch - step_cout); cout += step_cout)
127  {
128  auto out0 = wrapper::vloadq(reinterpret_cast<const T *>(in_ptr + cout * sizeof(T)));
129  wrapper::vstore(reinterpret_cast<T *>(out_ptr + cout * sizeof(T)), out0);
130  }
131 
132  for(; cout < out_dim_ch; ++cout)
133  {
134  auto out0 = *(reinterpret_cast<const T *>(in_ptr + cout * sizeof(T)));
135  *(reinterpret_cast<T *>(out_ptr + cout * sizeof(T))) = out0;
136  }
137  }
138  }
139  }
140 }
141 
142 template <typename T>
143 void bilinear_neon_scale(const ITensor *src, ITensor *dst, const ITensor *offsets, const ITensor *dx, const ITensor *dy,
144  BorderMode border_mode, PixelValue constant_border_value, float sampling_offset,
145  bool align_corners, const Window &window)
146 {
147  ARM_COMPUTE_UNUSED(offsets);
148  ARM_COMPUTE_UNUSED(dx);
149  ARM_COMPUTE_UNUSED(dy);
151 
152  // Compute the ratio between source and destination dimensions
153  const float scale_x = scale_utils::calculate_resize_ratio(src->info()->dimension(1), dst->info()->dimension(1), align_corners);
154  const float scale_y = scale_utils::calculate_resize_ratio(src->info()->dimension(2), dst->info()->dimension(2), align_corners);
155 
156  const int in_stride_y = src->info()->strides_in_bytes()[1];
157  const int in_stride_z = src->info()->strides_in_bytes()[2];
158  const int in_stride_w = src->info()->strides_in_bytes()[3];
159  const int out_stride_y = dst->info()->strides_in_bytes()[1];
160  const int out_stride_z = dst->info()->strides_in_bytes()[2];
161  const int out_stride_w = dst->info()->strides_in_bytes()[3];
162  const int in_dim_w = src->info()->dimension(1);
163  const int in_dim_h = src->info()->dimension(2);
164  const int out_dim_ch = dst->info()->dimension(0);
165  const int step_cout = 16 / sizeof(T);
166 
167  Window window_execution = window;
168  window_execution.set(Window::DimX, Window::Dimension(0, 1, 1));
169  Window win_in_out(window);
170  win_in_out.set(Window::DimY, Window::Dimension(0, 0, 0));
171  win_in_out.set(Window::DimZ, Window::Dimension(0, 0, 0));
172  Iterator in(src, win_in_out);
173  Iterator out(dst, win_in_out);
174 
175  const int xo_start = window_execution.y().start();
176  const int xo_end = window_execution.y().end();
177  const int xo_step = window_execution.y().step();
178  const int yo_start = window_execution.z().start();
179  const int yo_end = window_execution.z().end();
180  const int yo_step = window_execution.z().step();
181  const int bo_start = window_execution[3].start();
182  const int bo_end = window_execution[3].end();
183  const int bo_step = window_execution[3].step();
184 
185  if(border_mode == BorderMode::CONSTANT)
186  {
187 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
188  using ConstType = typename std::conditional<std::is_same<T, float16_t>::value, half, T>::type;
189 #else /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
190  using ConstType = T;
191 #endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
192  const T const_border_value = static_cast<T>(constant_border_value.get<ConstType>());
193 
194  for(int bo = bo_start; bo < bo_end; bo += bo_step)
195  {
196  const uint8_t *in_ptr_base = in.ptr() + bo * in_stride_w;
197  uint8_t *out_ptr_base = out.ptr() + bo * out_stride_w;
198 
199  for(int yo = yo_start; yo < yo_end; yo += yo_step)
200  {
201  // Floating-point coordinate
202  const float yi_f = ((yo + sampling_offset) * scale_y - sampling_offset);
203  // Integer coordinate
204  const auto yi = static_cast<int>(std::floor(yi_f));
205  // Weight for the y coordinate
206  const auto a1 = (yi_f - static_cast<float>(yi));
207  const auto b1 = (1.f - a1);
208 
209  for(int xo = xo_start; xo < xo_end; xo += xo_step)
210  {
211  // Floating-point coordinate
212  const float xi_f = ((xo + sampling_offset) * scale_x - sampling_offset);
213  // Integer coordinate
214  const auto xi = static_cast<int>(std::floor(xi_f));
215  // Weight for the x coordinate
216  const auto a = (xi_f - static_cast<float>(xi));
217  const auto b = (1.f - a);
218 
219  const auto s00_s = static_cast<T>(b * b1);
220  const auto s01_s = static_cast<T>(a * b1);
221  const auto s10_s = static_cast<T>(b * a1);
222  const auto s11_s = static_cast<T>(a * a1);
223 
224  const uint8_t *in_ptr = in_ptr_base + xi * in_stride_y + yi * in_stride_z;
225  uint8_t *out_ptr = out_ptr_base + xo * out_stride_y + yo * out_stride_z;
226 
227  int cout = 0;
228  for(; cout <= (out_dim_ch - step_cout); cout += step_cout)
229  {
230  auto in00 = wrapper::vdup_n(static_cast<T>(const_border_value), ExactTagType{});
231  auto in01 = wrapper::vdup_n(static_cast<T>(const_border_value), ExactTagType{});
232  auto in10 = wrapper::vdup_n(static_cast<T>(const_border_value), ExactTagType{});
233  auto in11 = wrapper::vdup_n(static_cast<T>(const_border_value), ExactTagType{});
234  if((yi >= 0) && (yi < in_dim_h))
235  {
236  if((xi >= 0) && (xi < in_dim_w))
237  {
238  in00 = wrapper::vloadq(reinterpret_cast<const T *>(in_ptr + cout * sizeof(T)));
239  }
240  if(((xi + 1) >= 0) && ((xi + 1) < in_dim_w))
241  {
242  in01 = wrapper::vloadq(reinterpret_cast<const T *>(in_ptr + cout * sizeof(T) + in_stride_y));
243  }
244  }
245  if(((yi + 1) >= 0) && ((yi + 1) < in_dim_h))
246  {
247  if((xi >= 0) && (xi < in_dim_w))
248  {
249  in10 = wrapper::vloadq(reinterpret_cast<const T *>(in_ptr + cout * sizeof(T) + in_stride_z));
250  }
251  if(((xi + 1) >= 0) && ((xi + 1) < in_dim_w))
252  {
253  in11 = wrapper::vloadq(reinterpret_cast<const T *>(in_ptr + cout * sizeof(T) + in_stride_y + in_stride_z));
254  }
255  }
256 
257  const auto s00 = wrapper::vdup_n(s00_s, ExactTagType{});
258  const auto s01 = wrapper::vdup_n(s01_s, ExactTagType{});
259  const auto s10 = wrapper::vdup_n(s10_s, ExactTagType{});
260  const auto s11 = wrapper::vdup_n(s11_s, ExactTagType{});
261  auto out0 = wrapper::vdup_n(static_cast<T>(0), ExactTagType{});
262  out0 = wrapper::vmla(out0, in00, s00);
263  out0 = wrapper::vmla(out0, in01, s01);
264  out0 = wrapper::vmla(out0, in10, s10);
265  out0 = wrapper::vmla(out0, in11, s11);
266  wrapper::vstore(reinterpret_cast<T *>(out_ptr + cout * sizeof(T)), out0);
267  }
268 
269  for(; cout < out_dim_ch; ++cout)
270  {
271  auto in00 = static_cast<T>(const_border_value);
272  auto in01 = static_cast<T>(const_border_value);
273  auto in10 = static_cast<T>(const_border_value);
274  auto in11 = static_cast<T>(const_border_value);
275  if((yi >= 0) && (yi < in_dim_h))
276  {
277  if((xi >= 0) && (xi < in_dim_w))
278  {
279  in00 = *(reinterpret_cast<const T *>(in_ptr + cout * sizeof(T)));
280  }
281  if(((xi + 1) >= 0) && ((xi + 1) < in_dim_w))
282  {
283  in01 = *(reinterpret_cast<const T *>(in_ptr + cout * sizeof(T) + in_stride_y));
284  }
285  }
286  if(((yi + 1) >= 0) && ((yi + 1) < in_dim_h))
287  {
288  if((xi >= 0) && (xi < in_dim_w))
289  {
290  in10 = *(reinterpret_cast<const T *>(in_ptr + cout * sizeof(T) + in_stride_z));
291  }
292  if(((xi + 1) >= 0) && ((xi + 1) < in_dim_w))
293  {
294  in11 = *(reinterpret_cast<const T *>(in_ptr + cout * sizeof(T) + in_stride_y + in_stride_z));
295  }
296  }
297  auto out0 = static_cast<T>(0);
298  out0 += in00 * s00_s;
299  out0 += in01 * s01_s;
300  out0 += in10 * s10_s;
301  out0 += in11 * s11_s;
302  *(reinterpret_cast<T *>(out_ptr + cout * sizeof(T))) = out0;
303  }
304  }
305  }
306  }
307  }
308  else if(border_mode == BorderMode::REPLICATE)
309  {
310  for(int bo = bo_start; bo < bo_end; bo += bo_step)
311  {
312  const uint8_t *in_ptr = in.ptr() + bo * in_stride_w;
313  uint8_t *out_ptr = out.ptr() + bo * out_stride_w;
314 
315  for(int yo = yo_start; yo < yo_end; yo += yo_step)
316  {
317  // Floating-point coordinate
318  const float yi_f = ((yo + sampling_offset) * scale_y - sampling_offset);
319  // Integer coordinate
320  const auto yi = static_cast<int>(std::floor(yi_f));
321  // Weight for the y coordinate
322  const auto a1 = (yi_f - static_cast<float>(yi));
323  const auto b1 = (1.f - a1);
324 
325  const auto yi0 = utility::clamp<int>(yi, 0, in_dim_h - 1);
326  const auto yi1 = utility::clamp<int>(yi + 1, 0, in_dim_h - 1);
327 
328  for(int xo = xo_start; xo < xo_end; xo += xo_step)
329  {
330  // Floating-point coordinate
331  const float xi_f = ((xo + sampling_offset) * scale_x - sampling_offset);
332  // Integer coordinate
333  const auto xi = static_cast<int>(std::floor(xi_f));
334  // Weight for the x coordinate
335  const auto a = (xi_f - static_cast<float>(xi));
336  const auto b = (1.f - a);
337 
338  const auto s00_s = static_cast<T>(b * b1);
339  const auto s01_s = static_cast<T>(a * b1);
340  const auto s10_s = static_cast<T>(b * a1);
341  const auto s11_s = static_cast<T>(a * a1);
342 
343  const auto xi0 = utility::clamp<int>(xi, 0, in_dim_w - 1);
344  const auto xi1 = utility::clamp<int>(xi + 1, 0, in_dim_w - 1);
345 
346  int cout = 0;
347  for(; cout <= (out_dim_ch - step_cout); cout += step_cout)
348  {
349  auto in00 = wrapper::vdup_n(static_cast<T>(0), ExactTagType{});
350  auto in01 = wrapper::vdup_n(static_cast<T>(0), ExactTagType{});
351  auto in10 = wrapper::vdup_n(static_cast<T>(0), ExactTagType{});
352  auto in11 = wrapper::vdup_n(static_cast<T>(0), ExactTagType{});
353  in00 = wrapper::vloadq(reinterpret_cast<const T *>(in_ptr + cout * sizeof(T) + (xi0) * in_stride_y + (yi0) * in_stride_z));
354  in01 = wrapper::vloadq(reinterpret_cast<const T *>(in_ptr + cout * sizeof(T) + (xi1) * in_stride_y + (yi0) * in_stride_z));
355  in10 = wrapper::vloadq(reinterpret_cast<const T *>(in_ptr + cout * sizeof(T) + (xi0) * in_stride_y + (yi1) * in_stride_z));
356  in11 = wrapper::vloadq(reinterpret_cast<const T *>(in_ptr + cout * sizeof(T) + (xi1) * in_stride_y + (yi1) * in_stride_z));
357 
358  const auto s00 = wrapper::vdup_n(s00_s, ExactTagType{});
359  const auto s01 = wrapper::vdup_n(s01_s, ExactTagType{});
360  const auto s10 = wrapper::vdup_n(s10_s, ExactTagType{});
361  const auto s11 = wrapper::vdup_n(s11_s, ExactTagType{});
362  auto out0 = wrapper::vdup_n(static_cast<T>(0), ExactTagType{});
363  out0 = wrapper::vmla(out0, in00, s00);
364  out0 = wrapper::vmla(out0, in01, s01);
365  out0 = wrapper::vmla(out0, in10, s10);
366  out0 = wrapper::vmla(out0, in11, s11);
367  wrapper::vstore(reinterpret_cast<T *>(out_ptr + cout * sizeof(T) + xo * out_stride_y + yo * out_stride_z), out0);
368  }
369 
370  for(; cout < out_dim_ch; ++cout)
371  {
372  auto in00 = static_cast<T>(0);
373  auto in01 = static_cast<T>(0);
374  auto in10 = static_cast<T>(0);
375  auto in11 = static_cast<T>(0);
376  in00 = *(reinterpret_cast<const T *>(in_ptr + cout * sizeof(T) + (xi0) * in_stride_y + (yi0) * in_stride_z));
377  in01 = *(reinterpret_cast<const T *>(in_ptr + cout * sizeof(T) + (xi1) * in_stride_y + (yi0) * in_stride_z));
378  in10 = *(reinterpret_cast<const T *>(in_ptr + cout * sizeof(T) + (xi0) * in_stride_y + (yi1) * in_stride_z));
379  in11 = *(reinterpret_cast<const T *>(in_ptr + cout * sizeof(T) + (xi1) * in_stride_y + (yi1) * in_stride_z));
380  auto out0 = static_cast<T>(0);
381  out0 += in00 * s00_s;
382  out0 += in01 * s01_s;
383  out0 += in10 * s10_s;
384  out0 += in11 * s11_s;
385  *(reinterpret_cast<T *>(out_ptr + cout * sizeof(T) + xo * out_stride_y + yo * out_stride_z)) = out0;
386  }
387  }
388  }
389  }
390  }
391  else
392  {
393  ARM_COMPUTE_ERROR("Not implemented");
394  }
395 }
396 
397 template <typename T>
398 void common_neon_scale(const ITensor *src, ITensor *dst, const ITensor *offsets, const ITensor *dx, const ITensor *dy,
399  InterpolationPolicy policy, BorderMode border_mode, PixelValue constant_border_value, float sampling_offset,
400  bool align_corners, const Window &window)
401 {
402  if(policy == InterpolationPolicy::BILINEAR)
403  {
404  bilinear_neon_scale<T>(src, dst, offsets, dx, dy, border_mode, constant_border_value, sampling_offset, align_corners, window);
405  }
406  else if(policy == InterpolationPolicy::NEAREST_NEIGHBOR)
407  {
408  nearest_neon_scale<T>(src, dst, offsets, sampling_offset, align_corners, window);
409  }
410 }
411 } // namespace cpu
412 } // namespace arm_compute
413 
414 #endif /* SRC_CORE_NEON_KERNELS_SCALE_LIST_H */
BorderMode
Methods available to handle borders.
Definition: Types.h:261
Class describing the value of a pixel for any image format.
Definition: PixelValue.h:34
InterpolationPolicy
Interpolation method.
Definition: Types.h:398
virtual size_t dimension(size_t index) const =0
Return the size of the requested dimension.
SimpleTensor< float > b
Definition: DFT.cpp:157
#define ARM_COMPUTE_ERROR(msg)
Print the given message then throw an std::runtime_error.
Definition: Error.h:352
constexpr int step() const
Return the step of the dimension.
Definition: Window.h:104
void get(uint8_t &v) const
Interpret the pixel value as a U8.
Definition: PixelValue.h:244
uint8x16_t vloadq(const uint8_t *ptr)
Definition: load.h:58
half_float::half half
16-bit floating point type
Definition: Types.h:48
Output values are defined by bilinear interpolation between the pixels.
Describe one of the image&#39;s dimensions with a start, end and step.
Definition: Window.h:77
void nearest_neon_scale(const ITensor *src, ITensor *dst, const ITensor *offsets, float sampling_offset, bool align_corners, const Window &window)
Definition: list.h:53
constexpr const Dimension & z() const
Alias to access the third dimension of the window.
Definition: Window.h:163
T round_half_away_from_zero(T value)
Round floating-point value with half value rounding away from zero.
Definition: Rounding.h:106
Output values are defined to match the source pixel whose center is nearest to the sample position...
decltype(strategy::transforms) typedef type
Interface for CPU tensor.
Definition: ITensor.h:36
SimpleTensor< float > src
Definition: DFT.cpp:155
Copyright (c) 2017-2021 Arm Limited.
typename neon_bitvector< T, BW >::tag_type neon_bitvector_tag_t
Helper type template to get the tag type of a neon vector.
Definition: traits.h:132
static constexpr size_t DimX
Alias for dimension 0 also known as X dimension.
Definition: Window.h:43
#define ARM_COMPUTE_UNUSED(...)
To avoid unused variables warnings.
Definition: Error.h:152
void qasymm8_signed_neon_scale(const ITensor *src, ITensor *dst, const ITensor *offsets, const ITensor *dx, const ITensor *dy, InterpolationPolicy policy, BorderMode border_mode, PixelValue constant_border_value, float sampling_offset, bool align_corners, const Window &window)
virtual ITensorInfo * info() const =0
Interface to be implemented by the child class to return the tensor&#39;s metadata.
#define DECLARE_SCALE_KERNEL(func_name)
Definition: list.h:40
constexpr uint8_t * ptr() const
Return a pointer to the current pixel.
Definition: Helpers.inl:139
void set(size_t dimension, const Dimension &dim)
Set the values of a given dimension.
Definition: Window.inl:49
void u8_neon_scale(const ITensor *src, ITensor *dst, const ITensor *offsets, const ITensor *dx, const ITensor *dy, InterpolationPolicy policy, BorderMode border_mode, PixelValue constant_border_value, float sampling_offset, bool align_corners, const Window &window)
Definition: integer.cpp:265
void bilinear_neon_scale(const ITensor *src, ITensor *dst, const ITensor *offsets, const ITensor *dx, const ITensor *dy, BorderMode border_mode, PixelValue constant_border_value, float sampling_offset, bool align_corners, const Window &window)
Definition: list.h:143
static constexpr size_t DimY
Alias for dimension 1 also known as Y dimension.
Definition: Window.h:45
static constexpr size_t DimZ
Alias for dimension 2 also known as Z dimension.
Definition: Window.h:47
Pixels outside the image are assumed to have the same value as the closest image pixel.
constexpr const Dimension & y() const
Alias to access the second dimension of the window.
Definition: Window.h:154
void s16_neon_scale(const ITensor *src, ITensor *dst, const ITensor *offsets, const ITensor *dx, const ITensor *dy, InterpolationPolicy policy, BorderMode border_mode, PixelValue constant_border_value, float sampling_offset, bool align_corners, const Window &window)
Definition: integer.cpp:279
void vstore(uint8_t *ptr, uint8x8_t val)
Definition: store.h:39
uint8x8_t vdup_n(uint8_t value, traits::vector_64_tag)
Definition: dup_n.h:41
void common_neon_scale(const ITensor *src, ITensor *dst, const ITensor *offsets, const ITensor *dx, const ITensor *dy, InterpolationPolicy policy, BorderMode border_mode, PixelValue constant_border_value, float sampling_offset, bool align_corners, const Window &window)
Definition: list.h:398
float calculate_resize_ratio(size_t input_size, size_t output_size, bool align_corners=false)
Returns resize ratio between input and output with consideration of aligned corners.
Definition: ScaleUtils.cpp:27
Includes all wrapper headers at once.
virtual const Strides & strides_in_bytes() const =0
The strides in bytes for accessing each dimension of the tensor.
uint8x8_t vmla(const uint8x8_t &a, const uint8x8_t &b, const uint8x8_t &c)
Definition: mla.h:46
constexpr int end() const
Return the end of the dimension.
Definition: Window.h:99
Iterator updated by execute_window_loop for each window element.
Definition: Helpers.h:46
constexpr int start() const
Return the start of the dimension.
Definition: Window.h:94
void qasymm8_neon_scale(const ITensor *src, ITensor *dst, const ITensor *offsets, const ITensor *dx, const ITensor *dy, InterpolationPolicy policy, BorderMode border_mode, PixelValue constant_border_value, float sampling_offset, bool align_corners, const Window &window)
Definition: qasymm8.cpp:131
Describe a multidimensional execution window.
Definition: Window.h:39