Compute Library
 20.05
Window.inl
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016-2020 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 namespace arm_compute
25 {
26 inline Window::Window(const Window &src)
27  : _dims(), _is_broadcasted(utility::generate_array<bool, Coordinates::num_max_dimensions, false>::value)
28 {
29  for(size_t i = 0; i < Coordinates::num_max_dimensions; ++i)
30  {
31  set(i, src[i]);
32  _is_broadcasted[i] = src.is_broadcasted(i);
33  }
34 }
35 
37 {
38  Window tmp(rhs);
39  swap(*this, tmp);
40  return *this;
41 }
42 
43 inline constexpr const Window::Dimension &Window::operator[](size_t dimension) const
44 {
45  // Precondition: dimension < Coordinates::num_max_dimensions
46  return _dims.at(dimension);
47 }
48 
49 inline void Window::set(size_t dimension, const Window::Dimension &dim)
50 {
52  _dims[dimension] = dim;
53 }
54 
55 inline void Window::set_broadcasted(size_t dimension)
56 {
58  set(dimension, Dimension(0, 0, 0));
59  _is_broadcasted[dimension] = true;
60 }
61 
62 inline bool Window::is_broadcasted(size_t dimension) const
63 {
65  return _is_broadcasted[dimension];
66 }
67 
68 inline Window Window::collapse_if_possible(const Window &full_window, const size_t first,
69  const size_t last, bool *has_collapsed) const
70 {
71  Window collapsed(*this);
72 
73  bool is_collapsable = true;
74  int collapsed_end = _dims[first].end();
75 
76  for(size_t d = first + 1; is_collapsable && (d < last); ++d)
77  {
78  // The _dims's dimension must match the full _dims dimension to be collapsable:
79  is_collapsable = (_dims[d].start() == 0) && (full_window[d].start() == 0) && (_dims[d].step() <= 1)
80  && (full_window[d].end() == _dims[d].end());
81  collapsed_end *= _dims[d].end();
82  }
83 
84  if(is_collapsable)
85  {
86  collapsed._dims.at(first).set_end(collapsed_end);
87  for(size_t d = first + 1; is_collapsable && (d < last); ++d)
88  {
89  collapsed.set(d, Dimension());
90  }
91  }
92 
93  if(has_collapsed != nullptr)
94  {
95  *has_collapsed = is_collapsable;
96  }
97 
98  return collapsed;
99 }
100 
101 inline Window Window::shift_dimensions(unsigned int shift_value) const
102 {
103  Window shifted_window;
104  for(size_t n = 0; n < (Coordinates::num_max_dimensions - shift_value); n++)
105  {
106  shifted_window.set(n, _dims[n + shift_value]);
107  }
108  return shifted_window;
109 }
110 
111 inline Window Window::collapse(const Window &full_window, const size_t first, const size_t last) const
112 {
113  bool has_collapsed = false;
114  Window collapsed = collapse_if_possible(full_window, first, last, &has_collapsed);
115  // Make sure that the window has collapsed
116  ARM_COMPUTE_ERROR_ON(!has_collapsed);
117  return collapsed;
118 }
119 
121 {
122  Window broadcastWin(*this);
123  for(size_t d = 0; d < TensorShape::num_max_dimensions; ++d)
124  {
125  if(shape[d] <= 1)
126  {
127  broadcastWin.set_broadcasted(d);
128  }
129  }
130  return broadcastWin;
131 }
132 
133 inline void Window::shift(size_t dimension, int shift_value)
134 {
136  Window::Dimension &d = _dims[dimension];
137  d = Window::Dimension(d.start() + shift_value, d.end() + shift_value, d.step());
138 }
139 
140 inline void Window::adjust(size_t dimension, int adjust_value, bool is_at_start)
141 {
143  Window::Dimension &d = _dims[dimension];
144 
145  if(is_at_start)
146  {
147  d = Window::Dimension(d.start() + adjust_value, d.end(), d.step());
148  }
149  else
150  {
151  d = Window::Dimension(d.start(), d.end() + adjust_value, d.step());
152  }
153 }
154 
155 inline void Window::scale(size_t dimension, float scale_value)
156 {
158  Window::Dimension &d = _dims[dimension];
159  const int scaled_step = d.step() * scale_value;
160  const int scaled_start = d.start() * scale_value;
161  const int scaled_diff = (d.end() - d.start()) * scale_value;
162  const int scaled_end = scaled_start + ceil_to_multiple(scaled_diff, scaled_step);
163 
164  d = Window::Dimension(scaled_start, scaled_end, scaled_step);
165 }
166 
167 inline void Window::set_dimension_step(size_t dimension, int step)
168 {
170  _dims[dimension].set_step(step);
171 }
172 
173 inline void Window::validate() const
174 {
175  for(size_t i = 0; i < Coordinates::num_max_dimensions; ++i)
176  {
177  ARM_COMPUTE_ERROR_ON(_dims[i].end() < _dims[i].start());
178  ARM_COMPUTE_ERROR_ON((_dims[i].step() != 0) && (((_dims[i].end() - _dims[i].start()) % _dims[i].step()) != 0));
179  }
180 }
181 
182 inline constexpr size_t Window::num_iterations(size_t dimension) const
183 {
184  // Precondition: dimension < Coordinates::num_max_dimensions
185  // Precondition: (end - start) % step == 0
186  return (_dims.at(dimension).end() - _dims.at(dimension).start()) / _dims.at(dimension).step();
187 }
188 
189 inline Window Window::split_window(size_t dimension, size_t id, size_t total) const
190 {
191  ARM_COMPUTE_ERROR_ON(id >= total);
193 
194  Window out;
195 
196  for(size_t d = 0; d < Coordinates::num_max_dimensions; ++d)
197  {
198  if(d == dimension)
199  {
200  int start = _dims[d].start();
201  int end = _dims[d].end();
202  const int step = _dims[d].step();
203 
204  const int num_it = num_iterations(d);
205  const int rem = num_it % total;
206  int work = num_it / total;
207 
208  int it_start = work * id;
209 
210  if(int(id) < rem)
211  {
212  ++work;
213  it_start += id;
214  }
215  else
216  {
217  it_start += rem;
218  }
219 
220  start += it_start * step;
221  end = std::min(end, start + work * step);
222 
223  out.set(d, Dimension(start, end, step));
224  }
225  else
226  {
227  out.set(d, _dims[d]);
228  }
229  }
230 
231  return out;
232 }
233 
234 template <unsigned int window_dimension>
235 inline bool Window::slide_window_slice(Window &slice) const
236 {
237  for(unsigned int n = window_dimension; n < Coordinates::num_max_dimensions; ++n)
238  {
239  // Did we reach the end of this dimension?
240  const int v = slice._dims[n].start() + 1;
241 
242  if(v < _dims[n].end())
243  {
244  // No: increment
245  slice._dims[n] = Dimension(v, v + 1, 1);
246 
247  // Reset lower dimensions:
248  for(unsigned int lower = window_dimension; lower < n; ++lower)
249  {
250  slice._dims[lower] = Dimension(_dims[lower].start(), _dims[lower].start() + 1, 1);
251  }
252  return true;
253  }
254  }
255 
256  // It was the last slice
257  return false; // Iteration over
258 }
259 
260 template <unsigned int window_dimension>
261 inline Window Window::first_slice_window() const
262 {
263  Window slice;
264 
265  std::copy_n(_dims.begin(), window_dimension, slice._dims.begin());
266 
267  //Initialise higher dimensions to be the first slice.
268  for(unsigned int n = window_dimension; n < Coordinates::num_max_dimensions; ++n)
269  {
270  slice._dims[n] = Dimension(_dims[n].start(), _dims[n].start() + 1, 1);
271  }
272 
273  return slice;
274 }
275 
276 inline void Window::use_tensor_dimensions(const TensorShape &shape, size_t first_dimension)
277 {
278  for(unsigned int n = first_dimension; n < shape.num_dimensions(); ++n)
279  {
280  set(n, Window::Dimension(0, std::max(shape[n], static_cast<uint32_t>(1))));
281  }
282 }
283 
285 {
287  for(size_t d = 0; d < TensorShape::num_max_dimensions; ++d)
288  {
289  shape.set(d, (_dims[d].end() - _dims[d].start()) / _dims[d].step());
290  }
291  return shape;
292 }
293 
294 inline size_t Window::num_iterations_total() const
295 {
296  size_t total = 1;
297  for(size_t d = 0; d < Coordinates::num_max_dimensions; ++d)
298  {
299  total *= num_iterations(d);
300  }
301  return total;
302 }
303 
304 inline void swap(Window &lhs, Window &rhs)
305 {
306  lhs._dims.swap(rhs._dims);
307 }
308 } // namespace arm_compute
void scale(size_t dimension, float scale_value)
Scale the values of a given dimension by the given scale_value.
Definition: Window.inl:155
Shape of a tensor.
Definition: TensorShape.h:39
void shift(size_t dimension, int shift_value)
Shift the values of a given dimension by the given shift_value.
Definition: Window.inl:133
constexpr int step() const
Return the step of the dimension.
Definition: Window.h:102
friend void swap(Window &lhs, Window &rhs)
Friend function that swaps the contents of two windows.
Definition: Window.inl:304
#define ARM_COMPUTE_ERROR_ON(cond)
If the condition is true then an error message is printed and an exception thrown.
Definition: Error.h:466
Window split_window(size_t dimension, size_t id, size_t total) const
Split a window into a set of sub windows along a given dimension.
Definition: Window.inl:189
Describe one of the image's dimensions with a start, end and step.
Definition: Window.h:75
void validate() const
Will validate all the window's dimensions' values when asserts are enabled.
Definition: Window.inl:173
constexpr size_t num_iterations(size_t dimension) const
Return the number of iterations needed to iterate through a given dimension.
Definition: Window.inl:182
void use_tensor_dimensions(const TensorShape &shape, size_t first_dimension=Window::DimX)
Use the tensor's dimensions to fill the window dimensions.
Definition: Window.inl:276
Copyright (c) 2017-2020 ARM Limited.
Window collapse(const Window &full_window, size_t first, size_t last=Coordinates::num_max_dimensions) const
Collapse the dimensions between first and last.
Definition: Window.inl:111
Window collapse_if_possible(const Window &full_window, size_t first, size_t last, bool *has_collapsed=nullptr) const
Collapse the dimensions between first and last if possible.
Definition: Window.inl:68
auto ceil_to_multiple(S value, T divisor) -> decltype(((value+divisor - 1)/divisor) *divisor)
Computes the smallest number larger or equal to value that is a multiple of divisor.
Definition: Utils.h:67
Coordinates of an item.
Definition: Coordinates.h:37
Window & operator=(const Window &rhs)
Copy assignment operator.
Definition: Window.inl:36
constexpr const Dimension & operator[](size_t dimension) const
Read only access to a given dimension of the window.
Definition: Window.inl:43
constexpr Window()
Default constructor: create a window containing a single element.
Definition: Window.h:50
void set(size_t dimension, const Dimension &dim)
Set the values of a given dimension.
Definition: Window.inl:49
Window broadcast_if_dimension_le_one(const TensorShape &shape) const
Don't advance in the dimension where shape is less equal to 1.
Definition: Window.inl:120
bool is_broadcasted(size_t dimension) const
Return whether a dimension has been broadcasted.
Definition: Window.inl:62
void set_dimension_step(size_t dimension, int step)
Set the step of a given dimension.
Definition: Window.inl:167
unsigned int num_dimensions() const
Returns the effective dimensionality of the tensor.
Definition: Dimensions.h:122
TensorShape shape() const
Return the shape of the window in number of steps.
Definition: Window.inl:284
TensorShape & set(size_t dimension, size_t value, bool apply_dim_correction=true)
Accessor to set the value of one of the dimensions.
Definition: TensorShape.h:78
constexpr int end() const
Return the end of the dimension.
Definition: Window.h:97
void adjust(size_t dimension, int adjust_value, bool is_at_start)
Adjust the start or end of a given dimension by the given value.
Definition: Window.inl:140
void set_broadcasted(size_t dimension)
Set the dimension as broadcasted dimension.
Definition: Window.inl:55
static constexpr size_t num_max_dimensions
Number of dimensions the tensor has.
Definition: Dimensions.h:45
void swap(Window &lhs, Window &rhs)
Definition: Window.inl:304
constexpr int start() const
Return the start of the dimension.
Definition: Window.h:92
size_t num_iterations_total() const
Return the total number of iterations needed to iterate through the entire window.
Definition: Window.inl:294
Describe a multidimensional execution window.
Definition: Window.h:39
Window shift_dimensions(unsigned int shift_value) const
Shift down all the dimensions of a window.
Definition: Window.inl:101
cast configure & src
Definition: Cast.cpp:169
SimpleTensor< T > slice(const SimpleTensor< T > &src, Coordinates starts, Coordinates ends)