Compute Library
 19.08
Window.inl
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016-2019 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()
28 {
29  for(size_t i = 0; i < Coordinates::num_max_dimensions; ++i)
30  {
31  set(i, src[i]);
32  }
33 }
34 
36 {
37  Window tmp(rhs);
38  swap(*this, tmp);
39  return *this;
40 }
41 
42 inline constexpr const Window::Dimension &Window::operator[](size_t dimension) const
43 {
44  // Precondition: dimension < Coordinates::num_max_dimensions
45  return _dims.at(dimension);
46 }
47 
48 inline void Window::set(size_t dimension, const Window::Dimension &dim)
49 {
51  _dims[dimension] = dim;
52 }
53 
54 inline Window Window::collapse_if_possible(const Window &full_window, const size_t first,
55  const size_t last, bool *has_collapsed) const
56 {
57  Window collapsed(*this);
58 
59  bool is_collapsable = true;
60  int collapsed_end = _dims[first].end();
61 
62  for(size_t d = first + 1; is_collapsable && (d < last); ++d)
63  {
64  // The _dims's dimension must match the full _dims dimension to be collapsable:
65  is_collapsable = (_dims[d].start() == 0) && (full_window[d].start() == 0) && (_dims[d].step() <= 1)
66  && (full_window[d].end() == _dims[d].end());
67  collapsed_end *= _dims[d].end();
68  }
69 
70  if(is_collapsable)
71  {
72  collapsed._dims.at(first).set_end(collapsed_end);
73  for(size_t d = first + 1; is_collapsable && (d < last); ++d)
74  {
75  collapsed.set(d, Dimension());
76  }
77  }
78 
79  if(has_collapsed != nullptr)
80  {
81  *has_collapsed = is_collapsable;
82  }
83 
84  return collapsed;
85 }
86 
87 inline Window Window::shift_dimensions(unsigned int shift_value) const
88 {
89  Window shifted_window;
90  for(size_t n = 0; n < (Coordinates::num_max_dimensions - shift_value); n++)
91  {
92  shifted_window.set(n, _dims[n + shift_value]);
93  }
94  return shifted_window;
95 }
96 
97 inline Window Window::collapse(const Window &full_window, const size_t first, const size_t last) const
98 {
99  bool has_collapsed = false;
100  Window collapsed = collapse_if_possible(full_window, first, last, &has_collapsed);
101  // Make sure that the window has collapsed
102  ARM_COMPUTE_ERROR_ON(!has_collapsed);
103  return collapsed;
104 }
105 
107 {
108  Window broadcastWin(*this);
109  for(size_t d = 0; d < TensorShape::num_max_dimensions; ++d)
110  {
111  if(shape[d] <= 1)
112  {
113  broadcastWin.set(d, Dimension(0, 0, 0));
114  }
115  }
116  return broadcastWin;
117 }
118 
119 inline void Window::shift(size_t dimension, int shift_value)
120 {
122  Window::Dimension &d = _dims[dimension];
123  d = Window::Dimension(d.start() + shift_value, d.end() + shift_value, d.step());
124 }
125 
126 inline void Window::adjust(size_t dimension, int adjust_value, bool is_at_start)
127 {
129  Window::Dimension &d = _dims[dimension];
130 
131  if(is_at_start)
132  {
133  d = Window::Dimension(d.start() + adjust_value, d.end(), d.step());
134  }
135  else
136  {
137  d = Window::Dimension(d.start(), d.end() + adjust_value, d.step());
138  }
139 }
140 
141 inline void Window::scale(size_t dimension, float scale_value)
142 {
144  Window::Dimension &d = _dims[dimension];
145  const int scaled_step = d.step() * scale_value;
146  const int scaled_start = d.start() * scale_value;
147  const int scaled_diff = (d.end() - d.start()) * scale_value;
148  const int scaled_end = scaled_start + ceil_to_multiple(scaled_diff, scaled_step);
149 
150  d = Window::Dimension(scaled_start, scaled_end, scaled_step);
151 }
152 
153 inline void Window::set_dimension_step(size_t dimension, int step)
154 {
156  _dims[dimension].set_step(step);
157 }
158 
159 inline void Window::validate() const
160 {
161  for(size_t i = 0; i < Coordinates::num_max_dimensions; ++i)
162  {
163  ARM_COMPUTE_ERROR_ON(_dims[i].end() < _dims[i].start());
164  ARM_COMPUTE_ERROR_ON((_dims[i].step() != 0) && (((_dims[i].end() - _dims[i].start()) % _dims[i].step()) != 0));
165  }
166 }
167 
168 inline constexpr size_t Window::num_iterations(size_t dimension) const
169 {
170  // Precondition: dimension < Coordinates::num_max_dimensions
171  // Precondition: (end - start) % step == 0
172  return (_dims.at(dimension).end() - _dims.at(dimension).start()) / _dims.at(dimension).step();
173 }
174 
175 inline Window Window::split_window(size_t dimension, size_t id, size_t total) const
176 {
177  ARM_COMPUTE_ERROR_ON(id >= total);
179 
180  Window out;
181 
182  for(size_t d = 0; d < Coordinates::num_max_dimensions; ++d)
183  {
184  if(d == dimension)
185  {
186  int start = _dims[d].start();
187  int end = _dims[d].end();
188  int per_sub_window = (num_iterations(d) / total) * _dims[d].step();
189 
190  start += id * per_sub_window;
191 
192  if(id != total - 1)
193  {
194  end = start + per_sub_window;
195  }
196 
197  out.set(d, Dimension(start, end, _dims[d].step()));
198  }
199  else
200  {
201  out.set(d, _dims[d]);
202  }
203  }
204 
205  return out;
206 }
207 
208 template <unsigned int window_dimension>
209 inline bool Window::slide_window_slice(Window &slice) const
210 {
211  for(unsigned int n = window_dimension; n < Coordinates::num_max_dimensions; ++n)
212  {
213  // Did we reach the end of this dimension?
214  const int v = slice._dims[n].start() + 1;
215 
216  if(v < _dims[n].end())
217  {
218  // No: increment
219  slice._dims[n] = Dimension(v, v + 1, 1);
220 
221  // Reset lower dimensions:
222  for(unsigned int lower = window_dimension; lower < n; ++lower)
223  {
224  slice._dims[lower] = Dimension(_dims[lower].start(), _dims[lower].start() + 1, 1);
225  }
226  return true;
227  }
228  }
229 
230  // It was the last slice
231  return false; // Iteration over
232 }
233 
234 template <unsigned int window_dimension>
235 inline Window Window::first_slice_window() const
236 {
237  Window slice;
238 
239  std::copy_n(_dims.begin(), window_dimension, slice._dims.begin());
240 
241  //Initialise higher dimensions to be the first slice.
242  for(unsigned int n = window_dimension; n < Coordinates::num_max_dimensions; ++n)
243  {
244  slice._dims[n] = Dimension(_dims[n].start(), _dims[n].start() + 1, 1);
245  }
246 
247  return slice;
248 }
249 
250 inline void Window::use_tensor_dimensions(const TensorShape &shape, size_t first_dimension)
251 {
252  for(unsigned int n = first_dimension; n < shape.num_dimensions(); ++n)
253  {
254  set(n, Window::Dimension(0, std::max(shape[n], static_cast<size_t>(1))));
255  }
256 }
257 
259 {
261  for(size_t d = 0; d < TensorShape::num_max_dimensions; ++d)
262  {
263  shape.set(d, (_dims[d].end() - _dims[d].start()) / _dims[d].step());
264  }
265  return shape;
266 }
267 
268 inline size_t Window::num_iterations_total() const
269 {
270  size_t total = 1;
271  for(size_t d = 0; d < Coordinates::num_max_dimensions; ++d)
272  {
273  total *= num_iterations(d);
274  }
275  return total;
276 }
277 
278 inline void swap(Window &lhs, Window &rhs)
279 {
280  lhs._dims.swap(rhs._dims);
281 }
282 } // 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:141
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:119
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:278
#define ARM_COMPUTE_ERROR_ON(cond)
If the condition is true then an error message is printed and an exception thrown.
Definition: Error.h:337
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:175
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:159
constexpr size_t num_iterations(size_t dimension) const
Return the number of iterations needed to iterate through a given dimension.
Definition: Window.inl:168
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:250
Copyright (c) 2017-2018 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:97
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:54
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:66
Window & operator=(const Window &rhs)
Copy assignment operator.
Definition: Window.inl:35
constexpr const Dimension & operator[](size_t dimension) const
Read only access to a given dimension of the window.
Definition: Window.inl:42
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:48
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:106
void set_dimension_step(size_t dimension, int step)
Set the step of a given dimension.
Definition: Window.inl:153
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:258
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:126
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:278
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:268
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:87
cast configure & src
Definition: Cast.cpp:169
SimpleTensor< T > slice(const SimpleTensor< T > &src, Coordinates starts, Coordinates ends)