blob: c4892748f4944ad0f546ba9f771f3fe82cbdd1b8 [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
Georgios Pinitas587708b2018-12-31 15:43:52 +00002 * Copyright (c) 2017-2019 ARM Limited.
Anthony Barbier6ff3b192017-09-04 18:44:23 +01003 *
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 */
Michalis Spyrouf4643372019-11-29 16:17:13 +000024#ifndef ARM_COMPUTE_TEST_TENSOR_LIBRARY_H
25#define ARM_COMPUTE_TEST_TENSOR_LIBRARY_H
Anthony Barbier6ff3b192017-09-04 18:44:23 +010026
Anthony Barbier6ff3b192017-09-04 18:44:23 +010027#include "arm_compute/core/Coordinates.h"
28#include "arm_compute/core/Error.h"
29#include "arm_compute/core/Helpers.h"
30#include "arm_compute/core/TensorInfo.h"
31#include "arm_compute/core/TensorShape.h"
32#include "arm_compute/core/Types.h"
33#include "arm_compute/core/Window.h"
Georgios Pinitas587708b2018-12-31 15:43:52 +000034#include "arm_compute/core/utils/misc/Random.h"
Michalis Spyrou6bff1952019-10-02 17:22:11 +010035#pragma GCC diagnostic push
36#pragma GCC diagnostic ignored "-Wunused-parameter"
SiCong Li86b53332017-08-23 11:02:43 +010037#include "libnpy/npy.hpp"
Michalis Spyrou6bff1952019-10-02 17:22:11 +010038#pragma GCC diagnostic pop
Moritz Pflanzere49e2662017-07-21 15:55:28 +010039#include "tests/RawTensor.h"
40#include "tests/TensorCache.h"
41#include "tests/Utils.h"
Anthony Barbierf6705ec2017-09-28 12:01:10 +010042#include "tests/framework/Exceptions.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010043
44#include <algorithm>
45#include <cstddef>
46#include <fstream>
47#include <random>
48#include <string>
49#include <type_traits>
SiCong Li86b53332017-08-23 11:02:43 +010050#include <vector>
Anthony Barbier6ff3b192017-09-04 18:44:23 +010051
52namespace arm_compute
53{
54namespace test
55{
56/** Factory class to create and fill tensors.
57 *
58 * Allows to initialise tensors from loaded images or by specifying the shape
59 * explicitly. Furthermore, provides methods to fill tensors with the content of
60 * loaded images or with random values.
61 */
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +010062class AssetsLibrary final
Anthony Barbier6ff3b192017-09-04 18:44:23 +010063{
64public:
Georgios Pinitas587708b2018-12-31 15:43:52 +000065 using RangePair = std::pair<float, float>;
66
67public:
John Richardson70f946b2017-10-02 16:52:16 +010068 /** Initialises the library with a @p path to the assets directory.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010069 * Furthermore, sets the seed for the random generator to @p seed.
70 *
John Richardson70f946b2017-10-02 16:52:16 +010071 * @param[in] path Path to load assets from.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010072 * @param[in] seed Seed used to initialise the random number generator.
73 */
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +010074 AssetsLibrary(std::string path, std::random_device::result_type seed);
Anthony Barbier6ff3b192017-09-04 18:44:23 +010075
Alex Gildayc357c472018-03-21 13:54:09 +000076 /** Path to assets directory used to initialise library.
77 *
78 * @return the path to the assets directory.
79 */
John Richardson70f946b2017-10-02 16:52:16 +010080 std::string path() const;
81
Alex Gildayc357c472018-03-21 13:54:09 +000082 /** Seed that is used to fill tensors with random values.
83 *
84 * @return the initial random seed.
85 */
Anthony Barbier6ff3b192017-09-04 18:44:23 +010086 std::random_device::result_type seed() const;
87
Giorgio Arenafda46182017-06-16 13:57:33 +010088 /** Provides a tensor shape for the specified image.
89 *
90 * @param[in] name Image file used to look up the raw tensor.
Alex Gildayc357c472018-03-21 13:54:09 +000091 *
92 * @return the tensor shape for the specified image.
Giorgio Arenafda46182017-06-16 13:57:33 +010093 */
94 TensorShape get_image_shape(const std::string &name);
95
Alex Gildayc357c472018-03-21 13:54:09 +000096 /** Provides a constant raw tensor for the specified image.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010097 *
98 * @param[in] name Image file used to look up the raw tensor.
Alex Gildayc357c472018-03-21 13:54:09 +000099 *
100 * @return a raw tensor for the specified image.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100101 */
102 const RawTensor &get(const std::string &name) const;
103
104 /** Provides a raw tensor for the specified image.
105 *
106 * @param[in] name Image file used to look up the raw tensor.
Alex Gildayc357c472018-03-21 13:54:09 +0000107 *
108 * @return a raw tensor for the specified image.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100109 */
110 RawTensor get(const std::string &name);
111
112 /** Creates an uninitialised raw tensor with the given @p data_type and @p
113 * num_channels. The shape is derived from the specified image.
114 *
115 * @param[in] name Image file used to initialise the tensor.
116 * @param[in] data_type Data type used to initialise the tensor.
117 * @param[in] num_channels Number of channels used to initialise the tensor.
Alex Gildayc357c472018-03-21 13:54:09 +0000118 *
119 * @return a raw tensor for the specified image.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100120 */
121 RawTensor get(const std::string &name, DataType data_type, int num_channels = 1) const;
122
123 /** Provides a contant raw tensor for the specified image after it has been
124 * converted to @p format.
125 *
126 * @param[in] name Image file used to look up the raw tensor.
127 * @param[in] format Format used to look up the raw tensor.
Alex Gildayc357c472018-03-21 13:54:09 +0000128 *
129 * @return a raw tensor for the specified image.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100130 */
131 const RawTensor &get(const std::string &name, Format format) const;
132
133 /** Provides a raw tensor for the specified image after it has been
134 * converted to @p format.
135 *
136 * @param[in] name Image file used to look up the raw tensor.
137 * @param[in] format Format used to look up the raw tensor.
Alex Gildayc357c472018-03-21 13:54:09 +0000138 *
139 * @return a raw tensor for the specified image.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100140 */
141 RawTensor get(const std::string &name, Format format);
142
143 /** Provides a contant raw tensor for the specified channel after it has
144 * been extracted form the given image.
145 *
146 * @param[in] name Image file used to look up the raw tensor.
147 * @param[in] channel Channel used to look up the raw tensor.
148 *
149 * @note The channel has to be unambiguous so that the format can be
150 * inferred automatically.
Alex Gildayc357c472018-03-21 13:54:09 +0000151 *
152 * @return a raw tensor for the specified image channel.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100153 */
154 const RawTensor &get(const std::string &name, Channel channel) const;
155
156 /** Provides a raw tensor for the specified channel after it has been
157 * extracted form the given image.
158 *
159 * @param[in] name Image file used to look up the raw tensor.
160 * @param[in] channel Channel used to look up the raw tensor.
161 *
162 * @note The channel has to be unambiguous so that the format can be
163 * inferred automatically.
Alex Gildayc357c472018-03-21 13:54:09 +0000164 *
165 * @return a raw tensor for the specified image channel.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100166 */
167 RawTensor get(const std::string &name, Channel channel);
168
169 /** Provides a constant raw tensor for the specified channel after it has
170 * been extracted form the given image formatted to @p format.
171 *
172 * @param[in] name Image file used to look up the raw tensor.
173 * @param[in] format Format used to look up the raw tensor.
174 * @param[in] channel Channel used to look up the raw tensor.
Alex Gildayc357c472018-03-21 13:54:09 +0000175 *
176 * @return a raw tensor for the specified image channel.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100177 */
178 const RawTensor &get(const std::string &name, Format format, Channel channel) const;
179
180 /** Provides a raw tensor for the specified channel after it has been
181 * extracted form the given image formatted to @p format.
182 *
183 * @param[in] name Image file used to look up the raw tensor.
184 * @param[in] format Format used to look up the raw tensor.
185 * @param[in] channel Channel used to look up the raw tensor.
Alex Gildayc357c472018-03-21 13:54:09 +0000186 *
187 * @return a raw tensor for the specified image channel.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100188 */
189 RawTensor get(const std::string &name, Format format, Channel channel);
190
Giorgio Arenaa2611812017-07-21 10:08:48 +0100191 /** Puts garbage values all around the tensor for testing purposes
192 *
193 * @param[in, out] tensor To be filled tensor.
194 * @param[in] distribution Distribution used to fill the tensor's surroundings.
195 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
196 */
197 template <typename T, typename D>
198 void fill_borders_with_garbage(T &&tensor, D &&distribution, std::random_device::result_type seed_offset) const;
199
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100200 /** Fills the specified @p tensor with random values drawn from @p
201 * distribution.
202 *
203 * @param[in, out] tensor To be filled tensor.
204 * @param[in] distribution Distribution used to fill the tensor.
205 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
206 *
207 * @note The @p distribution has to provide operator(Generator &) which
208 * will be used to draw samples.
209 */
210 template <typename T, typename D>
211 void fill(T &&tensor, D &&distribution, std::random_device::result_type seed_offset) const;
212
Pablo Telloe96e4f02018-12-21 16:47:23 +0000213 template <typename T, typename D>
214 void fill_boxes(T &&tensor, D &&distribution, std::random_device::result_type seed_offset) const;
215
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100216 /** Fills the specified @p raw tensor with random values drawn from @p
217 * distribution.
218 *
Vidhya Sudhan Loganathan951b8a42019-11-04 14:42:08 +0000219 * @param[in, out] vec To be filled vector.
220 * @param[in] distribution Distribution used to fill the tensor.
221 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
222 *
223 * @note The @p distribution has to provide operator(Generator &) which
224 * will be used to draw samples.
225 */
226 template <typename T, typename D>
227 void fill(std::vector<T> &vec, D &&distribution, std::random_device::result_type seed_offset) const;
228
229 /** Fills the specified @p raw tensor with random values drawn from @p
230 * distribution.
231 *
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100232 * @param[in, out] raw To be filled raw.
233 * @param[in] distribution Distribution used to fill the tensor.
234 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
235 *
236 * @note The @p distribution has to provide operator(Generator &) which
237 * will be used to draw samples.
238 */
239 template <typename D>
240 void fill(RawTensor &raw, D &&distribution, std::random_device::result_type seed_offset) const;
241
242 /** Fills the specified @p tensor with the content of the specified image
243 * converted to the given format.
244 *
245 * @param[in, out] tensor To be filled tensor.
246 * @param[in] name Image file used to fill the tensor.
247 * @param[in] format Format of the image used to fill the tensor.
248 *
249 * @warning No check is performed that the specified format actually
250 * matches the format of the tensor.
251 */
252 template <typename T>
253 void fill(T &&tensor, const std::string &name, Format format) const;
254
255 /** Fills the raw tensor with the content of the specified image
256 * converted to the given format.
257 *
258 * @param[in, out] raw To be filled raw tensor.
259 * @param[in] name Image file used to fill the tensor.
260 * @param[in] format Format of the image used to fill the tensor.
261 *
262 * @warning No check is performed that the specified format actually
263 * matches the format of the tensor.
264 */
265 void fill(RawTensor &raw, const std::string &name, Format format) const;
266
267 /** Fills the specified @p tensor with the content of the specified channel
268 * extracted from the given image.
269 *
270 * @param[in, out] tensor To be filled tensor.
271 * @param[in] name Image file used to fill the tensor.
272 * @param[in] channel Channel of the image used to fill the tensor.
273 *
274 * @note The channel has to be unambiguous so that the format can be
275 * inferred automatically.
276 *
277 * @warning No check is performed that the specified format actually
278 * matches the format of the tensor.
279 */
280 template <typename T>
281 void fill(T &&tensor, const std::string &name, Channel channel) const;
282
283 /** Fills the raw tensor with the content of the specified channel
284 * extracted from the given image.
285 *
286 * @param[in, out] raw To be filled raw tensor.
287 * @param[in] name Image file used to fill the tensor.
288 * @param[in] channel Channel of the image used to fill the tensor.
289 *
290 * @note The channel has to be unambiguous so that the format can be
291 * inferred automatically.
292 *
293 * @warning No check is performed that the specified format actually
294 * matches the format of the tensor.
295 */
296 void fill(RawTensor &raw, const std::string &name, Channel channel) const;
297
298 /** Fills the specified @p tensor with the content of the specified channel
299 * extracted from the given image after it has been converted to the given
300 * format.
301 *
302 * @param[in, out] tensor To be filled tensor.
303 * @param[in] name Image file used to fill the tensor.
304 * @param[in] format Format of the image used to fill the tensor.
305 * @param[in] channel Channel of the image used to fill the tensor.
306 *
307 * @warning No check is performed that the specified format actually
308 * matches the format of the tensor.
309 */
310 template <typename T>
311 void fill(T &&tensor, const std::string &name, Format format, Channel channel) const;
312
313 /** Fills the raw tensor with the content of the specified channel
314 * extracted from the given image after it has been converted to the given
315 * format.
316 *
317 * @param[in, out] raw To be filled raw tensor.
318 * @param[in] name Image file used to fill the tensor.
319 * @param[in] format Format of the image used to fill the tensor.
320 * @param[in] channel Channel of the image used to fill the tensor.
321 *
322 * @warning No check is performed that the specified format actually
323 * matches the format of the tensor.
324 */
325 void fill(RawTensor &raw, const std::string &name, Format format, Channel channel) const;
326
Alex Gilday345ab182018-01-09 11:40:19 +0000327 /** Fills the specified @p tensor with the content of the raw tensor.
328 *
329 * @param[in, out] tensor To be filled tensor.
330 * @param[in] raw Raw tensor used to fill the tensor.
331 *
332 * @warning No check is performed that the specified format actually
333 * matches the format of the tensor.
334 */
335 template <typename T>
336 void fill(T &&tensor, RawTensor raw) const;
337
Georgios Pinitas587708b2018-12-31 15:43:52 +0000338 /** Fill a tensor with uniform distribution
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100339 *
340 * @param[in, out] tensor To be filled tensor.
341 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
342 */
343 template <typename T>
344 void fill_tensor_uniform(T &&tensor, std::random_device::result_type seed_offset) const;
345
Georgios Pinitas587708b2018-12-31 15:43:52 +0000346 /** Fill a tensor with uniform distribution
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100347 *
348 * @param[in, out] tensor To be filled tensor.
349 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
350 * @param[in] low lowest value in the range (inclusive)
351 * @param[in] high highest value in the range (inclusive)
352 *
353 * @note @p low and @p high must be of the same type as the data type of @p tensor
354 */
355 template <typename T, typename D>
356 void fill_tensor_uniform(T &&tensor, std::random_device::result_type seed_offset, D low, D high) const;
357
Georgios Pinitas587708b2018-12-31 15:43:52 +0000358 /** Fill a tensor with uniform distribution across the specified range
359 *
360 * @param[in, out] tensor To be filled tensor.
361 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
362 * @param[in] excluded_range_pairs Ranges to exclude from the generator
363 */
364 template <typename T>
365 void fill_tensor_uniform_ranged(T &&tensor,
366 std::random_device::result_type seed_offset,
367 const std::vector<AssetsLibrary::RangePair> &excluded_range_pairs) const;
368
SiCong Li86b53332017-08-23 11:02:43 +0100369 /** Fills the specified @p tensor with data loaded from .npy (numpy binary) in specified path.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100370 *
371 * @param[in, out] tensor To be filled tensor.
372 * @param[in] name Data file.
SiCong Li86b53332017-08-23 11:02:43 +0100373 *
374 * @note The numpy array stored in the binary .npy file must be row-major in the sense that it
375 * must store elements within a row consecutively in the memory, then rows within a 2D slice,
376 * then 2D slices within a 3D slice and so on. Note that it imposes no restrictions on what
377 * indexing convention is used in the numpy array. That is, the numpy array can be either fortran
378 * style or C style as long as it adheres to the rule above.
379 *
380 * More concretely, the orders of dimensions for each style are as follows:
381 * C-style (numpy default):
382 * array[HigherDims..., Z, Y, X]
383 * Fortran style:
384 * array[X, Y, Z, HigherDims...]
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100385 */
386 template <typename T>
387 void fill_layer_data(T &&tensor, std::string name) const;
388
Michele Di Giorgio4d336302018-03-02 09:43:54 +0000389 /** Fill a tensor with a constant value
390 *
391 * @param[in, out] tensor To be filled tensor.
392 * @param[in] value Value to be assigned to all elements of the input tensor.
393 *
394 * @note @p value must be of the same type as the data type of @p tensor
395 */
396 template <typename T, typename D>
397 void fill_tensor_value(T &&tensor, D value) const;
398
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100399private:
400 // Function prototype to convert between image formats.
401 using Converter = void (*)(const RawTensor &src, RawTensor &dst);
402 // Function prototype to extract a channel from an image.
403 using Extractor = void (*)(const RawTensor &src, RawTensor &dst);
404 // Function prototype to load an image file.
405 using Loader = RawTensor (*)(const std::string &path);
406
407 const Converter &get_converter(Format src, Format dst) const;
408 const Converter &get_converter(DataType src, Format dst) const;
409 const Converter &get_converter(Format src, DataType dst) const;
410 const Converter &get_converter(DataType src, DataType dst) const;
411 const Extractor &get_extractor(Format format, Channel) const;
412 const Loader &get_loader(const std::string &extension) const;
413
414 /** Creates a raw tensor from the specified image.
415 *
416 * @param[in] name To be loaded image file.
417 *
418 * @note If use_single_image is true @p name is ignored and the user image
419 * is loaded instead.
420 */
421 RawTensor load_image(const std::string &name) const;
422
423 /** Provides a raw tensor for the specified image and format.
424 *
425 * @param[in] name Image file used to look up the raw tensor.
426 * @param[in] format Format used to look up the raw tensor.
427 *
428 * If the tensor has already been requested before the cached version will
429 * be returned. Otherwise the tensor will be added to the cache.
430 *
431 * @note If use_single_image is true @p name is ignored and the user image
432 * is loaded instead.
433 */
434 const RawTensor &find_or_create_raw_tensor(const std::string &name, Format format) const;
435
436 /** Provides a raw tensor for the specified image, format and channel.
437 *
438 * @param[in] name Image file used to look up the raw tensor.
439 * @param[in] format Format used to look up the raw tensor.
440 * @param[in] channel Channel used to look up the raw tensor.
441 *
442 * If the tensor has already been requested before the cached version will
443 * be returned. Otherwise the tensor will be added to the cache.
444 *
445 * @note If use_single_image is true @p name is ignored and the user image
446 * is loaded instead.
447 */
448 const RawTensor &find_or_create_raw_tensor(const std::string &name, Format format, Channel channel) const;
449
450 mutable TensorCache _cache{};
Georgios Pinitas421405b2018-10-26 19:05:32 +0100451 mutable arm_compute::Mutex _format_lock{};
452 mutable arm_compute::Mutex _channel_lock{};
Anthony Barbierac69aa12017-07-03 17:39:37 +0100453 const std::string _library_path;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100454 std::random_device::result_type _seed;
455};
456
Georgios Pinitas587708b2018-12-31 15:43:52 +0000457namespace detail
458{
459template <typename T>
460inline std::vector<std::pair<T, T>> convert_range_pair(const std::vector<AssetsLibrary::RangePair> &excluded_range_pairs)
461{
462 std::vector<std::pair<T, T>> converted;
463 std::transform(excluded_range_pairs.begin(),
464 excluded_range_pairs.end(),
465 std::back_inserter(converted),
466 [](const AssetsLibrary::RangePair & p)
467 {
468 return std::pair<T, T>(static_cast<T>(p.first), static_cast<T>(p.second));
469 });
470 return converted;
471}
472} // namespace detail
473
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100474template <typename T, typename D>
Giorgio Arenaa2611812017-07-21 10:08:48 +0100475void AssetsLibrary::fill_borders_with_garbage(T &&tensor, D &&distribution, std::random_device::result_type seed_offset) const
476{
477 const PaddingSize padding_size = tensor.padding();
478
479 Window window;
480 window.set(0, Window::Dimension(-padding_size.left, tensor.shape()[0] + padding_size.right, 1));
Gian Marco5420b282017-11-29 10:41:38 +0000481 if(tensor.shape().num_dimensions() > 1)
482 {
483 window.set(1, Window::Dimension(-padding_size.top, tensor.shape()[1] + padding_size.bottom, 1));
484 }
Giorgio Arenaa2611812017-07-21 10:08:48 +0100485
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100486 std::mt19937 gen(_seed + seed_offset);
Giorgio Arenaa2611812017-07-21 10:08:48 +0100487
488 execute_window_loop(window, [&](const Coordinates & id)
489 {
490 TensorShape shape = tensor.shape();
491
492 // If outside of valid region
493 if(id.x() < 0 || id.x() >= static_cast<int>(shape.x()) || id.y() < 0 || id.y() >= static_cast<int>(shape.y()))
494 {
495 using ResultType = typename std::remove_reference<D>::type::result_type;
496 const ResultType value = distribution(gen);
497 void *const out_ptr = tensor(id);
498 store_value_with_data_type(out_ptr, value, tensor.data_type());
499 }
500 });
501}
502
503template <typename T, typename D>
Pablo Telloe96e4f02018-12-21 16:47:23 +0000504void AssetsLibrary::fill_boxes(T &&tensor, D &&distribution, std::random_device::result_type seed_offset) const
505{
506 using ResultType = typename std::remove_reference<D>::type::result_type;
Michalis Spyroufae513c2019-10-16 17:41:33 +0100507 std::mt19937 gen(_seed + seed_offset);
508 TensorShape shape(tensor.shape());
509 const uint32_t num_boxes = tensor.num_elements() / 4;
Pablo Telloe96e4f02018-12-21 16:47:23 +0000510 // Iterate over all elements
511 std::uniform_real_distribution<> size_dist(0.f, 1.f);
Michalis Spyroufae513c2019-10-16 17:41:33 +0100512 for(uint32_t element_idx = 0; element_idx < num_boxes * 4; element_idx += 4)
Pablo Telloe96e4f02018-12-21 16:47:23 +0000513 {
514 const ResultType delta = size_dist(gen);
515 const ResultType epsilon = size_dist(gen);
516 const ResultType left = distribution(gen);
517 const ResultType top = distribution(gen);
518 const ResultType right = left + delta;
519 const ResultType bottom = top + epsilon;
520 const std::tuple<ResultType, ResultType, ResultType, ResultType> box(left, top, right, bottom);
521 Coordinates x1 = index2coord(shape, element_idx);
522 Coordinates y1 = index2coord(shape, element_idx + 1);
523 Coordinates x2 = index2coord(shape, element_idx + 2);
524 Coordinates y2 = index2coord(shape, element_idx + 3);
525 ResultType &target_value_x1 = reinterpret_cast<ResultType *>(tensor(x1))[0];
526 ResultType &target_value_y1 = reinterpret_cast<ResultType *>(tensor(y1))[0];
527 ResultType &target_value_x2 = reinterpret_cast<ResultType *>(tensor(x2))[0];
528 ResultType &target_value_y2 = reinterpret_cast<ResultType *>(tensor(y2))[0];
529 store_value_with_data_type(&target_value_x1, std::get<0>(box), tensor.data_type());
530 store_value_with_data_type(&target_value_y1, std::get<1>(box), tensor.data_type());
531 store_value_with_data_type(&target_value_x2, std::get<2>(box), tensor.data_type());
532 store_value_with_data_type(&target_value_y2, std::get<3>(box), tensor.data_type());
533 }
534 fill_borders_with_garbage(tensor, distribution, seed_offset);
535}
536
537template <typename T, typename D>
Vidhya Sudhan Loganathan951b8a42019-11-04 14:42:08 +0000538void AssetsLibrary::fill(std::vector<T> &vec, D &&distribution, std::random_device::result_type seed_offset) const
539{
540 ARM_COMPUTE_ERROR_ON_MSG(vec.empty(), "Vector must not be empty");
541
542 using ResultType = typename std::remove_reference<D>::type::result_type;
543
544 std::mt19937 gen(_seed + seed_offset);
545 for(size_t i = 0; i < vec.size(); ++i)
546 {
547 const ResultType value = distribution(gen);
548
549 vec[i] = value;
550 }
551}
552
553template <typename T, typename D>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100554void AssetsLibrary::fill(T &&tensor, D &&distribution, std::random_device::result_type seed_offset) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100555{
Ioan-Cristian Szabo9414f642017-10-27 17:35:40 +0100556 using ResultType = typename std::remove_reference<D>::type::result_type;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100557
558 std::mt19937 gen(_seed + seed_offset);
559
Giorgio Arena563494c2018-04-30 17:29:41 +0100560 const bool is_nhwc = tensor.data_layout() == DataLayout::NHWC;
561 TensorShape shape(tensor.shape());
562
563 if(is_nhwc)
564 {
565 // Ensure that the equivalent tensors will be filled for both data layouts
566 permute(shape, PermutationVector(1U, 2U, 0U));
567 }
568
Ioan-Cristian Szabo9414f642017-10-27 17:35:40 +0100569 // Iterate over all elements
Michalis Spyroufae513c2019-10-16 17:41:33 +0100570 const uint32_t num_elements = tensor.num_elements();
571 for(uint32_t element_idx = 0; element_idx < num_elements; ++element_idx)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100572 {
Giorgio Arena563494c2018-04-30 17:29:41 +0100573 Coordinates id = index2coord(shape, element_idx);
574
575 if(is_nhwc)
576 {
577 // Write in the correct id for permuted shapes
578 permute(id, PermutationVector(2U, 0U, 1U));
579 }
Ioan-Cristian Szabo9414f642017-10-27 17:35:40 +0100580
581 // Iterate over all channels
582 for(int channel = 0; channel < tensor.num_channels(); ++channel)
583 {
584 const ResultType value = distribution(gen);
Kohei Takahashicedb78f2018-08-23 10:23:52 +0900585 ResultType &target_value = reinterpret_cast<ResultType *>(tensor(id))[channel];
Ioan-Cristian Szabo9414f642017-10-27 17:35:40 +0100586
587 store_value_with_data_type(&target_value, value, tensor.data_type());
588 }
589 }
Giorgio Arenaa2611812017-07-21 10:08:48 +0100590
591 fill_borders_with_garbage(tensor, distribution, seed_offset);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100592}
593
594template <typename D>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100595void AssetsLibrary::fill(RawTensor &raw, D &&distribution, std::random_device::result_type seed_offset) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100596{
597 std::mt19937 gen(_seed + seed_offset);
598
599 for(size_t offset = 0; offset < raw.size(); offset += raw.element_size())
600 {
601 using ResultType = typename std::remove_reference<D>::type::result_type;
602 const ResultType value = distribution(gen);
Georgios Pinitas587708b2018-12-31 15:43:52 +0000603
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100604 store_value_with_data_type(raw.data() + offset, value, raw.data_type());
605 }
606}
607
608template <typename T>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100609void AssetsLibrary::fill(T &&tensor, const std::string &name, Format format) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100610{
611 const RawTensor &raw = get(name, format);
612
613 for(size_t offset = 0; offset < raw.size(); offset += raw.element_size())
614 {
615 const Coordinates id = index2coord(raw.shape(), offset / raw.element_size());
616
Moritz Pflanzer82e70a12017-08-08 16:20:45 +0100617 const RawTensor::value_type *const raw_ptr = raw.data() + offset;
618 const auto out_ptr = static_cast<RawTensor::value_type *>(tensor(id));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100619 std::copy_n(raw_ptr, raw.element_size(), out_ptr);
620 }
621}
622
623template <typename T>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100624void AssetsLibrary::fill(T &&tensor, const std::string &name, Channel channel) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100625{
626 fill(std::forward<T>(tensor), name, get_format_for_channel(channel), channel);
627}
628
629template <typename T>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100630void AssetsLibrary::fill(T &&tensor, const std::string &name, Format format, Channel channel) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100631{
632 const RawTensor &raw = get(name, format, channel);
633
634 for(size_t offset = 0; offset < raw.size(); offset += raw.element_size())
635 {
636 const Coordinates id = index2coord(raw.shape(), offset / raw.element_size());
637
Moritz Pflanzer82e70a12017-08-08 16:20:45 +0100638 const RawTensor::value_type *const raw_ptr = raw.data() + offset;
639 const auto out_ptr = static_cast<RawTensor::value_type *>(tensor(id));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100640 std::copy_n(raw_ptr, raw.element_size(), out_ptr);
641 }
642}
643
644template <typename T>
Alex Gilday345ab182018-01-09 11:40:19 +0000645void AssetsLibrary::fill(T &&tensor, RawTensor raw) const
646{
647 for(size_t offset = 0; offset < raw.size(); offset += raw.element_size())
648 {
649 const Coordinates id = index2coord(raw.shape(), offset / raw.element_size());
650
651 const RawTensor::value_type *const raw_ptr = raw.data() + offset;
652 const auto out_ptr = static_cast<RawTensor::value_type *>(tensor(id));
653 std::copy_n(raw_ptr, raw.element_size(), out_ptr);
654 }
655}
656
657template <typename T>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100658void AssetsLibrary::fill_tensor_uniform(T &&tensor, std::random_device::result_type seed_offset) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100659{
660 switch(tensor.data_type())
661 {
662 case DataType::U8:
Anton Lokhmotovaf6204c2017-11-08 09:34:19 +0000663 case DataType::QASYMM8:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100664 {
665 std::uniform_int_distribution<uint8_t> distribution_u8(std::numeric_limits<uint8_t>::lowest(), std::numeric_limits<uint8_t>::max());
666 fill(tensor, distribution_u8, seed_offset);
667 break;
668 }
669 case DataType::S8:
Georgios Pinitas3d13af82019-06-04 13:04:16 +0100670 case DataType::QSYMM8:
Georgios Pinitas8217c8e2019-11-11 18:24:22 +0000671 case DataType::QSYMM8_PER_CHANNEL:
Georgios Pinitasdbdea0d2019-10-16 19:21:40 +0100672 case DataType::QASYMM8_SIGNED:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100673 {
674 std::uniform_int_distribution<int8_t> distribution_s8(std::numeric_limits<int8_t>::lowest(), std::numeric_limits<int8_t>::max());
675 fill(tensor, distribution_s8, seed_offset);
676 break;
677 }
678 case DataType::U16:
679 {
680 std::uniform_int_distribution<uint16_t> distribution_u16(std::numeric_limits<uint16_t>::lowest(), std::numeric_limits<uint16_t>::max());
681 fill(tensor, distribution_u16, seed_offset);
682 break;
683 }
684 case DataType::S16:
Manuel Bottini3689fcd2019-06-14 17:18:12 +0100685 case DataType::QSYMM16:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100686 {
687 std::uniform_int_distribution<int16_t> distribution_s16(std::numeric_limits<int16_t>::lowest(), std::numeric_limits<int16_t>::max());
688 fill(tensor, distribution_s16, seed_offset);
689 break;
690 }
691 case DataType::U32:
692 {
693 std::uniform_int_distribution<uint32_t> distribution_u32(std::numeric_limits<uint32_t>::lowest(), std::numeric_limits<uint32_t>::max());
694 fill(tensor, distribution_u32, seed_offset);
695 break;
696 }
697 case DataType::S32:
698 {
699 std::uniform_int_distribution<int32_t> distribution_s32(std::numeric_limits<int32_t>::lowest(), std::numeric_limits<int32_t>::max());
700 fill(tensor, distribution_s32, seed_offset);
701 break;
702 }
703 case DataType::U64:
704 {
705 std::uniform_int_distribution<uint64_t> distribution_u64(std::numeric_limits<uint64_t>::lowest(), std::numeric_limits<uint64_t>::max());
706 fill(tensor, distribution_u64, seed_offset);
707 break;
708 }
709 case DataType::S64:
710 {
711 std::uniform_int_distribution<int64_t> distribution_s64(std::numeric_limits<int64_t>::lowest(), std::numeric_limits<int64_t>::max());
712 fill(tensor, distribution_s64, seed_offset);
713 break;
714 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100715 case DataType::F16:
SiCong Li02dfb2c2017-07-27 17:59:20 +0100716 {
717 // It doesn't make sense to check [-inf, inf], so hard code it to a big number
718 std::uniform_real_distribution<float> distribution_f16(-100.f, 100.f);
719 fill(tensor, distribution_f16, seed_offset);
720 break;
721 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100722 case DataType::F32:
723 {
724 // It doesn't make sense to check [-inf, inf], so hard code it to a big number
725 std::uniform_real_distribution<float> distribution_f32(-1000.f, 1000.f);
726 fill(tensor, distribution_f32, seed_offset);
727 break;
728 }
729 case DataType::F64:
730 {
731 // It doesn't make sense to check [-inf, inf], so hard code it to a big number
732 std::uniform_real_distribution<double> distribution_f64(-1000.f, 1000.f);
733 fill(tensor, distribution_f64, seed_offset);
734 break;
735 }
736 case DataType::SIZET:
737 {
738 std::uniform_int_distribution<size_t> distribution_sizet(std::numeric_limits<size_t>::lowest(), std::numeric_limits<size_t>::max());
739 fill(tensor, distribution_sizet, seed_offset);
740 break;
741 }
742 default:
743 ARM_COMPUTE_ERROR("NOT SUPPORTED!");
744 }
745}
746
Georgios Pinitas587708b2018-12-31 15:43:52 +0000747template <typename T>
748void AssetsLibrary::fill_tensor_uniform_ranged(T &&tensor,
749 std::random_device::result_type seed_offset,
750 const std::vector<AssetsLibrary::RangePair> &excluded_range_pairs) const
751{
752 using namespace arm_compute::utils::random;
753
754 switch(tensor.data_type())
755 {
756 case DataType::U8:
757 case DataType::QASYMM8:
758 {
759 const auto converted_pairs = detail::convert_range_pair<uint8_t>(excluded_range_pairs);
760 RangedUniformDistribution<uint8_t> distribution_u8(std::numeric_limits<uint8_t>::lowest(),
761 std::numeric_limits<uint8_t>::max(),
762 converted_pairs);
763 fill(tensor, distribution_u8, seed_offset);
764 break;
765 }
766 case DataType::S8:
Georgios Pinitas3d13af82019-06-04 13:04:16 +0100767 case DataType::QSYMM8:
Georgios Pinitas587708b2018-12-31 15:43:52 +0000768 {
769 const auto converted_pairs = detail::convert_range_pair<int8_t>(excluded_range_pairs);
770 RangedUniformDistribution<int8_t> distribution_s8(std::numeric_limits<int8_t>::lowest(),
771 std::numeric_limits<int8_t>::max(),
772 converted_pairs);
773 fill(tensor, distribution_s8, seed_offset);
774 break;
775 }
776 case DataType::U16:
777 {
778 const auto converted_pairs = detail::convert_range_pair<uint16_t>(excluded_range_pairs);
779 RangedUniformDistribution<uint16_t> distribution_u16(std::numeric_limits<uint16_t>::lowest(),
780 std::numeric_limits<uint16_t>::max(),
781 converted_pairs);
782 fill(tensor, distribution_u16, seed_offset);
783 break;
784 }
785 case DataType::S16:
Manuel Bottini3689fcd2019-06-14 17:18:12 +0100786 case DataType::QSYMM16:
Georgios Pinitas587708b2018-12-31 15:43:52 +0000787 {
788 const auto converted_pairs = detail::convert_range_pair<int16_t>(excluded_range_pairs);
789 RangedUniformDistribution<int16_t> distribution_s16(std::numeric_limits<int16_t>::lowest(),
790 std::numeric_limits<int16_t>::max(),
791 converted_pairs);
792 fill(tensor, distribution_s16, seed_offset);
793 break;
794 }
795 case DataType::U32:
796 {
797 const auto converted_pairs = detail::convert_range_pair<uint32_t>(excluded_range_pairs);
798 RangedUniformDistribution<uint32_t> distribution_u32(std::numeric_limits<uint32_t>::lowest(),
799 std::numeric_limits<uint32_t>::max(),
800 converted_pairs);
801 fill(tensor, distribution_u32, seed_offset);
802 break;
803 }
804 case DataType::S32:
805 {
806 const auto converted_pairs = detail::convert_range_pair<int32_t>(excluded_range_pairs);
807 RangedUniformDistribution<int32_t> distribution_s32(std::numeric_limits<int32_t>::lowest(),
808 std::numeric_limits<int32_t>::max(),
809 converted_pairs);
810 fill(tensor, distribution_s32, seed_offset);
811 break;
812 }
813 case DataType::F16:
814 {
815 // It doesn't make sense to check [-inf, inf], so hard code it to a big number
816 const auto converted_pairs = detail::convert_range_pair<float>(excluded_range_pairs);
817 RangedUniformDistribution<float> distribution_f16(-100.f, 100.f, converted_pairs);
818 fill(tensor, distribution_f16, seed_offset);
819 break;
820 }
821 case DataType::F32:
822 {
823 // It doesn't make sense to check [-inf, inf], so hard code it to a big number
824 const auto converted_pairs = detail::convert_range_pair<float>(excluded_range_pairs);
825 RangedUniformDistribution<float> distribution_f32(-1000.f, 1000.f, converted_pairs);
826 fill(tensor, distribution_f32, seed_offset);
827 break;
828 }
829 default:
830 ARM_COMPUTE_ERROR("NOT SUPPORTED!");
831 }
832}
833
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100834template <typename T, typename D>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100835void AssetsLibrary::fill_tensor_uniform(T &&tensor, std::random_device::result_type seed_offset, D low, D high) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100836{
837 switch(tensor.data_type())
838 {
839 case DataType::U8:
Anton Lokhmotovaf6204c2017-11-08 09:34:19 +0000840 case DataType::QASYMM8:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100841 {
842 ARM_COMPUTE_ERROR_ON(!(std::is_same<uint8_t, D>::value));
843 std::uniform_int_distribution<uint8_t> distribution_u8(low, high);
844 fill(tensor, distribution_u8, seed_offset);
845 break;
846 }
847 case DataType::S8:
Georgios Pinitas3d13af82019-06-04 13:04:16 +0100848 case DataType::QSYMM8:
Sang-Hoon Parkd8176472019-12-04 09:46:28 +0000849 case DataType::QASYMM8_SIGNED:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100850 {
851 ARM_COMPUTE_ERROR_ON(!(std::is_same<int8_t, D>::value));
852 std::uniform_int_distribution<int8_t> distribution_s8(low, high);
853 fill(tensor, distribution_s8, seed_offset);
854 break;
855 }
856 case DataType::U16:
857 {
858 ARM_COMPUTE_ERROR_ON(!(std::is_same<uint16_t, D>::value));
859 std::uniform_int_distribution<uint16_t> distribution_u16(low, high);
860 fill(tensor, distribution_u16, seed_offset);
861 break;
862 }
863 case DataType::S16:
Manuel Bottini3689fcd2019-06-14 17:18:12 +0100864 case DataType::QSYMM16:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100865 {
866 ARM_COMPUTE_ERROR_ON(!(std::is_same<int16_t, D>::value));
867 std::uniform_int_distribution<int16_t> distribution_s16(low, high);
868 fill(tensor, distribution_s16, seed_offset);
869 break;
870 }
871 case DataType::U32:
872 {
873 ARM_COMPUTE_ERROR_ON(!(std::is_same<uint32_t, D>::value));
874 std::uniform_int_distribution<uint32_t> distribution_u32(low, high);
875 fill(tensor, distribution_u32, seed_offset);
876 break;
877 }
878 case DataType::S32:
879 {
880 ARM_COMPUTE_ERROR_ON(!(std::is_same<int32_t, D>::value));
881 std::uniform_int_distribution<int32_t> distribution_s32(low, high);
882 fill(tensor, distribution_s32, seed_offset);
883 break;
884 }
885 case DataType::U64:
886 {
887 ARM_COMPUTE_ERROR_ON(!(std::is_same<uint64_t, D>::value));
888 std::uniform_int_distribution<uint64_t> distribution_u64(low, high);
889 fill(tensor, distribution_u64, seed_offset);
890 break;
891 }
892 case DataType::S64:
893 {
894 ARM_COMPUTE_ERROR_ON(!(std::is_same<int64_t, D>::value));
895 std::uniform_int_distribution<int64_t> distribution_s64(low, high);
896 fill(tensor, distribution_s64, seed_offset);
897 break;
898 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100899 case DataType::F16:
900 {
Moritz Pflanzere49e2662017-07-21 15:55:28 +0100901 std::uniform_real_distribution<float> distribution_f16(low, high);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100902 fill(tensor, distribution_f16, seed_offset);
903 break;
904 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100905 case DataType::F32:
906 {
907 ARM_COMPUTE_ERROR_ON(!(std::is_same<float, D>::value));
908 std::uniform_real_distribution<float> distribution_f32(low, high);
909 fill(tensor, distribution_f32, seed_offset);
910 break;
911 }
912 case DataType::F64:
913 {
914 ARM_COMPUTE_ERROR_ON(!(std::is_same<double, D>::value));
915 std::uniform_real_distribution<double> distribution_f64(low, high);
916 fill(tensor, distribution_f64, seed_offset);
917 break;
918 }
919 case DataType::SIZET:
920 {
921 ARM_COMPUTE_ERROR_ON(!(std::is_same<size_t, D>::value));
922 std::uniform_int_distribution<size_t> distribution_sizet(low, high);
923 fill(tensor, distribution_sizet, seed_offset);
924 break;
925 }
926 default:
927 ARM_COMPUTE_ERROR("NOT SUPPORTED!");
928 }
929}
930
931template <typename T>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100932void AssetsLibrary::fill_layer_data(T &&tensor, std::string name) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100933{
934#ifdef _WIN32
935 const std::string path_separator("\\");
Anthony Barbierac69aa12017-07-03 17:39:37 +0100936#else /* _WIN32 */
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100937 const std::string path_separator("/");
Anthony Barbierac69aa12017-07-03 17:39:37 +0100938#endif /* _WIN32 */
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100939 const std::string path = _library_path + path_separator + name;
940
SiCong Li86b53332017-08-23 11:02:43 +0100941 std::vector<unsigned long> shape;
942
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100943 // Open file
SiCong Li86b53332017-08-23 11:02:43 +0100944 std::ifstream stream(path, std::ios::in | std::ios::binary);
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100945 if(!stream.good())
946 {
947 throw framework::FileNotFound("Could not load npy file: " + path);
948 }
Anthony Barbier87f21cd2017-11-10 16:27:32 +0000949 std::string header = npy::read_header(stream);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100950
SiCong Li86b53332017-08-23 11:02:43 +0100951 // Parse header
952 bool fortran_order = false;
953 std::string typestr;
Anthony Barbier87f21cd2017-11-10 16:27:32 +0000954 npy::parse_header(header, typestr, fortran_order, shape);
SiCong Li86b53332017-08-23 11:02:43 +0100955
956 // Check if the typestring matches the given one
957 std::string expect_typestr = get_typestring(tensor.data_type());
958 ARM_COMPUTE_ERROR_ON_MSG(typestr != expect_typestr, "Typestrings mismatch");
959
960 // Validate tensor shape
961 ARM_COMPUTE_ERROR_ON_MSG(shape.size() != tensor.shape().num_dimensions(), "Tensor ranks mismatch");
962 if(fortran_order)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100963 {
SiCong Li86b53332017-08-23 11:02:43 +0100964 for(size_t i = 0; i < shape.size(); ++i)
965 {
966 ARM_COMPUTE_ERROR_ON_MSG(tensor.shape()[i] != shape[i], "Tensor dimensions mismatch");
967 }
968 }
969 else
970 {
971 for(size_t i = 0; i < shape.size(); ++i)
972 {
973 ARM_COMPUTE_ERROR_ON_MSG(tensor.shape()[i] != shape[shape.size() - i - 1], "Tensor dimensions mismatch");
974 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100975 }
976
SiCong Li86b53332017-08-23 11:02:43 +0100977 // Read data
978 if(tensor.padding().empty())
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100979 {
SiCong Li86b53332017-08-23 11:02:43 +0100980 // If tensor has no padding read directly from stream.
981 stream.read(reinterpret_cast<char *>(tensor.data()), tensor.size());
982 }
983 else
984 {
985 // If tensor has padding accessing tensor elements through execution window.
986 Window window;
987 window.use_tensor_dimensions(tensor.shape());
988
SiCong Li86b53332017-08-23 11:02:43 +0100989 execute_window_loop(window, [&](const Coordinates & id)
990 {
991 stream.read(reinterpret_cast<char *>(tensor(id)), tensor.element_size());
992 });
993 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100994}
Michele Di Giorgio4d336302018-03-02 09:43:54 +0000995
996template <typename T, typename D>
997void AssetsLibrary::fill_tensor_value(T &&tensor, D value) const
998{
999 fill_tensor_uniform(tensor, 0, value, value);
1000}
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001001} // namespace test
1002} // namespace arm_compute
Michalis Spyrouf4643372019-11-29 16:17:13 +00001003#endif /* ARM_COMPUTE_TEST_TENSOR_LIBRARY_H */