blob: 84653ed089b4469fc7fb5b9208d49ea40ea20509 [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
Georgios Pinitase8291ac2020-02-26 09:58:13 +00002 * Copyright (c) 2017-2020 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"
Moritz Pflanzere49e2662017-07-21 15:55:28 +010035#include "tests/RawTensor.h"
36#include "tests/TensorCache.h"
37#include "tests/Utils.h"
Anthony Barbierf6705ec2017-09-28 12:01:10 +010038#include "tests/framework/Exceptions.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010039
40#include <algorithm>
41#include <cstddef>
42#include <fstream>
43#include <random>
44#include <string>
45#include <type_traits>
SiCong Li86b53332017-08-23 11:02:43 +010046#include <vector>
Anthony Barbier6ff3b192017-09-04 18:44:23 +010047
48namespace arm_compute
49{
50namespace test
51{
52/** Factory class to create and fill tensors.
53 *
54 * Allows to initialise tensors from loaded images or by specifying the shape
55 * explicitly. Furthermore, provides methods to fill tensors with the content of
56 * loaded images or with random values.
57 */
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +010058class AssetsLibrary final
Anthony Barbier6ff3b192017-09-04 18:44:23 +010059{
60public:
Georgios Pinitas587708b2018-12-31 15:43:52 +000061 using RangePair = std::pair<float, float>;
62
63public:
John Richardson70f946b2017-10-02 16:52:16 +010064 /** Initialises the library with a @p path to the assets directory.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010065 * Furthermore, sets the seed for the random generator to @p seed.
66 *
John Richardson70f946b2017-10-02 16:52:16 +010067 * @param[in] path Path to load assets from.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010068 * @param[in] seed Seed used to initialise the random number generator.
69 */
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +010070 AssetsLibrary(std::string path, std::random_device::result_type seed);
Anthony Barbier6ff3b192017-09-04 18:44:23 +010071
Alex Gildayc357c472018-03-21 13:54:09 +000072 /** Path to assets directory used to initialise library.
73 *
74 * @return the path to the assets directory.
75 */
John Richardson70f946b2017-10-02 16:52:16 +010076 std::string path() const;
77
Alex Gildayc357c472018-03-21 13:54:09 +000078 /** Seed that is used to fill tensors with random values.
79 *
80 * @return the initial random seed.
81 */
Anthony Barbier6ff3b192017-09-04 18:44:23 +010082 std::random_device::result_type seed() const;
83
Giorgio Arenafda46182017-06-16 13:57:33 +010084 /** Provides a tensor shape for the specified image.
85 *
86 * @param[in] name Image file used to look up the raw tensor.
Alex Gildayc357c472018-03-21 13:54:09 +000087 *
88 * @return the tensor shape for the specified image.
Giorgio Arenafda46182017-06-16 13:57:33 +010089 */
90 TensorShape get_image_shape(const std::string &name);
91
Alex Gildayc357c472018-03-21 13:54:09 +000092 /** Provides a constant raw tensor for the specified image.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010093 *
94 * @param[in] name Image file used to look up the raw tensor.
Alex Gildayc357c472018-03-21 13:54:09 +000095 *
96 * @return a raw tensor for the specified image.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010097 */
98 const RawTensor &get(const std::string &name) const;
99
100 /** Provides a raw tensor for the specified image.
101 *
102 * @param[in] name Image file used to look up the raw tensor.
Alex Gildayc357c472018-03-21 13:54:09 +0000103 *
104 * @return a raw tensor for the specified image.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100105 */
106 RawTensor get(const std::string &name);
107
108 /** Creates an uninitialised raw tensor with the given @p data_type and @p
109 * num_channels. The shape is derived from the specified image.
110 *
111 * @param[in] name Image file used to initialise the tensor.
112 * @param[in] data_type Data type used to initialise the tensor.
113 * @param[in] num_channels Number of channels used to initialise the tensor.
Alex Gildayc357c472018-03-21 13:54:09 +0000114 *
115 * @return a raw tensor for the specified image.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100116 */
117 RawTensor get(const std::string &name, DataType data_type, int num_channels = 1) const;
118
119 /** Provides a contant raw tensor for the specified image after it has been
120 * converted to @p format.
121 *
122 * @param[in] name Image file used to look up the raw tensor.
123 * @param[in] format Format used to look up the raw tensor.
Alex Gildayc357c472018-03-21 13:54:09 +0000124 *
125 * @return a raw tensor for the specified image.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100126 */
127 const RawTensor &get(const std::string &name, Format format) const;
128
129 /** Provides a raw tensor for the specified image after it has been
130 * converted to @p format.
131 *
132 * @param[in] name Image file used to look up the raw tensor.
133 * @param[in] format Format used to look up the raw tensor.
Alex Gildayc357c472018-03-21 13:54:09 +0000134 *
135 * @return a raw tensor for the specified image.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100136 */
137 RawTensor get(const std::string &name, Format format);
138
139 /** Provides a contant raw tensor for the specified channel after it has
140 * been extracted form the given image.
141 *
142 * @param[in] name Image file used to look up the raw tensor.
143 * @param[in] channel Channel used to look up the raw tensor.
144 *
145 * @note The channel has to be unambiguous so that the format can be
146 * inferred automatically.
Alex Gildayc357c472018-03-21 13:54:09 +0000147 *
148 * @return a raw tensor for the specified image channel.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100149 */
150 const RawTensor &get(const std::string &name, Channel channel) const;
151
152 /** Provides a raw tensor for the specified channel after it has been
153 * extracted form the given image.
154 *
155 * @param[in] name Image file used to look up the raw tensor.
156 * @param[in] channel Channel used to look up the raw tensor.
157 *
158 * @note The channel has to be unambiguous so that the format can be
159 * inferred automatically.
Alex Gildayc357c472018-03-21 13:54:09 +0000160 *
161 * @return a raw tensor for the specified image channel.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100162 */
163 RawTensor get(const std::string &name, Channel channel);
164
165 /** Provides a constant raw tensor for the specified channel after it has
166 * been extracted form the given image formatted to @p format.
167 *
168 * @param[in] name Image file used to look up the raw tensor.
169 * @param[in] format Format used to look up the raw tensor.
170 * @param[in] channel Channel used to look up the raw tensor.
Alex Gildayc357c472018-03-21 13:54:09 +0000171 *
172 * @return a raw tensor for the specified image channel.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100173 */
174 const RawTensor &get(const std::string &name, Format format, Channel channel) const;
175
176 /** Provides a raw tensor for the specified channel after it has been
177 * extracted form the given image formatted to @p format.
178 *
179 * @param[in] name Image file used to look up the raw tensor.
180 * @param[in] format Format used to look up the raw tensor.
181 * @param[in] channel Channel used to look up the raw tensor.
Alex Gildayc357c472018-03-21 13:54:09 +0000182 *
183 * @return a raw tensor for the specified image channel.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100184 */
185 RawTensor get(const std::string &name, Format format, Channel channel);
186
Giorgio Arenaa2611812017-07-21 10:08:48 +0100187 /** Puts garbage values all around the tensor for testing purposes
188 *
189 * @param[in, out] tensor To be filled tensor.
190 * @param[in] distribution Distribution used to fill the tensor's surroundings.
191 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
192 */
193 template <typename T, typename D>
194 void fill_borders_with_garbage(T &&tensor, D &&distribution, std::random_device::result_type seed_offset) const;
195
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100196 /** Fills the specified @p tensor with random values drawn from @p
197 * distribution.
198 *
199 * @param[in, out] tensor To be filled tensor.
200 * @param[in] distribution Distribution used to fill the tensor.
201 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
202 *
203 * @note The @p distribution has to provide operator(Generator &) which
204 * will be used to draw samples.
205 */
206 template <typename T, typename D>
207 void fill(T &&tensor, D &&distribution, std::random_device::result_type seed_offset) const;
208
Pablo Telloe96e4f02018-12-21 16:47:23 +0000209 template <typename T, typename D>
210 void fill_boxes(T &&tensor, D &&distribution, std::random_device::result_type seed_offset) const;
211
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100212 /** Fills the specified @p raw tensor with random values drawn from @p
213 * distribution.
214 *
Vidhya Sudhan Loganathan951b8a42019-11-04 14:42:08 +0000215 * @param[in, out] vec To be filled vector.
216 * @param[in] distribution Distribution used to fill the tensor.
217 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
218 *
219 * @note The @p distribution has to provide operator(Generator &) which
220 * will be used to draw samples.
221 */
222 template <typename T, typename D>
223 void fill(std::vector<T> &vec, D &&distribution, std::random_device::result_type seed_offset) const;
224
225 /** Fills the specified @p raw tensor with random values drawn from @p
226 * distribution.
227 *
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100228 * @param[in, out] raw To be filled raw.
229 * @param[in] distribution Distribution used to fill the tensor.
230 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
231 *
232 * @note The @p distribution has to provide operator(Generator &) which
233 * will be used to draw samples.
234 */
235 template <typename D>
236 void fill(RawTensor &raw, D &&distribution, std::random_device::result_type seed_offset) const;
237
238 /** Fills the specified @p tensor with the content of the specified image
239 * converted to the given format.
240 *
241 * @param[in, out] tensor To be filled tensor.
242 * @param[in] name Image file used to fill the tensor.
243 * @param[in] format Format of the image used to fill the tensor.
244 *
245 * @warning No check is performed that the specified format actually
246 * matches the format of the tensor.
247 */
248 template <typename T>
249 void fill(T &&tensor, const std::string &name, Format format) const;
250
251 /** Fills the raw tensor with the content of the specified image
252 * converted to the given format.
253 *
254 * @param[in, out] raw To be filled raw tensor.
255 * @param[in] name Image file used to fill the tensor.
256 * @param[in] format Format of the image used to fill the tensor.
257 *
258 * @warning No check is performed that the specified format actually
259 * matches the format of the tensor.
260 */
261 void fill(RawTensor &raw, const std::string &name, Format format) const;
262
263 /** Fills the specified @p tensor with the content of the specified channel
264 * extracted from the given image.
265 *
266 * @param[in, out] tensor To be filled tensor.
267 * @param[in] name Image file used to fill the tensor.
268 * @param[in] channel Channel of the image used to fill the tensor.
269 *
270 * @note The channel has to be unambiguous so that the format can be
271 * inferred automatically.
272 *
273 * @warning No check is performed that the specified format actually
274 * matches the format of the tensor.
275 */
276 template <typename T>
277 void fill(T &&tensor, const std::string &name, Channel channel) const;
278
279 /** Fills the raw tensor with the content of the specified channel
280 * extracted from the given image.
281 *
282 * @param[in, out] raw To be filled raw tensor.
283 * @param[in] name Image file used to fill the tensor.
284 * @param[in] channel Channel of the image used to fill the tensor.
285 *
286 * @note The channel has to be unambiguous so that the format can be
287 * inferred automatically.
288 *
289 * @warning No check is performed that the specified format actually
290 * matches the format of the tensor.
291 */
292 void fill(RawTensor &raw, const std::string &name, Channel channel) const;
293
294 /** Fills the specified @p tensor with the content of the specified channel
295 * extracted from the given image after it has been converted to the given
296 * format.
297 *
298 * @param[in, out] tensor To be filled tensor.
299 * @param[in] name Image file used to fill the tensor.
300 * @param[in] format Format of the image used to fill the tensor.
301 * @param[in] channel Channel of the image used to fill the tensor.
302 *
303 * @warning No check is performed that the specified format actually
304 * matches the format of the tensor.
305 */
306 template <typename T>
307 void fill(T &&tensor, const std::string &name, Format format, Channel channel) const;
308
309 /** Fills the raw tensor with the content of the specified channel
310 * extracted from the given image after it has been converted to the given
311 * format.
312 *
313 * @param[in, out] raw To be filled raw tensor.
314 * @param[in] name Image file used to fill the tensor.
315 * @param[in] format Format of the image used to fill the tensor.
316 * @param[in] channel Channel of the image used to fill the tensor.
317 *
318 * @warning No check is performed that the specified format actually
319 * matches the format of the tensor.
320 */
321 void fill(RawTensor &raw, const std::string &name, Format format, Channel channel) const;
322
Alex Gilday345ab182018-01-09 11:40:19 +0000323 /** Fills the specified @p tensor with the content of the raw tensor.
324 *
325 * @param[in, out] tensor To be filled tensor.
326 * @param[in] raw Raw tensor used to fill the tensor.
327 *
328 * @warning No check is performed that the specified format actually
329 * matches the format of the tensor.
330 */
331 template <typename T>
332 void fill(T &&tensor, RawTensor raw) const;
333
Georgios Pinitas587708b2018-12-31 15:43:52 +0000334 /** Fill a tensor with uniform distribution
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100335 *
336 * @param[in, out] tensor To be filled tensor.
337 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
338 */
339 template <typename T>
340 void fill_tensor_uniform(T &&tensor, std::random_device::result_type seed_offset) const;
341
Georgios Pinitas587708b2018-12-31 15:43:52 +0000342 /** Fill a tensor with uniform distribution
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100343 *
344 * @param[in, out] tensor To be filled tensor.
345 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
346 * @param[in] low lowest value in the range (inclusive)
347 * @param[in] high highest value in the range (inclusive)
348 *
349 * @note @p low and @p high must be of the same type as the data type of @p tensor
350 */
351 template <typename T, typename D>
352 void fill_tensor_uniform(T &&tensor, std::random_device::result_type seed_offset, D low, D high) const;
353
Georgios Pinitas587708b2018-12-31 15:43:52 +0000354 /** Fill a tensor with uniform distribution across the specified range
355 *
356 * @param[in, out] tensor To be filled tensor.
357 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
358 * @param[in] excluded_range_pairs Ranges to exclude from the generator
359 */
360 template <typename T>
361 void fill_tensor_uniform_ranged(T &&tensor,
362 std::random_device::result_type seed_offset,
363 const std::vector<AssetsLibrary::RangePair> &excluded_range_pairs) const;
364
SiCong Li86b53332017-08-23 11:02:43 +0100365 /** Fills the specified @p tensor with data loaded from .npy (numpy binary) in specified path.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100366 *
367 * @param[in, out] tensor To be filled tensor.
368 * @param[in] name Data file.
SiCong Li86b53332017-08-23 11:02:43 +0100369 *
370 * @note The numpy array stored in the binary .npy file must be row-major in the sense that it
371 * must store elements within a row consecutively in the memory, then rows within a 2D slice,
372 * then 2D slices within a 3D slice and so on. Note that it imposes no restrictions on what
373 * indexing convention is used in the numpy array. That is, the numpy array can be either fortran
374 * style or C style as long as it adheres to the rule above.
375 *
376 * More concretely, the orders of dimensions for each style are as follows:
377 * C-style (numpy default):
378 * array[HigherDims..., Z, Y, X]
379 * Fortran style:
380 * array[X, Y, Z, HigherDims...]
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100381 */
382 template <typename T>
383 void fill_layer_data(T &&tensor, std::string name) const;
384
Michele Di Giorgio4d336302018-03-02 09:43:54 +0000385 /** Fill a tensor with a constant value
386 *
387 * @param[in, out] tensor To be filled tensor.
388 * @param[in] value Value to be assigned to all elements of the input tensor.
389 *
390 * @note @p value must be of the same type as the data type of @p tensor
391 */
392 template <typename T, typename D>
393 void fill_tensor_value(T &&tensor, D value) const;
394
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100395private:
396 // Function prototype to convert between image formats.
397 using Converter = void (*)(const RawTensor &src, RawTensor &dst);
398 // Function prototype to extract a channel from an image.
399 using Extractor = void (*)(const RawTensor &src, RawTensor &dst);
400 // Function prototype to load an image file.
401 using Loader = RawTensor (*)(const std::string &path);
402
403 const Converter &get_converter(Format src, Format dst) const;
404 const Converter &get_converter(DataType src, Format dst) const;
405 const Converter &get_converter(Format src, DataType dst) const;
406 const Converter &get_converter(DataType src, DataType dst) const;
407 const Extractor &get_extractor(Format format, Channel) const;
408 const Loader &get_loader(const std::string &extension) const;
409
410 /** Creates a raw tensor from the specified image.
411 *
412 * @param[in] name To be loaded image file.
413 *
414 * @note If use_single_image is true @p name is ignored and the user image
415 * is loaded instead.
416 */
417 RawTensor load_image(const std::string &name) const;
418
419 /** Provides a raw tensor for the specified image and format.
420 *
421 * @param[in] name Image file used to look up the raw tensor.
422 * @param[in] format Format used to look up the raw tensor.
423 *
424 * If the tensor has already been requested before the cached version will
425 * be returned. Otherwise the tensor will be added to the cache.
426 *
427 * @note If use_single_image is true @p name is ignored and the user image
428 * is loaded instead.
429 */
430 const RawTensor &find_or_create_raw_tensor(const std::string &name, Format format) const;
431
432 /** Provides a raw tensor for the specified image, format and channel.
433 *
434 * @param[in] name Image file used to look up the raw tensor.
435 * @param[in] format Format used to look up the raw tensor.
436 * @param[in] channel Channel used to look up the raw tensor.
437 *
438 * If the tensor has already been requested before the cached version will
439 * be returned. Otherwise the tensor will be added to the cache.
440 *
441 * @note If use_single_image is true @p name is ignored and the user image
442 * is loaded instead.
443 */
444 const RawTensor &find_or_create_raw_tensor(const std::string &name, Format format, Channel channel) const;
445
446 mutable TensorCache _cache{};
Georgios Pinitas421405b2018-10-26 19:05:32 +0100447 mutable arm_compute::Mutex _format_lock{};
448 mutable arm_compute::Mutex _channel_lock{};
Anthony Barbierac69aa12017-07-03 17:39:37 +0100449 const std::string _library_path;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100450 std::random_device::result_type _seed;
451};
452
Georgios Pinitas587708b2018-12-31 15:43:52 +0000453namespace detail
454{
455template <typename T>
456inline std::vector<std::pair<T, T>> convert_range_pair(const std::vector<AssetsLibrary::RangePair> &excluded_range_pairs)
457{
458 std::vector<std::pair<T, T>> converted;
459 std::transform(excluded_range_pairs.begin(),
460 excluded_range_pairs.end(),
461 std::back_inserter(converted),
462 [](const AssetsLibrary::RangePair & p)
463 {
464 return std::pair<T, T>(static_cast<T>(p.first), static_cast<T>(p.second));
465 });
466 return converted;
467}
Matthew Bentham470bc1e2020-03-09 10:55:40 +0000468
469/* Read npy header and check the payload is suitable for the specified type and shape
470 *
471 * @param[in] stream ifstream of the npy file
472 * @param[in] expect_typestr Expected typestr
473 * @param[in] expect_shape Shape of tensor expected to receive the data
474 *
475 * @note Advances stream to the beginning of the data payload
476 */
477void validate_npy_header(std::ifstream &stream, const std::string &expect_typestr, const TensorShape &expect_shape);
Georgios Pinitas587708b2018-12-31 15:43:52 +0000478} // namespace detail
479
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100480template <typename T, typename D>
Giorgio Arenaa2611812017-07-21 10:08:48 +0100481void AssetsLibrary::fill_borders_with_garbage(T &&tensor, D &&distribution, std::random_device::result_type seed_offset) const
482{
483 const PaddingSize padding_size = tensor.padding();
484
485 Window window;
486 window.set(0, Window::Dimension(-padding_size.left, tensor.shape()[0] + padding_size.right, 1));
Gian Marco5420b282017-11-29 10:41:38 +0000487 if(tensor.shape().num_dimensions() > 1)
488 {
489 window.set(1, Window::Dimension(-padding_size.top, tensor.shape()[1] + padding_size.bottom, 1));
490 }
Giorgio Arenaa2611812017-07-21 10:08:48 +0100491
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100492 std::mt19937 gen(_seed + seed_offset);
Giorgio Arenaa2611812017-07-21 10:08:48 +0100493
494 execute_window_loop(window, [&](const Coordinates & id)
495 {
496 TensorShape shape = tensor.shape();
497
498 // If outside of valid region
499 if(id.x() < 0 || id.x() >= static_cast<int>(shape.x()) || id.y() < 0 || id.y() >= static_cast<int>(shape.y()))
500 {
501 using ResultType = typename std::remove_reference<D>::type::result_type;
502 const ResultType value = distribution(gen);
503 void *const out_ptr = tensor(id);
504 store_value_with_data_type(out_ptr, value, tensor.data_type());
505 }
506 });
507}
508
509template <typename T, typename D>
Pablo Telloe96e4f02018-12-21 16:47:23 +0000510void AssetsLibrary::fill_boxes(T &&tensor, D &&distribution, std::random_device::result_type seed_offset) const
511{
512 using ResultType = typename std::remove_reference<D>::type::result_type;
Michalis Spyroufae513c2019-10-16 17:41:33 +0100513 std::mt19937 gen(_seed + seed_offset);
514 TensorShape shape(tensor.shape());
515 const uint32_t num_boxes = tensor.num_elements() / 4;
Pablo Telloe96e4f02018-12-21 16:47:23 +0000516 // Iterate over all elements
517 std::uniform_real_distribution<> size_dist(0.f, 1.f);
Michalis Spyroufae513c2019-10-16 17:41:33 +0100518 for(uint32_t element_idx = 0; element_idx < num_boxes * 4; element_idx += 4)
Pablo Telloe96e4f02018-12-21 16:47:23 +0000519 {
520 const ResultType delta = size_dist(gen);
521 const ResultType epsilon = size_dist(gen);
522 const ResultType left = distribution(gen);
523 const ResultType top = distribution(gen);
524 const ResultType right = left + delta;
525 const ResultType bottom = top + epsilon;
526 const std::tuple<ResultType, ResultType, ResultType, ResultType> box(left, top, right, bottom);
527 Coordinates x1 = index2coord(shape, element_idx);
528 Coordinates y1 = index2coord(shape, element_idx + 1);
529 Coordinates x2 = index2coord(shape, element_idx + 2);
530 Coordinates y2 = index2coord(shape, element_idx + 3);
531 ResultType &target_value_x1 = reinterpret_cast<ResultType *>(tensor(x1))[0];
532 ResultType &target_value_y1 = reinterpret_cast<ResultType *>(tensor(y1))[0];
533 ResultType &target_value_x2 = reinterpret_cast<ResultType *>(tensor(x2))[0];
534 ResultType &target_value_y2 = reinterpret_cast<ResultType *>(tensor(y2))[0];
535 store_value_with_data_type(&target_value_x1, std::get<0>(box), tensor.data_type());
536 store_value_with_data_type(&target_value_y1, std::get<1>(box), tensor.data_type());
537 store_value_with_data_type(&target_value_x2, std::get<2>(box), tensor.data_type());
538 store_value_with_data_type(&target_value_y2, std::get<3>(box), tensor.data_type());
539 }
540 fill_borders_with_garbage(tensor, distribution, seed_offset);
541}
542
543template <typename T, typename D>
Vidhya Sudhan Loganathan951b8a42019-11-04 14:42:08 +0000544void AssetsLibrary::fill(std::vector<T> &vec, D &&distribution, std::random_device::result_type seed_offset) const
545{
546 ARM_COMPUTE_ERROR_ON_MSG(vec.empty(), "Vector must not be empty");
547
548 using ResultType = typename std::remove_reference<D>::type::result_type;
549
550 std::mt19937 gen(_seed + seed_offset);
551 for(size_t i = 0; i < vec.size(); ++i)
552 {
553 const ResultType value = distribution(gen);
554
555 vec[i] = value;
556 }
557}
558
559template <typename T, typename D>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100560void AssetsLibrary::fill(T &&tensor, D &&distribution, std::random_device::result_type seed_offset) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100561{
Ioan-Cristian Szabo9414f642017-10-27 17:35:40 +0100562 using ResultType = typename std::remove_reference<D>::type::result_type;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100563
564 std::mt19937 gen(_seed + seed_offset);
565
Giorgio Arena563494c2018-04-30 17:29:41 +0100566 const bool is_nhwc = tensor.data_layout() == DataLayout::NHWC;
567 TensorShape shape(tensor.shape());
568
569 if(is_nhwc)
570 {
571 // Ensure that the equivalent tensors will be filled for both data layouts
572 permute(shape, PermutationVector(1U, 2U, 0U));
573 }
574
Ioan-Cristian Szabo9414f642017-10-27 17:35:40 +0100575 // Iterate over all elements
Michalis Spyroufae513c2019-10-16 17:41:33 +0100576 const uint32_t num_elements = tensor.num_elements();
577 for(uint32_t element_idx = 0; element_idx < num_elements; ++element_idx)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100578 {
Giorgio Arena563494c2018-04-30 17:29:41 +0100579 Coordinates id = index2coord(shape, element_idx);
580
581 if(is_nhwc)
582 {
583 // Write in the correct id for permuted shapes
584 permute(id, PermutationVector(2U, 0U, 1U));
585 }
Ioan-Cristian Szabo9414f642017-10-27 17:35:40 +0100586
587 // Iterate over all channels
588 for(int channel = 0; channel < tensor.num_channels(); ++channel)
589 {
590 const ResultType value = distribution(gen);
Kohei Takahashicedb78f2018-08-23 10:23:52 +0900591 ResultType &target_value = reinterpret_cast<ResultType *>(tensor(id))[channel];
Ioan-Cristian Szabo9414f642017-10-27 17:35:40 +0100592
593 store_value_with_data_type(&target_value, value, tensor.data_type());
594 }
595 }
Giorgio Arenaa2611812017-07-21 10:08:48 +0100596
597 fill_borders_with_garbage(tensor, distribution, seed_offset);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100598}
599
600template <typename D>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100601void AssetsLibrary::fill(RawTensor &raw, D &&distribution, std::random_device::result_type seed_offset) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100602{
603 std::mt19937 gen(_seed + seed_offset);
604
605 for(size_t offset = 0; offset < raw.size(); offset += raw.element_size())
606 {
607 using ResultType = typename std::remove_reference<D>::type::result_type;
608 const ResultType value = distribution(gen);
Georgios Pinitas587708b2018-12-31 15:43:52 +0000609
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100610 store_value_with_data_type(raw.data() + offset, value, raw.data_type());
611 }
612}
613
614template <typename T>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100615void AssetsLibrary::fill(T &&tensor, const std::string &name, Format format) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100616{
617 const RawTensor &raw = get(name, format);
618
619 for(size_t offset = 0; offset < raw.size(); offset += raw.element_size())
620 {
621 const Coordinates id = index2coord(raw.shape(), offset / raw.element_size());
622
Moritz Pflanzer82e70a12017-08-08 16:20:45 +0100623 const RawTensor::value_type *const raw_ptr = raw.data() + offset;
624 const auto out_ptr = static_cast<RawTensor::value_type *>(tensor(id));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100625 std::copy_n(raw_ptr, raw.element_size(), out_ptr);
626 }
627}
628
629template <typename T>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100630void AssetsLibrary::fill(T &&tensor, const std::string &name, Channel channel) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100631{
632 fill(std::forward<T>(tensor), name, get_format_for_channel(channel), channel);
633}
634
635template <typename T>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100636void AssetsLibrary::fill(T &&tensor, const std::string &name, Format format, Channel channel) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100637{
638 const RawTensor &raw = get(name, format, channel);
639
640 for(size_t offset = 0; offset < raw.size(); offset += raw.element_size())
641 {
642 const Coordinates id = index2coord(raw.shape(), offset / raw.element_size());
643
Moritz Pflanzer82e70a12017-08-08 16:20:45 +0100644 const RawTensor::value_type *const raw_ptr = raw.data() + offset;
645 const auto out_ptr = static_cast<RawTensor::value_type *>(tensor(id));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100646 std::copy_n(raw_ptr, raw.element_size(), out_ptr);
647 }
648}
649
650template <typename T>
Alex Gilday345ab182018-01-09 11:40:19 +0000651void AssetsLibrary::fill(T &&tensor, RawTensor raw) const
652{
653 for(size_t offset = 0; offset < raw.size(); offset += raw.element_size())
654 {
655 const Coordinates id = index2coord(raw.shape(), offset / raw.element_size());
656
657 const RawTensor::value_type *const raw_ptr = raw.data() + offset;
658 const auto out_ptr = static_cast<RawTensor::value_type *>(tensor(id));
659 std::copy_n(raw_ptr, raw.element_size(), out_ptr);
660 }
661}
662
663template <typename T>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100664void AssetsLibrary::fill_tensor_uniform(T &&tensor, std::random_device::result_type seed_offset) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100665{
666 switch(tensor.data_type())
667 {
668 case DataType::U8:
Anton Lokhmotovaf6204c2017-11-08 09:34:19 +0000669 case DataType::QASYMM8:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100670 {
671 std::uniform_int_distribution<uint8_t> distribution_u8(std::numeric_limits<uint8_t>::lowest(), std::numeric_limits<uint8_t>::max());
672 fill(tensor, distribution_u8, seed_offset);
673 break;
674 }
675 case DataType::S8:
Georgios Pinitas3d13af82019-06-04 13:04:16 +0100676 case DataType::QSYMM8:
Georgios Pinitas8217c8e2019-11-11 18:24:22 +0000677 case DataType::QSYMM8_PER_CHANNEL:
Georgios Pinitasdbdea0d2019-10-16 19:21:40 +0100678 case DataType::QASYMM8_SIGNED:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100679 {
680 std::uniform_int_distribution<int8_t> distribution_s8(std::numeric_limits<int8_t>::lowest(), std::numeric_limits<int8_t>::max());
681 fill(tensor, distribution_s8, seed_offset);
682 break;
683 }
684 case DataType::U16:
685 {
686 std::uniform_int_distribution<uint16_t> distribution_u16(std::numeric_limits<uint16_t>::lowest(), std::numeric_limits<uint16_t>::max());
687 fill(tensor, distribution_u16, seed_offset);
688 break;
689 }
690 case DataType::S16:
Manuel Bottini3689fcd2019-06-14 17:18:12 +0100691 case DataType::QSYMM16:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100692 {
693 std::uniform_int_distribution<int16_t> distribution_s16(std::numeric_limits<int16_t>::lowest(), std::numeric_limits<int16_t>::max());
694 fill(tensor, distribution_s16, seed_offset);
695 break;
696 }
697 case DataType::U32:
698 {
699 std::uniform_int_distribution<uint32_t> distribution_u32(std::numeric_limits<uint32_t>::lowest(), std::numeric_limits<uint32_t>::max());
700 fill(tensor, distribution_u32, seed_offset);
701 break;
702 }
703 case DataType::S32:
704 {
705 std::uniform_int_distribution<int32_t> distribution_s32(std::numeric_limits<int32_t>::lowest(), std::numeric_limits<int32_t>::max());
706 fill(tensor, distribution_s32, seed_offset);
707 break;
708 }
709 case DataType::U64:
710 {
711 std::uniform_int_distribution<uint64_t> distribution_u64(std::numeric_limits<uint64_t>::lowest(), std::numeric_limits<uint64_t>::max());
712 fill(tensor, distribution_u64, seed_offset);
713 break;
714 }
715 case DataType::S64:
716 {
717 std::uniform_int_distribution<int64_t> distribution_s64(std::numeric_limits<int64_t>::lowest(), std::numeric_limits<int64_t>::max());
718 fill(tensor, distribution_s64, seed_offset);
719 break;
720 }
Georgios Pinitase8291ac2020-02-26 09:58:13 +0000721 case DataType::BFLOAT16:
722 {
723 // It doesn't make sense to check [-inf, inf], so hard code it to a big number
724 std::uniform_real_distribution<float> distribution_bf16(-1000.f, 1000.f);
725 fill(tensor, distribution_bf16, seed_offset);
726 break;
727 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100728 case DataType::F16:
SiCong Li02dfb2c2017-07-27 17:59:20 +0100729 {
730 // It doesn't make sense to check [-inf, inf], so hard code it to a big number
731 std::uniform_real_distribution<float> distribution_f16(-100.f, 100.f);
732 fill(tensor, distribution_f16, seed_offset);
733 break;
734 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100735 case DataType::F32:
736 {
737 // It doesn't make sense to check [-inf, inf], so hard code it to a big number
738 std::uniform_real_distribution<float> distribution_f32(-1000.f, 1000.f);
739 fill(tensor, distribution_f32, seed_offset);
740 break;
741 }
742 case DataType::F64:
743 {
744 // It doesn't make sense to check [-inf, inf], so hard code it to a big number
745 std::uniform_real_distribution<double> distribution_f64(-1000.f, 1000.f);
746 fill(tensor, distribution_f64, seed_offset);
747 break;
748 }
749 case DataType::SIZET:
750 {
751 std::uniform_int_distribution<size_t> distribution_sizet(std::numeric_limits<size_t>::lowest(), std::numeric_limits<size_t>::max());
752 fill(tensor, distribution_sizet, seed_offset);
753 break;
754 }
755 default:
756 ARM_COMPUTE_ERROR("NOT SUPPORTED!");
757 }
758}
759
Georgios Pinitas587708b2018-12-31 15:43:52 +0000760template <typename T>
761void AssetsLibrary::fill_tensor_uniform_ranged(T &&tensor,
762 std::random_device::result_type seed_offset,
763 const std::vector<AssetsLibrary::RangePair> &excluded_range_pairs) const
764{
765 using namespace arm_compute::utils::random;
766
767 switch(tensor.data_type())
768 {
769 case DataType::U8:
770 case DataType::QASYMM8:
771 {
772 const auto converted_pairs = detail::convert_range_pair<uint8_t>(excluded_range_pairs);
773 RangedUniformDistribution<uint8_t> distribution_u8(std::numeric_limits<uint8_t>::lowest(),
774 std::numeric_limits<uint8_t>::max(),
775 converted_pairs);
776 fill(tensor, distribution_u8, seed_offset);
777 break;
778 }
779 case DataType::S8:
Georgios Pinitas3d13af82019-06-04 13:04:16 +0100780 case DataType::QSYMM8:
Georgios Pinitas587708b2018-12-31 15:43:52 +0000781 {
782 const auto converted_pairs = detail::convert_range_pair<int8_t>(excluded_range_pairs);
783 RangedUniformDistribution<int8_t> distribution_s8(std::numeric_limits<int8_t>::lowest(),
784 std::numeric_limits<int8_t>::max(),
785 converted_pairs);
786 fill(tensor, distribution_s8, seed_offset);
787 break;
788 }
789 case DataType::U16:
790 {
791 const auto converted_pairs = detail::convert_range_pair<uint16_t>(excluded_range_pairs);
792 RangedUniformDistribution<uint16_t> distribution_u16(std::numeric_limits<uint16_t>::lowest(),
793 std::numeric_limits<uint16_t>::max(),
794 converted_pairs);
795 fill(tensor, distribution_u16, seed_offset);
796 break;
797 }
798 case DataType::S16:
Manuel Bottini3689fcd2019-06-14 17:18:12 +0100799 case DataType::QSYMM16:
Georgios Pinitas587708b2018-12-31 15:43:52 +0000800 {
801 const auto converted_pairs = detail::convert_range_pair<int16_t>(excluded_range_pairs);
802 RangedUniformDistribution<int16_t> distribution_s16(std::numeric_limits<int16_t>::lowest(),
803 std::numeric_limits<int16_t>::max(),
804 converted_pairs);
805 fill(tensor, distribution_s16, seed_offset);
806 break;
807 }
808 case DataType::U32:
809 {
810 const auto converted_pairs = detail::convert_range_pair<uint32_t>(excluded_range_pairs);
811 RangedUniformDistribution<uint32_t> distribution_u32(std::numeric_limits<uint32_t>::lowest(),
812 std::numeric_limits<uint32_t>::max(),
813 converted_pairs);
814 fill(tensor, distribution_u32, seed_offset);
815 break;
816 }
817 case DataType::S32:
818 {
819 const auto converted_pairs = detail::convert_range_pair<int32_t>(excluded_range_pairs);
820 RangedUniformDistribution<int32_t> distribution_s32(std::numeric_limits<int32_t>::lowest(),
821 std::numeric_limits<int32_t>::max(),
822 converted_pairs);
823 fill(tensor, distribution_s32, seed_offset);
824 break;
825 }
Georgios Pinitase8291ac2020-02-26 09:58:13 +0000826 case DataType::BFLOAT16:
827 {
828 // It doesn't make sense to check [-inf, inf], so hard code it to a big number
829 const auto converted_pairs = detail::convert_range_pair<float>(excluded_range_pairs);
830 RangedUniformDistribution<float> distribution_bf16(-1000.f, 1000.f, converted_pairs);
831 fill(tensor, distribution_bf16, seed_offset);
832 break;
833 }
Georgios Pinitas587708b2018-12-31 15:43:52 +0000834 case DataType::F16:
835 {
836 // It doesn't make sense to check [-inf, inf], so hard code it to a big number
837 const auto converted_pairs = detail::convert_range_pair<float>(excluded_range_pairs);
838 RangedUniformDistribution<float> distribution_f16(-100.f, 100.f, converted_pairs);
839 fill(tensor, distribution_f16, seed_offset);
840 break;
841 }
842 case DataType::F32:
843 {
844 // It doesn't make sense to check [-inf, inf], so hard code it to a big number
845 const auto converted_pairs = detail::convert_range_pair<float>(excluded_range_pairs);
846 RangedUniformDistribution<float> distribution_f32(-1000.f, 1000.f, converted_pairs);
847 fill(tensor, distribution_f32, seed_offset);
848 break;
849 }
850 default:
851 ARM_COMPUTE_ERROR("NOT SUPPORTED!");
852 }
853}
854
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100855template <typename T, typename D>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100856void 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 +0100857{
858 switch(tensor.data_type())
859 {
860 case DataType::U8:
Anton Lokhmotovaf6204c2017-11-08 09:34:19 +0000861 case DataType::QASYMM8:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100862 {
863 ARM_COMPUTE_ERROR_ON(!(std::is_same<uint8_t, D>::value));
864 std::uniform_int_distribution<uint8_t> distribution_u8(low, high);
865 fill(tensor, distribution_u8, seed_offset);
866 break;
867 }
868 case DataType::S8:
Georgios Pinitas3d13af82019-06-04 13:04:16 +0100869 case DataType::QSYMM8:
Sang-Hoon Parkd8176472019-12-04 09:46:28 +0000870 case DataType::QASYMM8_SIGNED:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100871 {
872 ARM_COMPUTE_ERROR_ON(!(std::is_same<int8_t, D>::value));
873 std::uniform_int_distribution<int8_t> distribution_s8(low, high);
874 fill(tensor, distribution_s8, seed_offset);
875 break;
876 }
877 case DataType::U16:
878 {
879 ARM_COMPUTE_ERROR_ON(!(std::is_same<uint16_t, D>::value));
880 std::uniform_int_distribution<uint16_t> distribution_u16(low, high);
881 fill(tensor, distribution_u16, seed_offset);
882 break;
883 }
884 case DataType::S16:
Manuel Bottini3689fcd2019-06-14 17:18:12 +0100885 case DataType::QSYMM16:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100886 {
887 ARM_COMPUTE_ERROR_ON(!(std::is_same<int16_t, D>::value));
888 std::uniform_int_distribution<int16_t> distribution_s16(low, high);
889 fill(tensor, distribution_s16, seed_offset);
890 break;
891 }
892 case DataType::U32:
893 {
894 ARM_COMPUTE_ERROR_ON(!(std::is_same<uint32_t, D>::value));
895 std::uniform_int_distribution<uint32_t> distribution_u32(low, high);
896 fill(tensor, distribution_u32, seed_offset);
897 break;
898 }
899 case DataType::S32:
900 {
901 ARM_COMPUTE_ERROR_ON(!(std::is_same<int32_t, D>::value));
902 std::uniform_int_distribution<int32_t> distribution_s32(low, high);
903 fill(tensor, distribution_s32, seed_offset);
904 break;
905 }
906 case DataType::U64:
907 {
908 ARM_COMPUTE_ERROR_ON(!(std::is_same<uint64_t, D>::value));
909 std::uniform_int_distribution<uint64_t> distribution_u64(low, high);
910 fill(tensor, distribution_u64, seed_offset);
911 break;
912 }
913 case DataType::S64:
914 {
915 ARM_COMPUTE_ERROR_ON(!(std::is_same<int64_t, D>::value));
916 std::uniform_int_distribution<int64_t> distribution_s64(low, high);
917 fill(tensor, distribution_s64, seed_offset);
918 break;
919 }
Georgios Pinitase8291ac2020-02-26 09:58:13 +0000920 case DataType::BFLOAT16:
921 {
922 std::uniform_real_distribution<float> distribution_bf16(low, high);
923 fill(tensor, distribution_bf16, seed_offset);
924 break;
925 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100926 case DataType::F16:
927 {
Moritz Pflanzere49e2662017-07-21 15:55:28 +0100928 std::uniform_real_distribution<float> distribution_f16(low, high);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100929 fill(tensor, distribution_f16, seed_offset);
930 break;
931 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100932 case DataType::F32:
933 {
934 ARM_COMPUTE_ERROR_ON(!(std::is_same<float, D>::value));
935 std::uniform_real_distribution<float> distribution_f32(low, high);
936 fill(tensor, distribution_f32, seed_offset);
937 break;
938 }
939 case DataType::F64:
940 {
941 ARM_COMPUTE_ERROR_ON(!(std::is_same<double, D>::value));
942 std::uniform_real_distribution<double> distribution_f64(low, high);
943 fill(tensor, distribution_f64, seed_offset);
944 break;
945 }
946 case DataType::SIZET:
947 {
948 ARM_COMPUTE_ERROR_ON(!(std::is_same<size_t, D>::value));
949 std::uniform_int_distribution<size_t> distribution_sizet(low, high);
950 fill(tensor, distribution_sizet, seed_offset);
951 break;
952 }
953 default:
954 ARM_COMPUTE_ERROR("NOT SUPPORTED!");
955 }
956}
957
958template <typename T>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100959void AssetsLibrary::fill_layer_data(T &&tensor, std::string name) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100960{
961#ifdef _WIN32
962 const std::string path_separator("\\");
Anthony Barbierac69aa12017-07-03 17:39:37 +0100963#else /* _WIN32 */
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100964 const std::string path_separator("/");
Anthony Barbierac69aa12017-07-03 17:39:37 +0100965#endif /* _WIN32 */
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100966 const std::string path = _library_path + path_separator + name;
967
968 // Open file
SiCong Li86b53332017-08-23 11:02:43 +0100969 std::ifstream stream(path, std::ios::in | std::ios::binary);
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100970 if(!stream.good())
971 {
972 throw framework::FileNotFound("Could not load npy file: " + path);
973 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100974
Matthew Bentham470bc1e2020-03-09 10:55:40 +0000975 validate_npy_header(stream, tensor.data_type(), tensor.shape());
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100976
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 */