blob: bd97cb7bd43d54b887f3efaa0003b6b2a5c64c0b [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
Giorgio Arena232c4522022-03-03 10:09:01 +00002 * Copyright (c) 2017-2022 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"
Sang-Hoon Park68dd25f2020-10-19 16:00:11 +010034#include "support/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"
Giorgio Arena6aeb2172020-12-15 15:45:43 +000039#include "utils/Utils.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010040
41#include <algorithm>
42#include <cstddef>
43#include <fstream>
44#include <random>
45#include <string>
46#include <type_traits>
SiCong Li86b53332017-08-23 11:02:43 +010047#include <vector>
Anthony Barbier6ff3b192017-09-04 18:44:23 +010048
49namespace arm_compute
50{
51namespace test
52{
53/** Factory class to create and fill tensors.
54 *
55 * Allows to initialise tensors from loaded images or by specifying the shape
56 * explicitly. Furthermore, provides methods to fill tensors with the content of
57 * loaded images or with random values.
58 */
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +010059class AssetsLibrary final
Anthony Barbier6ff3b192017-09-04 18:44:23 +010060{
61public:
Georgios Pinitas587708b2018-12-31 15:43:52 +000062 using RangePair = std::pair<float, float>;
63
64public:
John Richardson70f946b2017-10-02 16:52:16 +010065 /** Initialises the library with a @p path to the assets directory.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010066 * Furthermore, sets the seed for the random generator to @p seed.
67 *
John Richardson70f946b2017-10-02 16:52:16 +010068 * @param[in] path Path to load assets from.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010069 * @param[in] seed Seed used to initialise the random number generator.
70 */
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +010071 AssetsLibrary(std::string path, std::random_device::result_type seed);
Anthony Barbier6ff3b192017-09-04 18:44:23 +010072
Alex Gildayc357c472018-03-21 13:54:09 +000073 /** Path to assets directory used to initialise library.
74 *
75 * @return the path to the assets directory.
76 */
John Richardson70f946b2017-10-02 16:52:16 +010077 std::string path() const;
78
Alex Gildayc357c472018-03-21 13:54:09 +000079 /** Seed that is used to fill tensors with random values.
80 *
81 * @return the initial random seed.
82 */
Anthony Barbier6ff3b192017-09-04 18:44:23 +010083 std::random_device::result_type seed() const;
84
Giorgio Arenafda46182017-06-16 13:57:33 +010085 /** Provides a tensor shape for the specified image.
86 *
87 * @param[in] name Image file used to look up the raw tensor.
Alex Gildayc357c472018-03-21 13:54:09 +000088 *
89 * @return the tensor shape for the specified image.
Giorgio Arenafda46182017-06-16 13:57:33 +010090 */
91 TensorShape get_image_shape(const std::string &name);
92
Alex Gildayc357c472018-03-21 13:54:09 +000093 /** Provides a constant raw tensor for the specified image.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010094 *
95 * @param[in] name Image file used to look up the raw tensor.
Alex Gildayc357c472018-03-21 13:54:09 +000096 *
97 * @return a raw tensor for the specified image.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010098 */
99 const RawTensor &get(const std::string &name) const;
100
101 /** Provides a raw tensor for the specified image.
102 *
103 * @param[in] name Image file used to look up the raw tensor.
Alex Gildayc357c472018-03-21 13:54:09 +0000104 *
105 * @return a raw tensor for the specified image.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100106 */
107 RawTensor get(const std::string &name);
108
109 /** Creates an uninitialised raw tensor with the given @p data_type and @p
110 * num_channels. The shape is derived from the specified image.
111 *
112 * @param[in] name Image file used to initialise the tensor.
113 * @param[in] data_type Data type used to initialise the tensor.
114 * @param[in] num_channels Number of channels used to initialise the tensor.
Alex Gildayc357c472018-03-21 13:54:09 +0000115 *
116 * @return a raw tensor for the specified image.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100117 */
118 RawTensor get(const std::string &name, DataType data_type, int num_channels = 1) const;
119
120 /** Provides a contant raw tensor for the specified image after it has been
121 * converted to @p format.
122 *
123 * @param[in] name Image file used to look up the raw tensor.
124 * @param[in] format Format used to look up the raw tensor.
Alex Gildayc357c472018-03-21 13:54:09 +0000125 *
126 * @return a raw tensor for the specified image.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100127 */
128 const RawTensor &get(const std::string &name, Format format) const;
129
130 /** Provides a raw tensor for the specified image after it has been
131 * converted to @p format.
132 *
133 * @param[in] name Image file used to look up the raw tensor.
134 * @param[in] format Format used to look up the raw tensor.
Alex Gildayc357c472018-03-21 13:54:09 +0000135 *
136 * @return a raw tensor for the specified image.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100137 */
138 RawTensor get(const std::string &name, Format format);
139
140 /** Provides a contant raw tensor for the specified channel after it has
141 * been extracted form the given image.
142 *
143 * @param[in] name Image file used to look up the raw tensor.
144 * @param[in] channel Channel used to look up the raw tensor.
145 *
146 * @note The channel has to be unambiguous so that the format can be
147 * inferred automatically.
Alex Gildayc357c472018-03-21 13:54:09 +0000148 *
149 * @return a raw tensor for the specified image channel.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100150 */
151 const RawTensor &get(const std::string &name, Channel channel) const;
152
153 /** Provides a raw tensor for the specified channel after it has been
154 * extracted form the given image.
155 *
156 * @param[in] name Image file used to look up the raw tensor.
157 * @param[in] channel Channel used to look up the raw tensor.
158 *
159 * @note The channel has to be unambiguous so that the format can be
160 * inferred automatically.
Alex Gildayc357c472018-03-21 13:54:09 +0000161 *
162 * @return a raw tensor for the specified image channel.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100163 */
164 RawTensor get(const std::string &name, Channel channel);
165
166 /** Provides a constant raw tensor for the specified channel after it has
167 * been extracted form the given image formatted to @p format.
168 *
169 * @param[in] name Image file used to look up the raw tensor.
170 * @param[in] format Format used to look up the raw tensor.
171 * @param[in] channel Channel used to look up the raw tensor.
Alex Gildayc357c472018-03-21 13:54:09 +0000172 *
173 * @return a raw tensor for the specified image channel.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100174 */
175 const RawTensor &get(const std::string &name, Format format, Channel channel) const;
176
177 /** Provides a raw tensor for the specified channel after it has been
178 * extracted form the given image formatted to @p format.
179 *
180 * @param[in] name Image file used to look up the raw tensor.
181 * @param[in] format Format used to look up the raw tensor.
182 * @param[in] channel Channel used to look up the raw tensor.
Alex Gildayc357c472018-03-21 13:54:09 +0000183 *
184 * @return a raw tensor for the specified image channel.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100185 */
186 RawTensor get(const std::string &name, Format format, Channel channel);
187
Giorgio Arenaa2611812017-07-21 10:08:48 +0100188 /** Puts garbage values all around the tensor for testing purposes
189 *
190 * @param[in, out] tensor To be filled tensor.
191 * @param[in] distribution Distribution used to fill the tensor's surroundings.
192 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
193 */
194 template <typename T, typename D>
195 void fill_borders_with_garbage(T &&tensor, D &&distribution, std::random_device::result_type seed_offset) const;
196
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100197 /** Fills the specified @p tensor with random values drawn from @p
198 * distribution.
199 *
200 * @param[in, out] tensor To be filled tensor.
201 * @param[in] distribution Distribution used to fill the tensor.
202 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
203 *
204 * @note The @p distribution has to provide operator(Generator &) which
205 * will be used to draw samples.
206 */
207 template <typename T, typename D>
208 void fill(T &&tensor, D &&distribution, std::random_device::result_type seed_offset) const;
209
Pablo Telloe96e4f02018-12-21 16:47:23 +0000210 template <typename T, typename D>
211 void fill_boxes(T &&tensor, D &&distribution, std::random_device::result_type seed_offset) const;
212
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100213 /** Fills the specified @p raw tensor with random values drawn from @p
214 * distribution.
215 *
Vidhya Sudhan Loganathan951b8a42019-11-04 14:42:08 +0000216 * @param[in, out] vec To be filled vector.
217 * @param[in] distribution Distribution used to fill the tensor.
218 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
219 *
220 * @note The @p distribution has to provide operator(Generator &) which
221 * will be used to draw samples.
222 */
223 template <typename T, typename D>
224 void fill(std::vector<T> &vec, D &&distribution, std::random_device::result_type seed_offset) const;
225
226 /** Fills the specified @p raw tensor with random values drawn from @p
227 * distribution.
228 *
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100229 * @param[in, out] raw To be filled raw.
230 * @param[in] distribution Distribution used to fill the tensor.
231 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
232 *
233 * @note The @p distribution has to provide operator(Generator &) which
234 * will be used to draw samples.
235 */
236 template <typename D>
237 void fill(RawTensor &raw, D &&distribution, std::random_device::result_type seed_offset) const;
238
239 /** Fills the specified @p tensor with the content of the specified image
240 * converted to the given format.
241 *
242 * @param[in, out] tensor To be filled tensor.
243 * @param[in] name Image file used to fill the tensor.
244 * @param[in] format Format of the image used to fill the tensor.
245 *
246 * @warning No check is performed that the specified format actually
247 * matches the format of the tensor.
248 */
249 template <typename T>
250 void fill(T &&tensor, const std::string &name, Format format) const;
251
252 /** Fills the raw tensor with the content of the specified image
253 * converted to the given format.
254 *
255 * @param[in, out] raw To be filled raw tensor.
256 * @param[in] name Image file used to fill the tensor.
257 * @param[in] format Format of the image used to fill the tensor.
258 *
259 * @warning No check is performed that the specified format actually
260 * matches the format of the tensor.
261 */
262 void fill(RawTensor &raw, const std::string &name, Format format) const;
263
264 /** Fills the specified @p tensor with the content of the specified channel
265 * extracted from the given image.
266 *
267 * @param[in, out] tensor To be filled tensor.
268 * @param[in] name Image file used to fill the tensor.
269 * @param[in] channel Channel of the image used to fill the tensor.
270 *
271 * @note The channel has to be unambiguous so that the format can be
272 * inferred automatically.
273 *
274 * @warning No check is performed that the specified format actually
275 * matches the format of the tensor.
276 */
277 template <typename T>
278 void fill(T &&tensor, const std::string &name, Channel channel) const;
279
280 /** Fills the raw tensor with the content of the specified channel
281 * extracted from the given image.
282 *
283 * @param[in, out] raw To be filled raw tensor.
284 * @param[in] name Image file used to fill the tensor.
285 * @param[in] channel Channel of the image used to fill the tensor.
286 *
287 * @note The channel has to be unambiguous so that the format can be
288 * inferred automatically.
289 *
290 * @warning No check is performed that the specified format actually
291 * matches the format of the tensor.
292 */
293 void fill(RawTensor &raw, const std::string &name, Channel channel) const;
294
295 /** Fills the specified @p tensor with the content of the specified channel
296 * extracted from the given image after it has been converted to the given
297 * format.
298 *
299 * @param[in, out] tensor To be filled tensor.
300 * @param[in] name Image file used to fill the tensor.
301 * @param[in] format Format of the image used to fill the tensor.
302 * @param[in] channel Channel of the image used to fill the tensor.
303 *
304 * @warning No check is performed that the specified format actually
305 * matches the format of the tensor.
306 */
307 template <typename T>
308 void fill(T &&tensor, const std::string &name, Format format, Channel channel) const;
309
310 /** Fills the raw tensor with the content of the specified channel
311 * extracted from the given image after it has been converted to the given
312 * format.
313 *
314 * @param[in, out] raw To be filled raw tensor.
315 * @param[in] name Image file used to fill the tensor.
316 * @param[in] format Format of the image used to fill the tensor.
317 * @param[in] channel Channel of the image used to fill the tensor.
318 *
319 * @warning No check is performed that the specified format actually
320 * matches the format of the tensor.
321 */
322 void fill(RawTensor &raw, const std::string &name, Format format, Channel channel) const;
323
Alex Gilday345ab182018-01-09 11:40:19 +0000324 /** Fills the specified @p tensor with the content of the raw tensor.
325 *
326 * @param[in, out] tensor To be filled tensor.
327 * @param[in] raw Raw tensor used to fill the tensor.
328 *
329 * @warning No check is performed that the specified format actually
330 * matches the format of the tensor.
331 */
332 template <typename T>
333 void fill(T &&tensor, RawTensor raw) const;
334
Georgios Pinitas587708b2018-12-31 15:43:52 +0000335 /** Fill a tensor with uniform distribution
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100336 *
337 * @param[in, out] tensor To be filled tensor.
338 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
339 */
340 template <typename T>
341 void fill_tensor_uniform(T &&tensor, std::random_device::result_type seed_offset) const;
342
Georgios Pinitas587708b2018-12-31 15:43:52 +0000343 /** Fill a tensor with uniform distribution
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100344 *
345 * @param[in, out] tensor To be filled tensor.
346 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
347 * @param[in] low lowest value in the range (inclusive)
348 * @param[in] high highest value in the range (inclusive)
349 *
350 * @note @p low and @p high must be of the same type as the data type of @p tensor
351 */
352 template <typename T, typename D>
353 void fill_tensor_uniform(T &&tensor, std::random_device::result_type seed_offset, D low, D high) const;
354
Georgios Pinitas587708b2018-12-31 15:43:52 +0000355 /** Fill a tensor with uniform distribution across the specified range
356 *
357 * @param[in, out] tensor To be filled tensor.
358 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
359 * @param[in] excluded_range_pairs Ranges to exclude from the generator
360 */
361 template <typename T>
362 void fill_tensor_uniform_ranged(T &&tensor,
363 std::random_device::result_type seed_offset,
364 const std::vector<AssetsLibrary::RangePair> &excluded_range_pairs) const;
365
SiCong Li86b53332017-08-23 11:02:43 +0100366 /** Fills the specified @p tensor with data loaded from .npy (numpy binary) in specified path.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100367 *
368 * @param[in, out] tensor To be filled tensor.
369 * @param[in] name Data file.
SiCong Li86b53332017-08-23 11:02:43 +0100370 *
371 * @note The numpy array stored in the binary .npy file must be row-major in the sense that it
372 * must store elements within a row consecutively in the memory, then rows within a 2D slice,
373 * then 2D slices within a 3D slice and so on. Note that it imposes no restrictions on what
374 * indexing convention is used in the numpy array. That is, the numpy array can be either fortran
375 * style or C style as long as it adheres to the rule above.
376 *
377 * More concretely, the orders of dimensions for each style are as follows:
378 * C-style (numpy default):
379 * array[HigherDims..., Z, Y, X]
380 * Fortran style:
381 * array[X, Y, Z, HigherDims...]
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100382 */
383 template <typename T>
384 void fill_layer_data(T &&tensor, std::string name) const;
385
Michele Di Giorgio4d336302018-03-02 09:43:54 +0000386 /** Fill a tensor with a constant value
387 *
388 * @param[in, out] tensor To be filled tensor.
389 * @param[in] value Value to be assigned to all elements of the input tensor.
390 *
391 * @note @p value must be of the same type as the data type of @p tensor
392 */
393 template <typename T, typename D>
394 void fill_tensor_value(T &&tensor, D value) const;
395
Sang-Hoon Parka8a7c1d2020-05-12 22:01:23 +0100396 /** Fill a tensor with a given vector with static values.
397 *
398 * @param[in, out] tensor To be filled tensor.
399 * @param[in] values A vector containing values
400 *
401 * To cope with various size tensors, the vector size doens't have to be
402 * the same as tensor's size. If the size of the tensor is larger than the vector,
403 * the iterator the vector will keep iterating and wrap around. If the vector is
404 * larger, values located after the required size won't be used.
405 */
406 template <typename T, typename DataType>
407 void fill_static_values(T &&tensor, const std::vector<DataType> &values) const;
408
Giorgio Arena232c4522022-03-03 10:09:01 +0000409 // Function type to generate a number to fill tensors.
410 template <typename ResultType>
411 using GeneratorFunctionType = std::function<ResultType(void)>;
412 /** Fill a tensor with a value generator function.
413 *
414 * @param[in, out] tensor To be filled tensor.
415 * @param[in] generate_value A function that generates values.
416 */
417 template <typename T, typename ResultType>
418 void fill_with_generator(T &&tensor, const GeneratorFunctionType<ResultType> &generate_value) const;
419
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100420private:
421 // Function prototype to convert between image formats.
422 using Converter = void (*)(const RawTensor &src, RawTensor &dst);
423 // Function prototype to extract a channel from an image.
424 using Extractor = void (*)(const RawTensor &src, RawTensor &dst);
425 // Function prototype to load an image file.
426 using Loader = RawTensor (*)(const std::string &path);
427
428 const Converter &get_converter(Format src, Format dst) const;
429 const Converter &get_converter(DataType src, Format dst) const;
430 const Converter &get_converter(Format src, DataType dst) const;
431 const Converter &get_converter(DataType src, DataType dst) const;
432 const Extractor &get_extractor(Format format, Channel) const;
433 const Loader &get_loader(const std::string &extension) const;
434
435 /** Creates a raw tensor from the specified image.
436 *
437 * @param[in] name To be loaded image file.
438 *
439 * @note If use_single_image is true @p name is ignored and the user image
440 * is loaded instead.
441 */
442 RawTensor load_image(const std::string &name) const;
443
444 /** Provides a raw tensor for the specified image and format.
445 *
446 * @param[in] name Image file used to look up the raw tensor.
447 * @param[in] format Format used to look up the raw tensor.
448 *
449 * If the tensor has already been requested before the cached version will
450 * be returned. Otherwise the tensor will be added to the cache.
451 *
452 * @note If use_single_image is true @p name is ignored and the user image
453 * is loaded instead.
454 */
455 const RawTensor &find_or_create_raw_tensor(const std::string &name, Format format) const;
456
457 /** Provides a raw tensor for the specified image, format and channel.
458 *
459 * @param[in] name Image file used to look up the raw tensor.
460 * @param[in] format Format used to look up the raw tensor.
461 * @param[in] channel Channel used to look up the raw tensor.
462 *
463 * If the tensor has already been requested before the cached version will
464 * be returned. Otherwise the tensor will be added to the cache.
465 *
466 * @note If use_single_image is true @p name is ignored and the user image
467 * is loaded instead.
468 */
469 const RawTensor &find_or_create_raw_tensor(const std::string &name, Format format, Channel channel) const;
470
471 mutable TensorCache _cache{};
Georgios Pinitas421405b2018-10-26 19:05:32 +0100472 mutable arm_compute::Mutex _format_lock{};
473 mutable arm_compute::Mutex _channel_lock{};
Anthony Barbierac69aa12017-07-03 17:39:37 +0100474 const std::string _library_path;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100475 std::random_device::result_type _seed;
476};
477
Georgios Pinitas587708b2018-12-31 15:43:52 +0000478namespace detail
479{
480template <typename T>
481inline std::vector<std::pair<T, T>> convert_range_pair(const std::vector<AssetsLibrary::RangePair> &excluded_range_pairs)
482{
483 std::vector<std::pair<T, T>> converted;
484 std::transform(excluded_range_pairs.begin(),
485 excluded_range_pairs.end(),
486 std::back_inserter(converted),
487 [](const AssetsLibrary::RangePair & p)
488 {
489 return std::pair<T, T>(static_cast<T>(p.first), static_cast<T>(p.second));
490 });
491 return converted;
492}
Matthew Bentham470bc1e2020-03-09 10:55:40 +0000493
494/* Read npy header and check the payload is suitable for the specified type and shape
495 *
496 * @param[in] stream ifstream of the npy file
497 * @param[in] expect_typestr Expected typestr
498 * @param[in] expect_shape Shape of tensor expected to receive the data
499 *
500 * @note Advances stream to the beginning of the data payload
501 */
502void validate_npy_header(std::ifstream &stream, const std::string &expect_typestr, const TensorShape &expect_shape);
Georgios Pinitas587708b2018-12-31 15:43:52 +0000503} // namespace detail
504
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100505template <typename T, typename D>
Giorgio Arenaa2611812017-07-21 10:08:48 +0100506void AssetsLibrary::fill_borders_with_garbage(T &&tensor, D &&distribution, std::random_device::result_type seed_offset) const
507{
508 const PaddingSize padding_size = tensor.padding();
509
510 Window window;
511 window.set(0, Window::Dimension(-padding_size.left, tensor.shape()[0] + padding_size.right, 1));
Gian Marco5420b282017-11-29 10:41:38 +0000512 if(tensor.shape().num_dimensions() > 1)
513 {
514 window.set(1, Window::Dimension(-padding_size.top, tensor.shape()[1] + padding_size.bottom, 1));
515 }
Giorgio Arenaa2611812017-07-21 10:08:48 +0100516
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100517 std::mt19937 gen(_seed + seed_offset);
Giorgio Arenaa2611812017-07-21 10:08:48 +0100518
519 execute_window_loop(window, [&](const Coordinates & id)
520 {
521 TensorShape shape = tensor.shape();
522
523 // If outside of valid region
524 if(id.x() < 0 || id.x() >= static_cast<int>(shape.x()) || id.y() < 0 || id.y() >= static_cast<int>(shape.y()))
525 {
526 using ResultType = typename std::remove_reference<D>::type::result_type;
527 const ResultType value = distribution(gen);
528 void *const out_ptr = tensor(id);
529 store_value_with_data_type(out_ptr, value, tensor.data_type());
530 }
531 });
532}
533
534template <typename T, typename D>
Pablo Telloe96e4f02018-12-21 16:47:23 +0000535void AssetsLibrary::fill_boxes(T &&tensor, D &&distribution, std::random_device::result_type seed_offset) const
536{
Giorgio Arena4bdd1772020-12-17 16:47:07 +0000537 using DistributionType = typename std::remove_reference<D>::type;
538 using ResultType = typename DistributionType::result_type;
539
Michalis Spyroufae513c2019-10-16 17:41:33 +0100540 std::mt19937 gen(_seed + seed_offset);
541 TensorShape shape(tensor.shape());
542 const uint32_t num_boxes = tensor.num_elements() / 4;
Pablo Telloe96e4f02018-12-21 16:47:23 +0000543 // Iterate over all elements
Giorgio Arena4bdd1772020-12-17 16:47:07 +0000544 DistributionType size_dist{ ResultType(0.f), ResultType(1.f) };
Michalis Spyroufae513c2019-10-16 17:41:33 +0100545 for(uint32_t element_idx = 0; element_idx < num_boxes * 4; element_idx += 4)
Pablo Telloe96e4f02018-12-21 16:47:23 +0000546 {
547 const ResultType delta = size_dist(gen);
548 const ResultType epsilon = size_dist(gen);
549 const ResultType left = distribution(gen);
550 const ResultType top = distribution(gen);
551 const ResultType right = left + delta;
552 const ResultType bottom = top + epsilon;
553 const std::tuple<ResultType, ResultType, ResultType, ResultType> box(left, top, right, bottom);
554 Coordinates x1 = index2coord(shape, element_idx);
555 Coordinates y1 = index2coord(shape, element_idx + 1);
556 Coordinates x2 = index2coord(shape, element_idx + 2);
557 Coordinates y2 = index2coord(shape, element_idx + 3);
558 ResultType &target_value_x1 = reinterpret_cast<ResultType *>(tensor(x1))[0];
559 ResultType &target_value_y1 = reinterpret_cast<ResultType *>(tensor(y1))[0];
560 ResultType &target_value_x2 = reinterpret_cast<ResultType *>(tensor(x2))[0];
561 ResultType &target_value_y2 = reinterpret_cast<ResultType *>(tensor(y2))[0];
562 store_value_with_data_type(&target_value_x1, std::get<0>(box), tensor.data_type());
563 store_value_with_data_type(&target_value_y1, std::get<1>(box), tensor.data_type());
564 store_value_with_data_type(&target_value_x2, std::get<2>(box), tensor.data_type());
565 store_value_with_data_type(&target_value_y2, std::get<3>(box), tensor.data_type());
566 }
567 fill_borders_with_garbage(tensor, distribution, seed_offset);
568}
569
570template <typename T, typename D>
Vidhya Sudhan Loganathan951b8a42019-11-04 14:42:08 +0000571void AssetsLibrary::fill(std::vector<T> &vec, D &&distribution, std::random_device::result_type seed_offset) const
572{
573 ARM_COMPUTE_ERROR_ON_MSG(vec.empty(), "Vector must not be empty");
574
575 using ResultType = typename std::remove_reference<D>::type::result_type;
576
577 std::mt19937 gen(_seed + seed_offset);
578 for(size_t i = 0; i < vec.size(); ++i)
579 {
580 const ResultType value = distribution(gen);
581
582 vec[i] = value;
583 }
584}
585
Sang-Hoon Parka8a7c1d2020-05-12 22:01:23 +0100586template <typename T, typename ResultType>
587void AssetsLibrary::fill_with_generator(T &&tensor, const GeneratorFunctionType<ResultType> &generate_value) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100588{
Giorgio Arena563494c2018-04-30 17:29:41 +0100589 const bool is_nhwc = tensor.data_layout() == DataLayout::NHWC;
590 TensorShape shape(tensor.shape());
591
592 if(is_nhwc)
593 {
594 // Ensure that the equivalent tensors will be filled for both data layouts
595 permute(shape, PermutationVector(1U, 2U, 0U));
596 }
597
Ioan-Cristian Szabo9414f642017-10-27 17:35:40 +0100598 // Iterate over all elements
Michalis Spyroufae513c2019-10-16 17:41:33 +0100599 const uint32_t num_elements = tensor.num_elements();
600 for(uint32_t element_idx = 0; element_idx < num_elements; ++element_idx)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100601 {
Giorgio Arena563494c2018-04-30 17:29:41 +0100602 Coordinates id = index2coord(shape, element_idx);
603
604 if(is_nhwc)
605 {
606 // Write in the correct id for permuted shapes
607 permute(id, PermutationVector(2U, 0U, 1U));
608 }
Ioan-Cristian Szabo9414f642017-10-27 17:35:40 +0100609
610 // Iterate over all channels
611 for(int channel = 0; channel < tensor.num_channels(); ++channel)
612 {
Sang-Hoon Parka8a7c1d2020-05-12 22:01:23 +0100613 const ResultType value = generate_value();
Kohei Takahashicedb78f2018-08-23 10:23:52 +0900614 ResultType &target_value = reinterpret_cast<ResultType *>(tensor(id))[channel];
Ioan-Cristian Szabo9414f642017-10-27 17:35:40 +0100615
616 store_value_with_data_type(&target_value, value, tensor.data_type());
617 }
618 }
Sang-Hoon Parka8a7c1d2020-05-12 22:01:23 +0100619}
Giorgio Arenaa2611812017-07-21 10:08:48 +0100620
Sang-Hoon Parka8a7c1d2020-05-12 22:01:23 +0100621template <typename T, typename D>
622void AssetsLibrary::fill(T &&tensor, D &&distribution, std::random_device::result_type seed_offset) const
623{
624 using ResultType = typename std::remove_reference<D>::type::result_type;
625 std::mt19937 gen(_seed + seed_offset);
626
627 GeneratorFunctionType<ResultType> number_generator = [&]()
628 {
629 const ResultType value = distribution(gen);
630 return value;
631 };
632
633 fill_with_generator(tensor, number_generator);
Giorgio Arenaa2611812017-07-21 10:08:48 +0100634 fill_borders_with_garbage(tensor, distribution, seed_offset);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100635}
636
Sang-Hoon Parka8a7c1d2020-05-12 22:01:23 +0100637template <typename T, typename DataType>
638void AssetsLibrary::fill_static_values(T &&tensor, const std::vector<DataType> &values) const
639{
640 auto it = values.begin();
641 GeneratorFunctionType<DataType> get_next_value = [&]()
642 {
643 const DataType value = *it;
644 ++it;
645
646 if(it == values.end())
647 {
648 it = values.begin();
649 }
650
651 return value;
652 };
653
654 fill_with_generator(tensor, get_next_value);
655}
656
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100657template <typename D>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100658void AssetsLibrary::fill(RawTensor &raw, D &&distribution, std::random_device::result_type seed_offset) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100659{
660 std::mt19937 gen(_seed + seed_offset);
661
662 for(size_t offset = 0; offset < raw.size(); offset += raw.element_size())
663 {
664 using ResultType = typename std::remove_reference<D>::type::result_type;
665 const ResultType value = distribution(gen);
Georgios Pinitas587708b2018-12-31 15:43:52 +0000666
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100667 store_value_with_data_type(raw.data() + offset, value, raw.data_type());
668 }
669}
670
671template <typename T>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100672void AssetsLibrary::fill(T &&tensor, const std::string &name, Format format) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100673{
674 const RawTensor &raw = get(name, format);
675
676 for(size_t offset = 0; offset < raw.size(); offset += raw.element_size())
677 {
678 const Coordinates id = index2coord(raw.shape(), offset / raw.element_size());
679
Moritz Pflanzer82e70a12017-08-08 16:20:45 +0100680 const RawTensor::value_type *const raw_ptr = raw.data() + offset;
681 const auto out_ptr = static_cast<RawTensor::value_type *>(tensor(id));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100682 std::copy_n(raw_ptr, raw.element_size(), out_ptr);
683 }
684}
685
686template <typename T>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100687void AssetsLibrary::fill(T &&tensor, const std::string &name, Channel channel) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100688{
689 fill(std::forward<T>(tensor), name, get_format_for_channel(channel), channel);
690}
691
692template <typename T>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100693void AssetsLibrary::fill(T &&tensor, const std::string &name, Format format, Channel channel) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100694{
695 const RawTensor &raw = get(name, format, channel);
696
697 for(size_t offset = 0; offset < raw.size(); offset += raw.element_size())
698 {
699 const Coordinates id = index2coord(raw.shape(), offset / raw.element_size());
700
Moritz Pflanzer82e70a12017-08-08 16:20:45 +0100701 const RawTensor::value_type *const raw_ptr = raw.data() + offset;
702 const auto out_ptr = static_cast<RawTensor::value_type *>(tensor(id));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100703 std::copy_n(raw_ptr, raw.element_size(), out_ptr);
704 }
705}
706
707template <typename T>
Alex Gilday345ab182018-01-09 11:40:19 +0000708void AssetsLibrary::fill(T &&tensor, RawTensor raw) const
709{
710 for(size_t offset = 0; offset < raw.size(); offset += raw.element_size())
711 {
712 const Coordinates id = index2coord(raw.shape(), offset / raw.element_size());
713
714 const RawTensor::value_type *const raw_ptr = raw.data() + offset;
715 const auto out_ptr = static_cast<RawTensor::value_type *>(tensor(id));
716 std::copy_n(raw_ptr, raw.element_size(), out_ptr);
717 }
718}
719
720template <typename T>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100721void AssetsLibrary::fill_tensor_uniform(T &&tensor, std::random_device::result_type seed_offset) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100722{
723 switch(tensor.data_type())
724 {
725 case DataType::U8:
Anton Lokhmotovaf6204c2017-11-08 09:34:19 +0000726 case DataType::QASYMM8:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100727 {
Pablo Tello29cab362022-03-10 17:05:34 +0000728 std::uniform_int_distribution<unsigned int> distribution_u8(std::numeric_limits<uint8_t>::lowest(), std::numeric_limits<uint8_t>::max());
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100729 fill(tensor, distribution_u8, seed_offset);
730 break;
731 }
732 case DataType::S8:
Georgios Pinitas3d13af82019-06-04 13:04:16 +0100733 case DataType::QSYMM8:
Georgios Pinitas8217c8e2019-11-11 18:24:22 +0000734 case DataType::QSYMM8_PER_CHANNEL:
Georgios Pinitasdbdea0d2019-10-16 19:21:40 +0100735 case DataType::QASYMM8_SIGNED:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100736 {
Pablo Tello29cab362022-03-10 17:05:34 +0000737 std::uniform_int_distribution<int> distribution_s8(std::numeric_limits<int8_t>::lowest(), std::numeric_limits<int8_t>::max());
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100738 fill(tensor, distribution_s8, seed_offset);
739 break;
740 }
741 case DataType::U16:
742 {
743 std::uniform_int_distribution<uint16_t> distribution_u16(std::numeric_limits<uint16_t>::lowest(), std::numeric_limits<uint16_t>::max());
744 fill(tensor, distribution_u16, seed_offset);
745 break;
746 }
747 case DataType::S16:
Manuel Bottini3689fcd2019-06-14 17:18:12 +0100748 case DataType::QSYMM16:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100749 {
750 std::uniform_int_distribution<int16_t> distribution_s16(std::numeric_limits<int16_t>::lowest(), std::numeric_limits<int16_t>::max());
751 fill(tensor, distribution_s16, seed_offset);
752 break;
753 }
754 case DataType::U32:
755 {
756 std::uniform_int_distribution<uint32_t> distribution_u32(std::numeric_limits<uint32_t>::lowest(), std::numeric_limits<uint32_t>::max());
757 fill(tensor, distribution_u32, seed_offset);
758 break;
759 }
760 case DataType::S32:
761 {
762 std::uniform_int_distribution<int32_t> distribution_s32(std::numeric_limits<int32_t>::lowest(), std::numeric_limits<int32_t>::max());
763 fill(tensor, distribution_s32, seed_offset);
764 break;
765 }
766 case DataType::U64:
767 {
768 std::uniform_int_distribution<uint64_t> distribution_u64(std::numeric_limits<uint64_t>::lowest(), std::numeric_limits<uint64_t>::max());
769 fill(tensor, distribution_u64, seed_offset);
770 break;
771 }
772 case DataType::S64:
773 {
774 std::uniform_int_distribution<int64_t> distribution_s64(std::numeric_limits<int64_t>::lowest(), std::numeric_limits<int64_t>::max());
775 fill(tensor, distribution_s64, seed_offset);
776 break;
777 }
Georgios Pinitase8291ac2020-02-26 09:58:13 +0000778 case DataType::BFLOAT16:
779 {
780 // It doesn't make sense to check [-inf, inf], so hard code it to a big number
Giorgio Arena33b103b2021-01-08 10:37:15 +0000781 arm_compute::utils::uniform_real_distribution_16bit<bfloat16> distribution_bf16{ -1000.f, 1000.f };
Georgios Pinitase8291ac2020-02-26 09:58:13 +0000782 fill(tensor, distribution_bf16, seed_offset);
783 break;
784 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100785 case DataType::F16:
SiCong Li02dfb2c2017-07-27 17:59:20 +0100786 {
787 // It doesn't make sense to check [-inf, inf], so hard code it to a big number
Giorgio Arenaa8e2aeb2021-01-06 11:34:57 +0000788 arm_compute::utils::uniform_real_distribution_16bit<half> distribution_f16{ -100.f, 100.f };
SiCong Li02dfb2c2017-07-27 17:59:20 +0100789 fill(tensor, distribution_f16, seed_offset);
790 break;
791 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100792 case DataType::F32:
793 {
794 // It doesn't make sense to check [-inf, inf], so hard code it to a big number
795 std::uniform_real_distribution<float> distribution_f32(-1000.f, 1000.f);
796 fill(tensor, distribution_f32, seed_offset);
797 break;
798 }
799 case DataType::F64:
800 {
801 // It doesn't make sense to check [-inf, inf], so hard code it to a big number
802 std::uniform_real_distribution<double> distribution_f64(-1000.f, 1000.f);
803 fill(tensor, distribution_f64, seed_offset);
804 break;
805 }
806 case DataType::SIZET:
807 {
808 std::uniform_int_distribution<size_t> distribution_sizet(std::numeric_limits<size_t>::lowest(), std::numeric_limits<size_t>::max());
809 fill(tensor, distribution_sizet, seed_offset);
810 break;
811 }
812 default:
813 ARM_COMPUTE_ERROR("NOT SUPPORTED!");
814 }
815}
816
Georgios Pinitas587708b2018-12-31 15:43:52 +0000817template <typename T>
818void AssetsLibrary::fill_tensor_uniform_ranged(T &&tensor,
819 std::random_device::result_type seed_offset,
820 const std::vector<AssetsLibrary::RangePair> &excluded_range_pairs) const
821{
822 using namespace arm_compute::utils::random;
823
824 switch(tensor.data_type())
825 {
826 case DataType::U8:
827 case DataType::QASYMM8:
828 {
Pablo Tello29cab362022-03-10 17:05:34 +0000829 const auto converted_pairs = detail::convert_range_pair<uint32_t>(excluded_range_pairs);
830 RangedUniformDistribution<uint32_t> distribution_u8(std::numeric_limits<uint8_t>::lowest(),
831 std::numeric_limits<uint8_t>::max(),
832 converted_pairs);
Georgios Pinitas587708b2018-12-31 15:43:52 +0000833 fill(tensor, distribution_u8, seed_offset);
834 break;
835 }
836 case DataType::S8:
Georgios Pinitas3d13af82019-06-04 13:04:16 +0100837 case DataType::QSYMM8:
Georgios Pinitas587708b2018-12-31 15:43:52 +0000838 {
Pablo Tello29cab362022-03-10 17:05:34 +0000839 const auto converted_pairs = detail::convert_range_pair<int32_t>(excluded_range_pairs);
840 RangedUniformDistribution<int32_t> distribution_s8(std::numeric_limits<int8_t>::lowest(),
841 std::numeric_limits<int8_t>::max(),
842 converted_pairs);
Georgios Pinitas587708b2018-12-31 15:43:52 +0000843 fill(tensor, distribution_s8, seed_offset);
844 break;
845 }
846 case DataType::U16:
847 {
848 const auto converted_pairs = detail::convert_range_pair<uint16_t>(excluded_range_pairs);
849 RangedUniformDistribution<uint16_t> distribution_u16(std::numeric_limits<uint16_t>::lowest(),
850 std::numeric_limits<uint16_t>::max(),
851 converted_pairs);
852 fill(tensor, distribution_u16, seed_offset);
853 break;
854 }
855 case DataType::S16:
Manuel Bottini3689fcd2019-06-14 17:18:12 +0100856 case DataType::QSYMM16:
Georgios Pinitas587708b2018-12-31 15:43:52 +0000857 {
858 const auto converted_pairs = detail::convert_range_pair<int16_t>(excluded_range_pairs);
859 RangedUniformDistribution<int16_t> distribution_s16(std::numeric_limits<int16_t>::lowest(),
860 std::numeric_limits<int16_t>::max(),
861 converted_pairs);
862 fill(tensor, distribution_s16, seed_offset);
863 break;
864 }
865 case DataType::U32:
866 {
867 const auto converted_pairs = detail::convert_range_pair<uint32_t>(excluded_range_pairs);
868 RangedUniformDistribution<uint32_t> distribution_u32(std::numeric_limits<uint32_t>::lowest(),
869 std::numeric_limits<uint32_t>::max(),
870 converted_pairs);
871 fill(tensor, distribution_u32, seed_offset);
872 break;
873 }
874 case DataType::S32:
875 {
876 const auto converted_pairs = detail::convert_range_pair<int32_t>(excluded_range_pairs);
877 RangedUniformDistribution<int32_t> distribution_s32(std::numeric_limits<int32_t>::lowest(),
878 std::numeric_limits<int32_t>::max(),
879 converted_pairs);
880 fill(tensor, distribution_s32, seed_offset);
881 break;
882 }
Georgios Pinitase8291ac2020-02-26 09:58:13 +0000883 case DataType::BFLOAT16:
884 {
885 // It doesn't make sense to check [-inf, inf], so hard code it to a big number
Giorgio Arenaa8e2aeb2021-01-06 11:34:57 +0000886 const auto converted_pairs = detail::convert_range_pair<bfloat16>(excluded_range_pairs);
887 RangedUniformDistribution<bfloat16> distribution_bf16(bfloat16(-1000.f), bfloat16(1000.f), converted_pairs);
Georgios Pinitase8291ac2020-02-26 09:58:13 +0000888 fill(tensor, distribution_bf16, seed_offset);
889 break;
890 }
Georgios Pinitas587708b2018-12-31 15:43:52 +0000891 case DataType::F16:
892 {
893 // It doesn't make sense to check [-inf, inf], so hard code it to a big number
Giorgio Arena6aeb2172020-12-15 15:45:43 +0000894 const auto converted_pairs = detail::convert_range_pair<half>(excluded_range_pairs);
895 RangedUniformDistribution<half> distribution_f16(half(-100.f), half(100.f), converted_pairs);
Georgios Pinitas587708b2018-12-31 15:43:52 +0000896 fill(tensor, distribution_f16, seed_offset);
897 break;
898 }
899 case DataType::F32:
900 {
901 // It doesn't make sense to check [-inf, inf], so hard code it to a big number
902 const auto converted_pairs = detail::convert_range_pair<float>(excluded_range_pairs);
903 RangedUniformDistribution<float> distribution_f32(-1000.f, 1000.f, converted_pairs);
904 fill(tensor, distribution_f32, seed_offset);
905 break;
906 }
907 default:
908 ARM_COMPUTE_ERROR("NOT SUPPORTED!");
909 }
910}
911
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100912template <typename T, typename D>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100913void 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 +0100914{
915 switch(tensor.data_type())
916 {
917 case DataType::U8:
Anton Lokhmotovaf6204c2017-11-08 09:34:19 +0000918 case DataType::QASYMM8:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100919 {
920 ARM_COMPUTE_ERROR_ON(!(std::is_same<uint8_t, D>::value));
Pablo Tello29cab362022-03-10 17:05:34 +0000921 std::uniform_int_distribution<uint32_t> distribution_u8(low, high);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100922 fill(tensor, distribution_u8, seed_offset);
923 break;
924 }
925 case DataType::S8:
Georgios Pinitas3d13af82019-06-04 13:04:16 +0100926 case DataType::QSYMM8:
Sang-Hoon Parkd8176472019-12-04 09:46:28 +0000927 case DataType::QASYMM8_SIGNED:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100928 {
929 ARM_COMPUTE_ERROR_ON(!(std::is_same<int8_t, D>::value));
Pablo Tello29cab362022-03-10 17:05:34 +0000930 std::uniform_int_distribution<int32_t> distribution_s8(low, high);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100931 fill(tensor, distribution_s8, seed_offset);
932 break;
933 }
934 case DataType::U16:
935 {
936 ARM_COMPUTE_ERROR_ON(!(std::is_same<uint16_t, D>::value));
937 std::uniform_int_distribution<uint16_t> distribution_u16(low, high);
938 fill(tensor, distribution_u16, seed_offset);
939 break;
940 }
941 case DataType::S16:
Manuel Bottini3689fcd2019-06-14 17:18:12 +0100942 case DataType::QSYMM16:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100943 {
944 ARM_COMPUTE_ERROR_ON(!(std::is_same<int16_t, D>::value));
945 std::uniform_int_distribution<int16_t> distribution_s16(low, high);
946 fill(tensor, distribution_s16, seed_offset);
947 break;
948 }
949 case DataType::U32:
950 {
951 ARM_COMPUTE_ERROR_ON(!(std::is_same<uint32_t, D>::value));
952 std::uniform_int_distribution<uint32_t> distribution_u32(low, high);
953 fill(tensor, distribution_u32, seed_offset);
954 break;
955 }
956 case DataType::S32:
957 {
958 ARM_COMPUTE_ERROR_ON(!(std::is_same<int32_t, D>::value));
959 std::uniform_int_distribution<int32_t> distribution_s32(low, high);
960 fill(tensor, distribution_s32, seed_offset);
961 break;
962 }
963 case DataType::U64:
964 {
965 ARM_COMPUTE_ERROR_ON(!(std::is_same<uint64_t, D>::value));
966 std::uniform_int_distribution<uint64_t> distribution_u64(low, high);
967 fill(tensor, distribution_u64, seed_offset);
968 break;
969 }
970 case DataType::S64:
971 {
972 ARM_COMPUTE_ERROR_ON(!(std::is_same<int64_t, D>::value));
973 std::uniform_int_distribution<int64_t> distribution_s64(low, high);
974 fill(tensor, distribution_s64, seed_offset);
975 break;
976 }
Georgios Pinitase8291ac2020-02-26 09:58:13 +0000977 case DataType::BFLOAT16:
978 {
Giorgio Arena33b103b2021-01-08 10:37:15 +0000979 arm_compute::utils::uniform_real_distribution_16bit<bfloat16> distribution_bf16{ float(low), float(high) };
Georgios Pinitase8291ac2020-02-26 09:58:13 +0000980 fill(tensor, distribution_bf16, seed_offset);
981 break;
982 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100983 case DataType::F16:
984 {
Giorgio Arenaa8e2aeb2021-01-06 11:34:57 +0000985 arm_compute::utils::uniform_real_distribution_16bit<half> distribution_f16{ float(low), float(high) };
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100986 fill(tensor, distribution_f16, seed_offset);
987 break;
988 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100989 case DataType::F32:
990 {
991 ARM_COMPUTE_ERROR_ON(!(std::is_same<float, D>::value));
992 std::uniform_real_distribution<float> distribution_f32(low, high);
993 fill(tensor, distribution_f32, seed_offset);
994 break;
995 }
996 case DataType::F64:
997 {
998 ARM_COMPUTE_ERROR_ON(!(std::is_same<double, D>::value));
999 std::uniform_real_distribution<double> distribution_f64(low, high);
1000 fill(tensor, distribution_f64, seed_offset);
1001 break;
1002 }
1003 case DataType::SIZET:
1004 {
1005 ARM_COMPUTE_ERROR_ON(!(std::is_same<size_t, D>::value));
1006 std::uniform_int_distribution<size_t> distribution_sizet(low, high);
1007 fill(tensor, distribution_sizet, seed_offset);
1008 break;
1009 }
1010 default:
1011 ARM_COMPUTE_ERROR("NOT SUPPORTED!");
1012 }
1013}
1014
1015template <typename T>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +01001016void AssetsLibrary::fill_layer_data(T &&tensor, std::string name) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001017{
1018#ifdef _WIN32
1019 const std::string path_separator("\\");
Anthony Barbierac69aa12017-07-03 17:39:37 +01001020#else /* _WIN32 */
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001021 const std::string path_separator("/");
Anthony Barbierac69aa12017-07-03 17:39:37 +01001022#endif /* _WIN32 */
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001023 const std::string path = _library_path + path_separator + name;
1024
1025 // Open file
SiCong Li86b53332017-08-23 11:02:43 +01001026 std::ifstream stream(path, std::ios::in | std::ios::binary);
Anthony Barbierf6705ec2017-09-28 12:01:10 +01001027 if(!stream.good())
1028 {
1029 throw framework::FileNotFound("Could not load npy file: " + path);
1030 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001031
Matthew Bentham470bc1e2020-03-09 10:55:40 +00001032 validate_npy_header(stream, tensor.data_type(), tensor.shape());
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001033
SiCong Li86b53332017-08-23 11:02:43 +01001034 // Read data
1035 if(tensor.padding().empty())
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001036 {
SiCong Li86b53332017-08-23 11:02:43 +01001037 // If tensor has no padding read directly from stream.
1038 stream.read(reinterpret_cast<char *>(tensor.data()), tensor.size());
1039 }
1040 else
1041 {
1042 // If tensor has padding accessing tensor elements through execution window.
1043 Window window;
1044 window.use_tensor_dimensions(tensor.shape());
1045
SiCong Li86b53332017-08-23 11:02:43 +01001046 execute_window_loop(window, [&](const Coordinates & id)
1047 {
1048 stream.read(reinterpret_cast<char *>(tensor(id)), tensor.element_size());
1049 });
1050 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001051}
Michele Di Giorgio4d336302018-03-02 09:43:54 +00001052
1053template <typename T, typename D>
1054void AssetsLibrary::fill_tensor_value(T &&tensor, D value) const
1055{
1056 fill_tensor_uniform(tensor, 0, value, value);
1057}
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001058} // namespace test
1059} // namespace arm_compute
Michalis Spyrouf4643372019-11-29 16:17:13 +00001060#endif /* ARM_COMPUTE_TEST_TENSOR_LIBRARY_H */