blob: 75428a145bf26ddca78bbd8189c20f337f260967 [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)
27 : _dims(), _thread_id(src._thread_id), _num_threads(src._num_threads)
28{
29 for(size_t i = 0; i < Coordinates::num_max_dimensions; ++i)
30 {
31 set(i, src[i]);
32 }
33}
34
35inline constexpr const Window::Dimension &Window::operator[](const size_t dimension) const
36{
37 // Precondition: dimension < Coordinates::num_max_dimensions
38 return _dims.at(dimension);
39}
40inline void Window::set(const size_t dimension, const Window::Dimension &dim)
41{
42 ARM_COMPUTE_ERROR_ON(dimension >= Coordinates::num_max_dimensions);
43 _dims[dimension] = dim;
44}
45
46inline void Window::shift(const size_t dimension, const int shift_value)
47{
48 ARM_COMPUTE_ERROR_ON(dimension >= Coordinates::num_max_dimensions);
49 Window::Dimension &d = _dims[dimension];
50 d = Window::Dimension(d.start() + shift_value, d.end() + shift_value, d.step());
51}
52
53inline void Window::adjust(size_t dimension, int adjust_value, bool is_at_start)
54{
55 ARM_COMPUTE_ERROR_ON(dimension >= Coordinates::num_max_dimensions);
56 Window::Dimension &d = _dims[dimension];
57
58 if(is_at_start)
59 {
60 d = Window::Dimension(d.start() + adjust_value, d.end(), d.step());
61 }
62 else
63 {
64 d = Window::Dimension(d.start(), d.end() + adjust_value, d.step());
65 }
66}
67
68inline void Window::scale(const size_t dimension, float scale_value)
69{
70 ARM_COMPUTE_ERROR_ON(dimension >= Coordinates::num_max_dimensions);
71 Window::Dimension &d = _dims[dimension];
72 const int scaled_step = d.step() * scale_value;
73 const int scaled_end = ceil_to_multiple(d.end() * scale_value, scaled_step);
74 d = Window::Dimension(d.start() * scale_value, scaled_end, scaled_step);
75}
76
77inline void Window::set_dimension_step(const size_t dimension, const int step)
78{
79 ARM_COMPUTE_ERROR_ON(dimension >= Coordinates::num_max_dimensions);
80 _dims[dimension].set_step(step);
81}
82
83inline void Window::validate() const
84{
85 for(size_t i = 0; i < Coordinates::num_max_dimensions; ++i)
86 {
87 ARM_COMPUTE_ERROR_ON(_dims[i].step() == 0);
88 ARM_COMPUTE_ERROR_ON(_dims[i].end() <= _dims[i].start());
89 ARM_COMPUTE_ERROR_ON((_dims[i].end() - _dims[i].start()) % _dims[i].step());
90 }
91}
92
93inline constexpr size_t Window::num_iterations(size_t dimension) const
94{
95 // Precondition: dimension < Coordinates::num_max_dimensions
96 // Precondition: (end - start) % step == 0
97 return (_dims.at(dimension).end() - _dims.at(dimension).start()) / _dims.at(dimension).step();
98}
99
100inline Window Window::split_window(const size_t dimension, const size_t id, const size_t total) const
101{
102 ARM_COMPUTE_ERROR_ON(id >= total);
103 ARM_COMPUTE_ERROR_ON(dimension >= Coordinates::num_max_dimensions);
104
105 Window out;
106
107 for(size_t d = 0; d < Coordinates::num_max_dimensions; ++d)
108 {
109 if(d == dimension)
110 {
111 int start = _dims[d].start();
112 int end = _dims[d].end();
113 int per_sub_window = (num_iterations(d) / total) * _dims[d].step();
114
115 start += id * per_sub_window;
116
117 if(id != total - 1)
118 {
119 end = start + per_sub_window;
120 }
121
122 out.set(d, Dimension(start, end, _dims[d].step()));
123 }
124 else
125 {
126 out.set(d, _dims[d]);
127 }
128 }
129
130 return out;
131}
132
133template <unsigned int window_dimension>
134inline bool Window::slide_window_slice(Window &slice) const
135{
136 for(unsigned int n = window_dimension; n < Coordinates::num_max_dimensions; ++n)
137 {
138 // Did we reach the end of this dimension?
139 const int v = slice._dims[n].start() + 1;
140
141 if(v < _dims[n].end())
142 {
143 // No: increment
144 slice._dims[n] = Dimension(v, v + 1, 1);
145
146 // Reset lower dimensions:
147 for(unsigned int lower = window_dimension; lower < n; ++lower)
148 {
149 slice._dims[lower] = Dimension(_dims[lower].start(), _dims[lower].start() + 1, 1);
150 }
151 return true;
152 }
153 }
154
155 // It was the last slice
156 return false; // Iteration over
157}
158
159template <unsigned int window_dimension>
160inline Window Window::first_slice_window() const
161{
162 Window slice;
163
164 std::copy_n(_dims.begin(), window_dimension, slice._dims.begin());
165
166 //Initialise higher dimensions to be the first slice.
167 for(unsigned int n = window_dimension; n < Coordinates::num_max_dimensions; ++n)
168 {
169 slice._dims[n] = Dimension(_dims[n].start(), _dims[n].start() + 1, 1);
170 }
171
172 return slice;
173}
174
175inline void Window::use_tensor_dimensions(const ITensorInfo *info, const size_t first_dimension)
176{
177 for(unsigned int n = first_dimension; n < info->num_dimensions(); ++n)
178 {
179 set(n, Window::Dimension(0, std::max(info->dimension(n), static_cast<size_t>(1))));
180 }
181}
182}