blob: 1b21820f900ec78d0bd32c3042fe1d355f05ddbe [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
2 * Copyright (c) 2016, 2017 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 */
24namespace arm_compute
25{
26inline Window::Window(const Window &src)
Moritz Pflanzerc186b572017-09-07 09:48:04 +010027 : _dims()
Anthony Barbier6ff3b192017-09-04 18:44:23 +010028{
29 for(size_t i = 0; i < Coordinates::num_max_dimensions; ++i)
30 {
31 set(i, src[i]);
32 }
33}
34
Moritz Pflanzerc186b572017-09-07 09:48:04 +010035inline constexpr const Window::Dimension &Window::operator[](size_t dimension) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +010036{
37 // Precondition: dimension < Coordinates::num_max_dimensions
38 return _dims.at(dimension);
39}
Moritz Pflanzerc186b572017-09-07 09:48:04 +010040inline void Window::set(size_t dimension, const Window::Dimension &dim)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010041{
42 ARM_COMPUTE_ERROR_ON(dimension >= Coordinates::num_max_dimensions);
43 _dims[dimension] = dim;
44}
45
Anthony Barbierbe35b0e2017-07-11 18:13:08 +010046inline Window Window::collapse_if_possible(const Window &full_window, size_t first) const
47{
48 bool is_collapsable = false;
49 Window collapsed;
50 for(size_t d = 0; d < Coordinates::num_max_dimensions; ++d)
51 {
52 if(is_collapsable)
53 {
54 collapsed.set(first, Window::Dimension(collapsed[first].end() * _dims[d].start(), collapsed[first].end() * _dims[d].end()));
55 }
56 else
57 {
58 collapsed.set(d, _dims[d]);
59 }
60
61 if(is_collapsable || d == first) // Try to start collapsing from this dimension
62 {
63 // The _dims's dimension must match the full _dims dimension to be collapsable:
64 is_collapsable = _dims[d].start() == 0 && _dims[d].start() == full_window[d].start()
65 && full_window[d].end() == _dims[d].end();
66 }
67 else
68 {
69 is_collapsable = false;
70 }
71 }
72 return collapsed;
73}
74
Michalis Spyrou5237e012018-01-17 09:40:27 +000075inline Window Window::collapse(const Window &full_window, size_t first) const
76{
77 Window collapsed = collapse_if_possible(full_window, first);
78 // Make sure that the window has collapsed
79 int end = _dims[first].end();
80 int start = 0;
81 ARM_COMPUTE_UNUSED(start);
82 for(size_t d = first + 1; d < Coordinates::num_max_dimensions; ++d)
83 {
84 start = end * _dims[d].start();
85 end *= _dims[d].end();
86 }
87 ARM_COMPUTE_ERROR_ON((collapsed[first].end() != end) || (collapsed[first].start() != start));
88 return collapsed;
89}
90
Moritz Pflanzerc186b572017-09-07 09:48:04 +010091inline void Window::shift(size_t dimension, int shift_value)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010092{
93 ARM_COMPUTE_ERROR_ON(dimension >= Coordinates::num_max_dimensions);
94 Window::Dimension &d = _dims[dimension];
95 d = Window::Dimension(d.start() + shift_value, d.end() + shift_value, d.step());
96}
97
98inline void Window::adjust(size_t dimension, int adjust_value, bool is_at_start)
99{
100 ARM_COMPUTE_ERROR_ON(dimension >= Coordinates::num_max_dimensions);
101 Window::Dimension &d = _dims[dimension];
102
103 if(is_at_start)
104 {
105 d = Window::Dimension(d.start() + adjust_value, d.end(), d.step());
106 }
107 else
108 {
109 d = Window::Dimension(d.start(), d.end() + adjust_value, d.step());
110 }
111}
112
Moritz Pflanzerc186b572017-09-07 09:48:04 +0100113inline void Window::scale(size_t dimension, float scale_value)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100114{
115 ARM_COMPUTE_ERROR_ON(dimension >= Coordinates::num_max_dimensions);
116 Window::Dimension &d = _dims[dimension];
117 const int scaled_step = d.step() * scale_value;
118 const int scaled_end = ceil_to_multiple(d.end() * scale_value, scaled_step);
119 d = Window::Dimension(d.start() * scale_value, scaled_end, scaled_step);
120}
121
Moritz Pflanzerc186b572017-09-07 09:48:04 +0100122inline void Window::set_dimension_step(size_t dimension, int step)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100123{
124 ARM_COMPUTE_ERROR_ON(dimension >= Coordinates::num_max_dimensions);
125 _dims[dimension].set_step(step);
126}
127
128inline void Window::validate() const
129{
130 for(size_t i = 0; i < Coordinates::num_max_dimensions; ++i)
131 {
132 ARM_COMPUTE_ERROR_ON(_dims[i].step() == 0);
Moritz Pflanzer6c6597c2017-09-24 12:09:41 +0100133 ARM_COMPUTE_ERROR_ON(_dims[i].end() < _dims[i].start());
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100134 ARM_COMPUTE_ERROR_ON((_dims[i].end() - _dims[i].start()) % _dims[i].step());
135 }
136}
137
138inline constexpr size_t Window::num_iterations(size_t dimension) const
139{
140 // Precondition: dimension < Coordinates::num_max_dimensions
141 // Precondition: (end - start) % step == 0
142 return (_dims.at(dimension).end() - _dims.at(dimension).start()) / _dims.at(dimension).step();
143}
144
Moritz Pflanzerc186b572017-09-07 09:48:04 +0100145inline Window Window::split_window(size_t dimension, size_t id, size_t total) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100146{
147 ARM_COMPUTE_ERROR_ON(id >= total);
148 ARM_COMPUTE_ERROR_ON(dimension >= Coordinates::num_max_dimensions);
149
150 Window out;
151
152 for(size_t d = 0; d < Coordinates::num_max_dimensions; ++d)
153 {
154 if(d == dimension)
155 {
156 int start = _dims[d].start();
157 int end = _dims[d].end();
158 int per_sub_window = (num_iterations(d) / total) * _dims[d].step();
159
160 start += id * per_sub_window;
161
162 if(id != total - 1)
163 {
164 end = start + per_sub_window;
165 }
166
167 out.set(d, Dimension(start, end, _dims[d].step()));
168 }
169 else
170 {
171 out.set(d, _dims[d]);
172 }
173 }
174
175 return out;
176}
177
178template <unsigned int window_dimension>
179inline bool Window::slide_window_slice(Window &slice) const
180{
181 for(unsigned int n = window_dimension; n < Coordinates::num_max_dimensions; ++n)
182 {
183 // Did we reach the end of this dimension?
184 const int v = slice._dims[n].start() + 1;
185
186 if(v < _dims[n].end())
187 {
188 // No: increment
189 slice._dims[n] = Dimension(v, v + 1, 1);
190
191 // Reset lower dimensions:
192 for(unsigned int lower = window_dimension; lower < n; ++lower)
193 {
194 slice._dims[lower] = Dimension(_dims[lower].start(), _dims[lower].start() + 1, 1);
195 }
196 return true;
197 }
198 }
199
200 // It was the last slice
201 return false; // Iteration over
202}
203
204template <unsigned int window_dimension>
205inline Window Window::first_slice_window() const
206{
207 Window slice;
208
209 std::copy_n(_dims.begin(), window_dimension, slice._dims.begin());
210
211 //Initialise higher dimensions to be the first slice.
212 for(unsigned int n = window_dimension; n < Coordinates::num_max_dimensions; ++n)
213 {
214 slice._dims[n] = Dimension(_dims[n].start(), _dims[n].start() + 1, 1);
215 }
216
217 return slice;
218}
219
SiCong Li86b53332017-08-23 11:02:43 +0100220inline void Window::use_tensor_dimensions(const TensorShape &shape, size_t first_dimension)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100221{
SiCong Li86b53332017-08-23 11:02:43 +0100222 for(unsigned int n = first_dimension; n < shape.num_dimensions(); ++n)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100223 {
SiCong Li86b53332017-08-23 11:02:43 +0100224 set(n, Window::Dimension(0, std::max(shape[n], static_cast<size_t>(1))));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100225 }
226}
227}