arm_compute v17.10
[platform/upstream/armcl.git] / tests / SimpleTensor.h
1 /*
2  * Copyright (c) 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  */
24 #ifndef __ARM_COMPUTE_TEST_SIMPLE_TENSOR_H__
25 #define __ARM_COMPUTE_TEST_SIMPLE_TENSOR_H__
26
27 #include "arm_compute/core/TensorShape.h"
28 #include "arm_compute/core/Types.h"
29 #include "arm_compute/core/Utils.h"
30 #include "support/ToolchainSupport.h"
31 #include "tests/IAccessor.h"
32 #include "tests/Utils.h"
33
34 #include <algorithm>
35 #include <array>
36 #include <cstddef>
37 #include <cstdint>
38 #include <functional>
39 #include <memory>
40 #include <stdexcept>
41 #include <utility>
42
43 namespace arm_compute
44 {
45 namespace test
46 {
47 class RawTensor;
48
49 /** Simple tensor object that stores elements in a consecutive chunk of memory.
50  *
51  * It can be created by either loading an image from a file which also
52  * initialises the content of the tensor or by explcitly specifying the size.
53  * The latter leaves the content uninitialised.
54  *
55  * Furthermore, the class provides methods to convert the tensor's values into
56  * different image format.
57  */
58 template <typename T>
59 class SimpleTensor : public IAccessor
60 {
61 public:
62     /** Create an uninitialised tensor. */
63     SimpleTensor() = default;
64
65     /** Create an uninitialised tensor of the given @p shape and @p format.
66      *
67      * @param[in] shape                Shape of the new raw tensor.
68      * @param[in] format               Format of the new raw tensor.
69      * @param[in] fixed_point_position (Optional) Number of bits for the fractional part of the fixed point numbers
70      */
71     SimpleTensor(TensorShape shape, Format format, int fixed_point_position = 0);
72
73     /** Create an uninitialised tensor of the given @p shape and @p data type.
74      *
75      * @param[in] shape                Shape of the new raw tensor.
76      * @param[in] data_type            Data type of the new raw tensor.
77      * @param[in] num_channels         (Optional) Number of channels (default = 1).
78      * @param[in] fixed_point_position (Optional) Number of bits for the fractional part of the fixed point numbers (default = 0).
79      */
80     SimpleTensor(TensorShape shape, DataType data_type, int num_channels = 1, int fixed_point_position = 0);
81
82     /** Create a deep copy of the given @p tensor.
83      *
84      * @param[in] tensor To be copied tensor.
85      */
86     SimpleTensor(const SimpleTensor &tensor);
87
88     /** Create a deep copy of the given @p tensor.
89      *
90      * @param[in] tensor To be copied tensor.
91      */
92     SimpleTensor &operator        =(SimpleTensor tensor);
93     SimpleTensor(SimpleTensor &&) = default;
94     ~SimpleTensor()               = default;
95
96     using value_type = T;
97     using Buffer     = std::unique_ptr<value_type[]>;
98
99     friend class RawTensor;
100
101     /** Return value at @p offset in the buffer.
102      *
103      * @param[in] offset Offset within the buffer.
104      */
105     T &operator[](size_t offset);
106
107     /** Return constant value at @p offset in the buffer.
108      *
109      * @param[in] offset Offset within the buffer.
110      */
111     const T &operator[](size_t offset) const;
112
113     /** Shape of the tensor. */
114     TensorShape shape() const override;
115
116     /** Size of each element in the tensor in bytes. */
117     size_t element_size() const override;
118
119     /** Total size of the tensor in bytes. */
120     size_t size() const override;
121
122     /** Image format of the tensor. */
123     Format format() const override;
124
125     /** Data type of the tensor. */
126     DataType data_type() const override;
127
128     /** Number of channels of the tensor. */
129     int num_channels() const override;
130
131     /** Number of elements of the tensor. */
132     int num_elements() const override;
133
134     /** Available padding around the tensor. */
135     PaddingSize padding() const override;
136
137     /** The number of bits for the fractional part of the fixed point numbers. */
138     int fixed_point_position() const override;
139
140     /** Constant pointer to the underlying buffer. */
141     const T *data() const;
142
143     /** Pointer to the underlying buffer. */
144     T *data();
145
146     /** Read only access to the specified element.
147      *
148      * @param[in] coord Coordinates of the desired element.
149      *
150      * @return A pointer to the desired element.
151      */
152     const void *operator()(const Coordinates &coord) const override;
153
154     /** Access to the specified element.
155      *
156      * @param[in] coord Coordinates of the desired element.
157      *
158      * @return A pointer to the desired element.
159      */
160     void *operator()(const Coordinates &coord) override;
161
162     /** Swaps the content of the provided tensors.
163      *
164      * @param[in, out] tensor1 Tensor to be swapped.
165      * @param[in, out] tensor2 Tensor to be swapped.
166      */
167     template <typename U>
168     friend void swap(SimpleTensor<U> &tensor1, SimpleTensor<U> &tensor2);
169
170 protected:
171     Buffer      _buffer{ nullptr };
172     TensorShape _shape{};
173     Format      _format{ Format::UNKNOWN };
174     DataType    _data_type{ DataType::UNKNOWN };
175     int         _num_channels{ 0 };
176     int         _fixed_point_position{ 0 };
177 };
178
179 template <typename T>
180 SimpleTensor<T>::SimpleTensor(TensorShape shape, Format format, int fixed_point_position)
181     : _buffer(nullptr),
182       _shape(shape),
183       _format(format),
184       _fixed_point_position(fixed_point_position)
185 {
186     _buffer = support::cpp14::make_unique<T[]>(num_elements() * num_channels());
187 }
188
189 template <typename T>
190 SimpleTensor<T>::SimpleTensor(TensorShape shape, DataType data_type, int num_channels, int fixed_point_position)
191     : _buffer(nullptr),
192       _shape(shape),
193       _data_type(data_type),
194       _num_channels(num_channels),
195       _fixed_point_position(fixed_point_position)
196 {
197     _buffer = support::cpp14::make_unique<T[]>(num_elements() * this->num_channels());
198 }
199
200 template <typename T>
201 SimpleTensor<T>::SimpleTensor(const SimpleTensor &tensor)
202     : _buffer(nullptr),
203       _shape(tensor.shape()),
204       _format(tensor.format()),
205       _data_type(tensor.data_type()),
206       _num_channels(tensor.num_channels()),
207       _fixed_point_position(tensor.fixed_point_position())
208 {
209     _buffer = support::cpp14::make_unique<T[]>(tensor.num_elements() * num_channels());
210     std::copy_n(tensor.data(), num_elements() * num_channels(), _buffer.get());
211 }
212
213 template <typename T>
214 SimpleTensor<T> &SimpleTensor<T>::operator=(SimpleTensor tensor)
215 {
216     swap(*this, tensor);
217
218     return *this;
219 }
220
221 template <typename T>
222 T &SimpleTensor<T>::operator[](size_t offset)
223 {
224     return _buffer[offset];
225 }
226
227 template <typename T>
228 const T &SimpleTensor<T>::operator[](size_t offset) const
229 {
230     return _buffer[offset];
231 }
232
233 template <typename T>
234 TensorShape SimpleTensor<T>::shape() const
235 {
236     return _shape;
237 }
238
239 template <typename T>
240 size_t SimpleTensor<T>::element_size() const
241 {
242     return num_channels() * element_size_from_data_type(data_type());
243 }
244
245 template <typename T>
246 int SimpleTensor<T>::fixed_point_position() const
247 {
248     return _fixed_point_position;
249 }
250
251 template <typename T>
252 size_t SimpleTensor<T>::size() const
253 {
254     const size_t size = std::accumulate(_shape.cbegin(), _shape.cend(), 1, std::multiplies<size_t>());
255     return size * element_size();
256 }
257
258 template <typename T>
259 Format SimpleTensor<T>::format() const
260 {
261     return _format;
262 }
263
264 template <typename T>
265 DataType SimpleTensor<T>::data_type() const
266 {
267     if(_format != Format::UNKNOWN)
268     {
269         return data_type_from_format(_format);
270     }
271     else
272     {
273         return _data_type;
274     }
275 }
276
277 template <typename T>
278 int SimpleTensor<T>::num_channels() const
279 {
280     switch(_format)
281     {
282         case Format::U8:
283         case Format::S16:
284         case Format::U16:
285         case Format::S32:
286         case Format::U32:
287         case Format::F32:
288             return 1;
289         case Format::RGB888:
290             return 3;
291         case Format::UNKNOWN:
292             return _num_channels;
293         default:
294             ARM_COMPUTE_ERROR("NOT SUPPORTED!");
295     }
296 }
297
298 template <typename T>
299 int SimpleTensor<T>::num_elements() const
300 {
301     return _shape.total_size();
302 }
303
304 template <typename T>
305 PaddingSize SimpleTensor<T>::padding() const
306 {
307     return PaddingSize(0);
308 }
309
310 template <typename T>
311 const T *SimpleTensor<T>::data() const
312 {
313     return _buffer.get();
314 }
315
316 template <typename T>
317 T *SimpleTensor<T>::data()
318 {
319     return _buffer.get();
320 }
321
322 template <typename T>
323 const void *SimpleTensor<T>::operator()(const Coordinates &coord) const
324 {
325     return _buffer.get() + coord2index(_shape, coord);
326 }
327
328 template <typename T>
329 void *SimpleTensor<T>::operator()(const Coordinates &coord)
330 {
331     return _buffer.get() + coord2index(_shape, coord);
332 }
333
334 template <typename U>
335 void swap(SimpleTensor<U> &tensor1, SimpleTensor<U> &tensor2)
336 {
337     // Use unqualified call to swap to enable ADL. But make std::swap available
338     // as backup.
339     using std::swap;
340     swap(tensor1._shape, tensor2._shape);
341     swap(tensor1._format, tensor2._format);
342     swap(tensor1._data_type, tensor2._data_type);
343     swap(tensor1._num_channels, tensor2._num_channels);
344     swap(tensor1._buffer, tensor2._buffer);
345 }
346 } // namespace test
347 } // namespace arm_compute
348 #endif /* __ARM_COMPUTE_TEST_SIMPLE_TENSOR_H__ */