blob: fc89d970733053285b6facb7e2d6f23d14733b66 [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
Michalis Spyrou780db4e2017-11-23 09:49:51 +00002 * Copyright (c) 2016, 2017, 2018 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 */
24#ifndef __ARM_COMPUTE_UTILS_H__
25#define __ARM_COMPUTE_UTILS_H__
26
27#include "arm_compute/core/Error.h"
Michel Iwaniec5dfeae62017-11-29 10:48:23 +000028#include "arm_compute/core/Rounding.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010029#include "arm_compute/core/Types.h"
30
31#include <algorithm>
32#include <cstdint>
33#include <cstdlib>
34#include <numeric>
35#include <sstream>
36#include <string>
37#include <type_traits>
38#include <utility>
steniu017ce53c62017-09-29 14:55:00 +010039#include <vector>
Anthony Barbier6ff3b192017-09-04 18:44:23 +010040
41namespace arm_compute
42{
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +000043/** Calculate the rounded up quotient of val / m. */
44template <typename S, typename T>
45constexpr auto DIV_CEIL(S val, T m) -> decltype((val + m - 1) / m)
46{
47 return (val + m - 1) / m;
48}
49
Anthony Barbier6ff3b192017-09-04 18:44:23 +010050/** Computes the smallest number larger or equal to value that is a multiple of divisor. */
51template <typename S, typename T>
52inline auto ceil_to_multiple(S value, T divisor) -> decltype(((value + divisor - 1) / divisor) * divisor)
53{
54 ARM_COMPUTE_ERROR_ON(value < 0 || divisor <= 0);
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +000055 return DIV_CEIL(value, divisor) * divisor;
Anthony Barbier6ff3b192017-09-04 18:44:23 +010056}
57
58/** Computes the largest number smaller or equal to value that is a multiple of divisor. */
59template <typename S, typename T>
60inline auto floor_to_multiple(S value, T divisor) -> decltype((value / divisor) * divisor)
61{
62 ARM_COMPUTE_ERROR_ON(value < 0 || divisor <= 0);
63 return (value / divisor) * divisor;
64}
65
Anthony Barbier6ff3b192017-09-04 18:44:23 +010066/** Returns the arm_compute library build information
67 *
68 * Contains the version number and the build options used to build the library
69 *
70 * @return The arm_compute library build information
71 */
72std::string build_information();
73
74/** Load an entire file in memory
75 *
76 * @param[in] filename Name of the file to read.
77 * @param[in] binary Is it a binary file ?
78 *
79 * @return The content of the file.
80 */
81std::string read_file(const std::string &filename, bool binary);
82
Anthony Barbier6ff3b192017-09-04 18:44:23 +010083/** The size in bytes of the data type
84 *
85 * @param[in] data_type Input data type
86 *
87 * @return The size in bytes of the data type
88 */
89inline size_t data_size_from_type(DataType data_type)
90{
91 switch(data_type)
92 {
93 case DataType::U8:
94 case DataType::S8:
95 case DataType::QS8:
Michel Iwaniec00633802017-10-12 14:14:15 +010096 case DataType::QASYMM8:
Anthony Barbier6ff3b192017-09-04 18:44:23 +010097 return 1;
98 case DataType::U16:
99 case DataType::S16:
100 case DataType::F16:
101 case DataType::QS16:
102 return 2;
103 case DataType::F32:
104 case DataType::U32:
105 case DataType::S32:
Pablo Tellof87cc7f2017-07-26 10:28:40 +0100106 case DataType::QS32:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100107 return 4;
108 case DataType::F64:
109 case DataType::U64:
110 case DataType::S64:
111 return 8;
112 case DataType::SIZET:
113 return sizeof(size_t);
114 default:
115 ARM_COMPUTE_ERROR("Invalid data type");
116 return 0;
117 }
118}
119
120/** The size in bytes of the pixel format
121 *
122 * @param[in] format Input format
123 *
124 * @return The size in bytes of the pixel format
125 */
126inline size_t pixel_size_from_format(Format format)
127{
128 switch(format)
129 {
130 case Format::U8:
131 return 1;
132 case Format::U16:
133 case Format::S16:
134 case Format::F16:
135 case Format::UV88:
136 case Format::YUYV422:
137 case Format::UYVY422:
138 return 2;
139 case Format::RGB888:
140 return 3;
141 case Format::RGBA8888:
142 return 4;
143 case Format::U32:
144 case Format::S32:
145 case Format::F32:
146 return 4;
147 //Doesn't make sense for planar formats:
148 case Format::NV12:
149 case Format::NV21:
150 case Format::IYUV:
151 case Format::YUV444:
152 default:
153 ARM_COMPUTE_ERROR("Undefined pixel size for given format");
154 return 0;
155 }
156}
157
158/** The size in bytes of the data type
159 *
160 * @param[in] dt Input data type
161 *
162 * @return The size in bytes of the data type
163 */
164inline size_t element_size_from_data_type(DataType dt)
165{
166 switch(dt)
167 {
168 case DataType::S8:
169 case DataType::U8:
170 case DataType::QS8:
Michel Iwaniec00633802017-10-12 14:14:15 +0100171 case DataType::QASYMM8:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100172 return 1;
173 case DataType::U16:
174 case DataType::S16:
175 case DataType::QS16:
176 case DataType::F16:
177 return 2;
178 case DataType::U32:
179 case DataType::S32:
180 case DataType::F32:
Pablo Tellof87cc7f2017-07-26 10:28:40 +0100181 case DataType::QS32:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100182 return 4;
183 default:
184 ARM_COMPUTE_ERROR("Undefined element size for given data type");
185 return 0;
186 }
187}
188
189/** Return the data type used by a given single-planar pixel format
190 *
191 * @param[in] format Input format
192 *
193 * @return The size in bytes of the pixel format
194 */
195inline DataType data_type_from_format(Format format)
196{
197 switch(format)
198 {
199 case Format::U8:
200 case Format::UV88:
201 case Format::RGB888:
202 case Format::RGBA8888:
203 case Format::YUYV422:
204 case Format::UYVY422:
205 return DataType::U8;
206 case Format::U16:
207 return DataType::U16;
208 case Format::S16:
209 return DataType::S16;
210 case Format::U32:
211 return DataType::U32;
212 case Format::S32:
213 return DataType::S32;
214 case Format::F16:
215 return DataType::F16;
216 case Format::F32:
217 return DataType::F32;
218 //Doesn't make sense for planar formats:
219 case Format::NV12:
220 case Format::NV21:
221 case Format::IYUV:
222 case Format::YUV444:
223 default:
224 ARM_COMPUTE_ERROR("Not supported data_type for given format");
225 return DataType::UNKNOWN;
226 }
227}
228
229/** Return the plane index of a given channel given an input format.
230 *
231 * @param[in] format Input format
232 * @param[in] channel Input channel
233 *
234 * @return The plane index of the specific channel of the specific format
235 */
236inline int plane_idx_from_channel(Format format, Channel channel)
237{
238 switch(format)
239 {
240 case Format::NV12:
241 case Format::NV21:
242 {
243 switch(channel)
244 {
245 case Channel::Y:
246 return 0;
247 case Channel::U:
248 case Channel::V:
249 return 1;
250 default:
251 ARM_COMPUTE_ERROR("Not supported channel");
252 return 0;
253 }
254 }
255 case Format::IYUV:
256 case Format::YUV444:
257 {
258 switch(channel)
259 {
260 case Channel::Y:
261 return 0;
262 case Channel::U:
263 return 1;
264 case Channel::V:
265 return 2;
266 default:
267 ARM_COMPUTE_ERROR("Not supported channel");
268 return 0;
269 }
270 }
271 default:
272 ARM_COMPUTE_ERROR("Not supported format");
273 return 0;
274 }
275}
276
277/** Return the number of planes for a given format
278 *
279 * @param[in] format Input format
280 *
281 * @return The number of planes for a given image format.
282 */
283inline size_t num_planes_from_format(Format format)
284{
285 switch(format)
286 {
287 case Format::U8:
288 case Format::S16:
289 case Format::U16:
290 case Format::S32:
291 case Format::U32:
292 case Format::F16:
293 case Format::F32:
294 case Format::RGB888:
295 case Format::RGBA8888:
296 case Format::YUYV422:
297 case Format::UYVY422:
298 return 1;
299 case Format::NV12:
300 case Format::NV21:
301 return 2;
302 case Format::IYUV:
303 case Format::YUV444:
304 return 3;
305 default:
306 ARM_COMPUTE_ERROR("Not supported format");
307 return 0;
308 }
309}
310
311/** Return the number of channels for a given single-planar pixel format
312 *
313 * @param[in] format Input format
314 *
315 * @return The number of channels for a given image format.
316 */
317inline size_t num_channels_from_format(Format format)
318{
319 switch(format)
320 {
321 case Format::U8:
322 case Format::U16:
323 case Format::S16:
324 case Format::U32:
325 case Format::S32:
326 case Format::F16:
327 case Format::F32:
328 return 1;
329 // Because the U and V channels are subsampled
330 // these formats appear like having only 2 channels:
331 case Format::YUYV422:
332 case Format::UYVY422:
333 return 2;
334 case Format::UV88:
335 return 2;
336 case Format::RGB888:
337 return 3;
338 case Format::RGBA8888:
339 return 4;
340 //Doesn't make sense for planar formats:
341 case Format::NV12:
342 case Format::NV21:
343 case Format::IYUV:
344 case Format::YUV444:
345 default:
346 return 0;
347 }
348}
349
Chunosovd621bca2017-11-03 17:33:15 +0700350/** Return the promoted data type of a given data type.
351 *
352 * @note If promoted data type is not supported an error will be thrown
353 *
354 * @param[in] dt Data type to get the promoted type of.
355 *
356 * @return Promoted data type
357 */
358inline DataType get_promoted_data_type(DataType dt)
359{
360 switch(dt)
361 {
362 case DataType::U8:
363 return DataType::U16;
364 case DataType::S8:
365 return DataType::S16;
366 case DataType::QS8:
367 return DataType::QS16;
368 case DataType::U16:
369 return DataType::U32;
370 case DataType::S16:
371 return DataType::S32;
372 case DataType::QS16:
373 return DataType::QS32;
374 case DataType::QASYMM8:
375 case DataType::F16:
376 case DataType::U32:
377 case DataType::S32:
378 case DataType::F32:
379 case DataType::QS32:
380 ARM_COMPUTE_ERROR("Unsupported data type promotions!");
381 default:
382 ARM_COMPUTE_ERROR("Undefined data type!");
383 }
384 return DataType::UNKNOWN;
385}
386
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100387/** Separate a 2D convolution into two 1D convolutions
Anthony Barbierf202e502017-11-23 18:02:04 +0000388 *
389 * @param[in] conv 2D convolution
390 * @param[out] conv_col 1D vertical convolution
391 * @param[out] conv_row 1D horizontal convolution
392 * @param[in] size Size of the 2D convolution
393 *
394 * @return true if the separation was successful
395 */
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100396inline bool separate_matrix(const int16_t *conv, int16_t *conv_col, int16_t *conv_row, uint8_t size)
397{
398 int32_t min_col = -1;
399 int16_t min_col_val = -1;
400
401 for(int32_t i = 0; i < size; ++i)
402 {
403 if(conv[i] != 0 && (min_col < 0 || abs(min_col_val) > abs(conv[i])))
404 {
405 min_col = i;
406 min_col_val = conv[i];
407 }
408 }
409
410 if(min_col < 0)
411 {
412 return false;
413 }
414
415 for(uint32_t j = 0; j < size; ++j)
416 {
417 conv_col[j] = conv[min_col + j * size];
418 }
419
420 for(uint32_t i = 0; i < size; i++)
421 {
422 if(static_cast<int>(i) == min_col)
423 {
424 conv_row[i] = 1;
425 }
426 else
427 {
428 int16_t coeff = conv[i] / conv[min_col];
429
430 for(uint32_t j = 1; j < size; ++j)
431 {
432 if(conv[i + j * size] != (conv_col[j] * coeff))
433 {
434 return false;
435 }
436 }
437
438 conv_row[i] = coeff;
439 }
440 }
441
442 return true;
443}
444
445/** Calculate the scale of the given square matrix
446 *
447 * The scale is the absolute value of the sum of all the coefficients in the matrix.
448 *
449 * @note If the coefficients add up to 0 then the scale is set to 1.
450 *
451 * @param[in] matrix Matrix coefficients
452 * @param[in] matrix_size Number of elements per side of the square matrix. (Number of coefficients = matrix_size * matrix_size).
453 *
454 * @return The absolute value of the sum of the coefficients if they don't add up to 0, otherwise 1.
455 */
456inline uint32_t calculate_matrix_scale(const int16_t *matrix, unsigned int matrix_size)
457{
458 const size_t size = matrix_size * matrix_size;
459
460 return std::max(1, std::abs(std::accumulate(matrix, matrix + size, 0)));
461}
462
steniu017ce53c62017-09-29 14:55:00 +0100463/** Calculate the output shapes of the depth concatenate function.
464 *
465 * @param[in] inputs_vector The vector that stores all the pointers to input.
466 *
467 * @return the output shape
468 */
469template <typename T>
470TensorShape calculate_depth_concatenate_shape(const std::vector<T *> &inputs_vector)
471{
472 TensorShape out_shape = inputs_vector[0]->info()->tensor_shape();
473
474 size_t max_x = 0;
475 size_t max_y = 0;
476 size_t depth = 0;
477
478 for(const auto &tensor : inputs_vector)
479 {
480 ARM_COMPUTE_ERROR_ON(tensor == nullptr);
481 const TensorShape shape = tensor->info()->tensor_shape();
482 max_x = std::max(shape.x(), max_x);
483 max_y = std::max(shape.y(), max_y);
484 depth += shape.z();
485 }
486
487 out_shape.set(0, max_x);
488 out_shape.set(1, max_y);
489 out_shape.set(2, depth);
490
491 return out_shape;
492}
493
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100494/** Calculate accurary required by the horizontal and vertical convolution computations
495 *
496 * @param[in] conv_col Pointer to the vertical vector of the separated convolution filter
497 * @param[in] conv_row Pointer to the horizontal vector of the convolution filter
498 * @param[in] size Number of elements per vector of the separated matrix
499 *
500 * @return The return type is a pair. The first element of the pair is the biggest data type needed for the first stage. The second
501 * element of the pair is the biggest data type needed for the second stage.
502 */
503inline std::pair<DataType, DataType> data_type_for_convolution(const int16_t *conv_col, const int16_t *conv_row, size_t size)
504{
505 DataType first_stage = DataType::UNKNOWN;
506 DataType second_stage = DataType::UNKNOWN;
507
508 auto gez = [](const int16_t &v)
509 {
510 return v >= 0;
511 };
512
513 auto accu_neg = [](const int &first, const int &second)
514 {
515 return first + (second < 0 ? second : 0);
516 };
517
518 auto accu_pos = [](const int &first, const int &second)
519 {
520 return first + (second > 0 ? second : 0);
521 };
522
523 const bool only_positive_coefficients = std::all_of(conv_row, conv_row + size, gez) && std::all_of(conv_col, conv_col + size, gez);
524
525 if(only_positive_coefficients)
526 {
527 const int max_row_value = std::accumulate(conv_row, conv_row + size, 0) * UINT8_MAX;
528 const int max_value = std::accumulate(conv_col, conv_col + size, 0) * max_row_value;
529
530 first_stage = (max_row_value <= UINT16_MAX) ? DataType::U16 : DataType::S32;
531
532 second_stage = (max_value <= UINT16_MAX) ? DataType::U16 : DataType::S32;
533 }
534 else
535 {
536 const int min_row_value = std::accumulate(conv_row, conv_row + size, 0, accu_neg) * UINT8_MAX;
537 const int max_row_value = std::accumulate(conv_row, conv_row + size, 0, accu_pos) * UINT8_MAX;
538 const int neg_coeffs_sum = std::accumulate(conv_col, conv_col + size, 0, accu_neg);
539 const int pos_coeffs_sum = std::accumulate(conv_col, conv_col + size, 0, accu_pos);
540 const int min_value = neg_coeffs_sum * max_row_value + pos_coeffs_sum * min_row_value;
541 const int max_value = neg_coeffs_sum * min_row_value + pos_coeffs_sum * max_row_value;
542
543 first_stage = ((INT16_MIN <= min_row_value) && (max_row_value <= INT16_MAX)) ? DataType::S16 : DataType::S32;
544
545 second_stage = ((INT16_MIN <= min_value) && (max_value <= INT16_MAX)) ? DataType::S16 : DataType::S32;
546 }
547
548 return std::make_pair(first_stage, second_stage);
549}
550
551/** Calculate the accuracy required by the squared convolution calculation.
552 *
553 *
554 * @param[in] conv Pointer to the squared convolution matrix
555 * @param[in] size The total size of the convolution matrix
556 *
557 * @return The return is the biggest data type needed to do the convolution
558 */
559inline DataType data_type_for_convolution_matrix(const int16_t *conv, size_t size)
560{
561 auto gez = [](const int16_t v)
562 {
563 return v >= 0;
564 };
565
566 const bool only_positive_coefficients = std::all_of(conv, conv + size, gez);
567
568 if(only_positive_coefficients)
569 {
570 const int max_conv_value = std::accumulate(conv, conv + size, 0) * UINT8_MAX;
571 if(max_conv_value <= UINT16_MAX)
572 {
573 return DataType::U16;
574 }
575 else
576 {
577 return DataType::S32;
578 }
579 }
580 else
581 {
582 const int min_value = std::accumulate(conv, conv + size, 0, [](int a, int b)
583 {
584 return b < 0 ? a + b : a;
585 })
586 * UINT8_MAX;
587
588 const int max_value = std::accumulate(conv, conv + size, 0, [](int a, int b)
589 {
590 return b > 0 ? a + b : a;
591 })
592 * UINT8_MAX;
593
594 if((INT16_MIN <= min_value) && (INT16_MAX >= max_value))
595 {
596 return DataType::S16;
597 }
598 else
599 {
600 return DataType::S32;
601 }
602 }
603}
604
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100605/** Returns expected shape for the deconvolution output tensor.
606 *
607 * @param[in] out_dims widht and height of the output tensor, these values can be obtained with the function deconvolution_output_dimensions.
608 * @param[in] input Shape of the input tensor.
609 * @param[in] weights Shape of the weights tensor.
610 *
611 * @return Deconvolution output tensor shape.
612 */
613TensorShape deconvolution_output_shape(const std::pair<unsigned int, unsigned int> &out_dims, TensorShape input, TensorShape weights);
614
615/** Returns expected width and height of the deconvolution's output tensor.
616 *
Michalis Spyrou780db4e2017-11-23 09:49:51 +0000617 * @param[in] in_width Width of input tensor (Number of columns)
618 * @param[in] in_height Height of input tensor (Number of rows)
619 * @param[in] kernel_width Kernel width.
620 * @param[in] kernel_height Kernel height.
621 * @param[in] padx X axis padding.
622 * @param[in] pady Y axis padding.
623 * @param[in] inner_border_right The number of zeros added to right edge of the input.
624 * @param[in] inner_border_top The number of zeros added to top edge of the input.
625 * @param[in] stride_x X axis input stride.
626 * @param[in] stride_y Y axis input stride.
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100627 *
628 * @return A pair with the new width in the first position and the new height in the second.
629 */
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100630const std::pair<unsigned int, unsigned int> deconvolution_output_dimensions(unsigned int in_width, unsigned int in_height,
631 unsigned int kernel_width, unsigned int kernel_height,
Michalis Spyrou780db4e2017-11-23 09:49:51 +0000632 unsigned int padx, unsigned int pady, unsigned int inner_border_right, unsigned int inner_border_top,
633 unsigned int stride_x, unsigned int stride_y);
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100634
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100635/** Returns expected width and height of output scaled tensor depending on dimensions rounding mode.
636 *
Gian Marco Iodice4e288692017-06-27 11:41:59 +0100637 * @param[in] width Width of input tensor (Number of columns)
638 * @param[in] height Height of input tensor (Number of rows)
639 * @param[in] kernel_width Kernel width.
640 * @param[in] kernel_height Kernel height.
641 * @param[in] pad_stride_info Pad and stride information.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100642 *
643 * @return A pair with the new width in the first position and the new height in the second.
644 */
Gian Marco Iodice4e288692017-06-27 11:41:59 +0100645const std::pair<unsigned int, unsigned int> scaled_dimensions(unsigned int width, unsigned int height,
646 unsigned int kernel_width, unsigned int kernel_height,
647 const PadStrideInfo &pad_stride_info);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100648
649/** Convert a tensor format into a string.
650 *
651 * @param[in] format @ref Format to be translated to string.
652 *
653 * @return The string describing the format.
654 */
655const std::string &string_from_format(Format format);
656
657/** Convert a channel identity into a string.
658 *
659 * @param[in] channel @ref Channel to be translated to string.
660 *
661 * @return The string describing the channel.
662 */
663const std::string &string_from_channel(Channel channel);
664
665/** Convert a data type identity into a string.
666 *
667 * @param[in] dt @ref DataType to be translated to string.
668 *
669 * @return The string describing the data type.
670 */
671const std::string &string_from_data_type(DataType dt);
672/** Convert a matrix pattern into a string.
673 *
674 * @param[in] pattern @ref MatrixPattern to be translated to string.
675 *
676 * @return The string describing the matrix pattern.
677 */
678const std::string &string_from_matrix_pattern(MatrixPattern pattern);
679/** Translates a given activation function to a string.
680 *
681 * @param[in] act @ref ActivationLayerInfo::ActivationFunction to be translated to string.
682 *
683 * @return The string describing the activation function.
684 */
685const std::string &string_from_activation_func(ActivationLayerInfo::ActivationFunction act);
686/** Translates a given non linear function to a string.
687 *
688 * @param[in] function @ref NonLinearFilterFunction to be translated to string.
689 *
690 * @return The string describing the non linear function.
691 */
692const std::string &string_from_non_linear_filter_function(NonLinearFilterFunction function);
693/** Translates a given interpolation policy to a string.
694 *
695 * @param[in] policy @ref InterpolationPolicy to be translated to string.
696 *
697 * @return The string describing the interpolation policy.
698 */
699const std::string &string_from_interpolation_policy(InterpolationPolicy policy);
700/** Translates a given border mode policy to a string.
701 *
702 * @param[in] border_mode @ref BorderMode to be translated to string.
703 *
704 * @return The string describing the border mode.
705 */
706const std::string &string_from_border_mode(BorderMode border_mode);
707/** Translates a given normalization type to a string.
708 *
709 * @param[in] type @ref NormType to be translated to string.
710 *
711 * @return The string describing the normalization type.
712 */
713const std::string &string_from_norm_type(NormType type);
Georgios Pinitascdf51452017-08-31 14:21:36 +0100714/** Translates a given pooling type to a string.
715 *
716 * @param[in] type @ref PoolingType to be translated to string.
717 *
718 * @return The string describing the pooling type.
719 */
720const std::string &string_from_pooling_type(PoolingType type);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100721/** Lower a given string.
722 *
723 * @param[in] val Given string to lower.
724 *
725 * @return The lowered string
726 */
727std::string lower_string(const std::string &val);
728
729/** Check if a given data type is of floating point type
730 *
731 * @param[in] dt Input data type.
732 *
733 * @return True if data type is of floating point type, else false.
734 */
735inline bool is_data_type_float(DataType dt)
736{
737 switch(dt)
738 {
739 case DataType::F16:
740 case DataType::F32:
741 return true;
742 default:
743 return false;
744 }
745}
746
Georgios Pinitas05078ec2017-11-02 13:06:59 +0000747/** Check if a given data type is of quantized type
748 *
749 * @note Quantized is considered a super-set of fixed-point and asymmetric data types.
750 *
751 * @param[in] dt Input data type.
752 *
753 * @return True if data type is of quantized type, else false.
754 */
755inline bool is_data_type_quantized(DataType dt)
756{
757 switch(dt)
758 {
759 case DataType::QS8:
760 case DataType::QASYMM8:
761 case DataType::QS16:
762 case DataType::QS32:
763 return true;
764 default:
765 return false;
766 }
767}
768
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100769/** Check if a given data type is of fixed point type
770 *
771 * @param[in] dt Input data type.
772 *
773 * @return True if data type is of fixed point type, else false.
774 */
775inline bool is_data_type_fixed_point(DataType dt)
776{
777 switch(dt)
778 {
779 case DataType::QS8:
780 case DataType::QS16:
Pablo Tellof87cc7f2017-07-26 10:28:40 +0100781 case DataType::QS32:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100782 return true;
783 default:
784 return false;
785 }
786}
787
Georgios Pinitas05078ec2017-11-02 13:06:59 +0000788/** Check if a given data type is of asymmetric quantized type
789 *
790 * @param[in] dt Input data type.
791 *
792 * @return True if data type is of symmetric quantized type, else false.
793 */
Anton Lokhmotovaf6204c2017-11-08 09:34:19 +0000794inline bool is_data_type_quantized_asymmetric(DataType dt)
Georgios Pinitas05078ec2017-11-02 13:06:59 +0000795{
796 switch(dt)
797 {
798 case DataType::QASYMM8:
799 return true;
800 default:
801 return false;
802 }
803}
804
Georgios Pinitas89010962017-08-04 14:58:27 +0100805/** Create a string with the float in full precision.
806 *
807 * @param val Floating point value
808 *
809 * @return String with the floating point value.
810 */
811inline std::string float_to_string_with_full_precision(float val)
812{
813 std::stringstream ss;
814 ss.precision(std::numeric_limits<float>::digits10 + 1);
815 ss << val;
816 return ss.str();
817}
818
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100819/** Print consecutive elements to an output stream.
820 *
821 * @param[out] s Output stream to print the elements to.
822 * @param[in] ptr Pointer to print the elements from.
823 * @param[in] n Number of elements to print.
824 * @param[in] stream_width (Optional) Width of the stream. If set to 0 the element's width is used. Defaults to 0.
825 * @param[in] element_delim (Optional) Delimeter among the consecutive elements. Defaults to space delimeter
826 */
827template <typename T>
828void print_consecutive_elements_impl(std::ostream &s, const T *ptr, unsigned int n, int stream_width = 0, const std::string &element_delim = " ")
829{
830 using print_type = typename std::conditional<std::is_floating_point<T>::value, T, int>::type;
831
832 for(unsigned int i = 0; i < n; ++i)
833 {
834 // Set stream width as it is not a "sticky" stream manipulator
835 if(stream_width != 0)
836 {
837 s.width(stream_width);
838 }
Anthony Barbier7068f992017-10-26 15:23:08 +0100839
840 if(std::is_same<typename std::decay<T>::type, half>::value)
841 {
842 // We use T instead of print_type here is because the std::is_floating_point<half> returns false and then the print_type becomes int.
843 s << std::right << static_cast<T>(ptr[i]) << element_delim;
844 }
845 else
846 {
847 s << std::right << static_cast<print_type>(ptr[i]) << element_delim;
848 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100849 }
850}
851
852/** Identify the maximum width of n consecutive elements.
853 *
854 * @param[in] s The output stream which will be used to print the elements. Used to extract the stream format.
855 * @param[in] ptr Pointer to the elements.
856 * @param[in] n Number of elements.
857 *
858 * @return The maximum width of the elements.
859 */
860template <typename T>
861int max_consecutive_elements_display_width_impl(std::ostream &s, const T *ptr, unsigned int n)
862{
863 using print_type = typename std::conditional<std::is_floating_point<T>::value, T, int>::type;
864
865 int max_width = -1;
866 for(unsigned int i = 0; i < n; ++i)
867 {
868 std::stringstream ss;
869 ss.copyfmt(s);
Anthony Barbier7068f992017-10-26 15:23:08 +0100870
871 if(std::is_same<typename std::decay<T>::type, half>::value)
872 {
873 // We use T instead of print_type here is because the std::is_floating_point<half> returns false and then the print_type becomes int.
874 ss << static_cast<T>(ptr[i]);
875 }
876 else
877 {
878 ss << static_cast<print_type>(ptr[i]);
879 }
880
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100881 max_width = std::max<int>(max_width, ss.str().size());
882 }
883 return max_width;
884}
885
886/** Print consecutive elements to an output stream.
887 *
888 * @param[out] s Output stream to print the elements to.
889 * @param[in] dt Data type of the elements
890 * @param[in] ptr Pointer to print the elements from.
891 * @param[in] n Number of elements to print.
892 * @param[in] stream_width (Optional) Width of the stream. If set to 0 the element's width is used. Defaults to 0.
893 * @param[in] element_delim (Optional) Delimeter among the consecutive elements. Defaults to space delimeter
894 */
895void print_consecutive_elements(std::ostream &s, DataType dt, const uint8_t *ptr, unsigned int n, int stream_width, const std::string &element_delim = " ");
896
897/** Identify the maximum width of n consecutive elements.
898 *
899 * @param[in] s Output stream to print the elements to.
900 * @param[in] dt Data type of the elements
901 * @param[in] ptr Pointer to print the elements from.
902 * @param[in] n Number of elements to print.
903 *
904 * @return The maximum width of the elements.
905 */
906int max_consecutive_elements_display_width(std::ostream &s, DataType dt, const uint8_t *ptr, unsigned int n);
907}
908#endif /*__ARM_COMPUTE_UTILS_H__ */