blob: f78add13f91786ef341bf694b5d62858409f2d8f [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
2 * Copyright (c) 2016, 2017 ARM Limited.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24#ifndef __ARM_COMPUTE_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{
43/** Computes the smallest number larger or equal to value that is a multiple of divisor. */
44template <typename S, typename T>
45inline auto ceil_to_multiple(S value, T divisor) -> decltype(((value + divisor - 1) / divisor) * divisor)
46{
47 ARM_COMPUTE_ERROR_ON(value < 0 || divisor <= 0);
48 return ((value + divisor - 1) / divisor) * divisor;
49}
50
51/** Computes the largest number smaller or equal to value that is a multiple of divisor. */
52template <typename S, typename T>
53inline auto floor_to_multiple(S value, T divisor) -> decltype((value / divisor) * divisor)
54{
55 ARM_COMPUTE_ERROR_ON(value < 0 || divisor <= 0);
56 return (value / divisor) * divisor;
57}
58
59/** Calculate the rounded up quotient of val / m. */
60template <typename S, typename T>
61constexpr auto DIV_CEIL(S val, T m) -> decltype((val + m - 1) / m)
62{
63 return (val + m - 1) / m;
64}
65
66/** 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 *
617 * @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] ax The number of zeros added to right edge of the input.
624 * @param[in] ay The number of zeros added to top edge of the input.
625 * @param[in] upscalex How much to scale the X axis.
626 * @param[in] upscaley How much to scale the Y axis.
627 * @param[in] round Rounding policy to be used when computing the output's dimensions.
628 *
629 * @return A pair with the new width in the first position and the new height in the second.
630 */
631
632const std::pair<unsigned int, unsigned int> deconvolution_output_dimensions(unsigned int in_width, unsigned int in_height,
633 unsigned int kernel_width, unsigned int kernel_height,
634 unsigned int padx, unsigned int pady, unsigned int ax, unsigned int ay,
635 float upscalex, float upscaley, DimensionRoundingType round);
636
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100637/** Returns expected width and height of output scaled tensor depending on dimensions rounding mode.
638 *
Gian Marco Iodice4e288692017-06-27 11:41:59 +0100639 * @param[in] width Width of input tensor (Number of columns)
640 * @param[in] height Height of input tensor (Number of rows)
641 * @param[in] kernel_width Kernel width.
642 * @param[in] kernel_height Kernel height.
643 * @param[in] pad_stride_info Pad and stride information.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100644 *
645 * @return A pair with the new width in the first position and the new height in the second.
646 */
Gian Marco Iodice4e288692017-06-27 11:41:59 +0100647const std::pair<unsigned int, unsigned int> scaled_dimensions(unsigned int width, unsigned int height,
648 unsigned int kernel_width, unsigned int kernel_height,
649 const PadStrideInfo &pad_stride_info);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100650
651/** Convert a tensor format into a string.
652 *
653 * @param[in] format @ref Format to be translated to string.
654 *
655 * @return The string describing the format.
656 */
657const std::string &string_from_format(Format format);
658
659/** Convert a channel identity into a string.
660 *
661 * @param[in] channel @ref Channel to be translated to string.
662 *
663 * @return The string describing the channel.
664 */
665const std::string &string_from_channel(Channel channel);
666
667/** Convert a data type identity into a string.
668 *
669 * @param[in] dt @ref DataType to be translated to string.
670 *
671 * @return The string describing the data type.
672 */
673const std::string &string_from_data_type(DataType dt);
674/** Convert a matrix pattern into a string.
675 *
676 * @param[in] pattern @ref MatrixPattern to be translated to string.
677 *
678 * @return The string describing the matrix pattern.
679 */
680const std::string &string_from_matrix_pattern(MatrixPattern pattern);
681/** Translates a given activation function to a string.
682 *
683 * @param[in] act @ref ActivationLayerInfo::ActivationFunction to be translated to string.
684 *
685 * @return The string describing the activation function.
686 */
687const std::string &string_from_activation_func(ActivationLayerInfo::ActivationFunction act);
688/** Translates a given non linear function to a string.
689 *
690 * @param[in] function @ref NonLinearFilterFunction to be translated to string.
691 *
692 * @return The string describing the non linear function.
693 */
694const std::string &string_from_non_linear_filter_function(NonLinearFilterFunction function);
695/** Translates a given interpolation policy to a string.
696 *
697 * @param[in] policy @ref InterpolationPolicy to be translated to string.
698 *
699 * @return The string describing the interpolation policy.
700 */
701const std::string &string_from_interpolation_policy(InterpolationPolicy policy);
702/** Translates a given border mode policy to a string.
703 *
704 * @param[in] border_mode @ref BorderMode to be translated to string.
705 *
706 * @return The string describing the border mode.
707 */
708const std::string &string_from_border_mode(BorderMode border_mode);
709/** Translates a given normalization type to a string.
710 *
711 * @param[in] type @ref NormType to be translated to string.
712 *
713 * @return The string describing the normalization type.
714 */
715const std::string &string_from_norm_type(NormType type);
Georgios Pinitascdf51452017-08-31 14:21:36 +0100716/** Translates a given pooling type to a string.
717 *
718 * @param[in] type @ref PoolingType to be translated to string.
719 *
720 * @return The string describing the pooling type.
721 */
722const std::string &string_from_pooling_type(PoolingType type);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100723/** Lower a given string.
724 *
725 * @param[in] val Given string to lower.
726 *
727 * @return The lowered string
728 */
729std::string lower_string(const std::string &val);
730
731/** Check if a given data type is of floating point type
732 *
733 * @param[in] dt Input data type.
734 *
735 * @return True if data type is of floating point type, else false.
736 */
737inline bool is_data_type_float(DataType dt)
738{
739 switch(dt)
740 {
741 case DataType::F16:
742 case DataType::F32:
743 return true;
744 default:
745 return false;
746 }
747}
748
Georgios Pinitas05078ec2017-11-02 13:06:59 +0000749/** Check if a given data type is of quantized type
750 *
751 * @note Quantized is considered a super-set of fixed-point and asymmetric data types.
752 *
753 * @param[in] dt Input data type.
754 *
755 * @return True if data type is of quantized type, else false.
756 */
757inline bool is_data_type_quantized(DataType dt)
758{
759 switch(dt)
760 {
761 case DataType::QS8:
762 case DataType::QASYMM8:
763 case DataType::QS16:
764 case DataType::QS32:
765 return true;
766 default:
767 return false;
768 }
769}
770
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100771/** Check if a given data type is of fixed point type
772 *
773 * @param[in] dt Input data type.
774 *
775 * @return True if data type is of fixed point type, else false.
776 */
777inline bool is_data_type_fixed_point(DataType dt)
778{
779 switch(dt)
780 {
781 case DataType::QS8:
782 case DataType::QS16:
Pablo Tellof87cc7f2017-07-26 10:28:40 +0100783 case DataType::QS32:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100784 return true;
785 default:
786 return false;
787 }
788}
789
Georgios Pinitas05078ec2017-11-02 13:06:59 +0000790/** Check if a given data type is of asymmetric quantized type
791 *
792 * @param[in] dt Input data type.
793 *
794 * @return True if data type is of symmetric quantized type, else false.
795 */
Anton Lokhmotovaf6204c2017-11-08 09:34:19 +0000796inline bool is_data_type_quantized_asymmetric(DataType dt)
Georgios Pinitas05078ec2017-11-02 13:06:59 +0000797{
798 switch(dt)
799 {
800 case DataType::QASYMM8:
801 return true;
802 default:
803 return false;
804 }
805}
806
Georgios Pinitas89010962017-08-04 14:58:27 +0100807/** Create a string with the float in full precision.
808 *
809 * @param val Floating point value
810 *
811 * @return String with the floating point value.
812 */
813inline std::string float_to_string_with_full_precision(float val)
814{
815 std::stringstream ss;
816 ss.precision(std::numeric_limits<float>::digits10 + 1);
817 ss << val;
818 return ss.str();
819}
820
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100821/** Print consecutive elements to an output stream.
822 *
823 * @param[out] s Output stream to print the elements to.
824 * @param[in] ptr Pointer to print the elements from.
825 * @param[in] n Number of elements to print.
826 * @param[in] stream_width (Optional) Width of the stream. If set to 0 the element's width is used. Defaults to 0.
827 * @param[in] element_delim (Optional) Delimeter among the consecutive elements. Defaults to space delimeter
828 */
829template <typename T>
830void print_consecutive_elements_impl(std::ostream &s, const T *ptr, unsigned int n, int stream_width = 0, const std::string &element_delim = " ")
831{
832 using print_type = typename std::conditional<std::is_floating_point<T>::value, T, int>::type;
833
834 for(unsigned int i = 0; i < n; ++i)
835 {
836 // Set stream width as it is not a "sticky" stream manipulator
837 if(stream_width != 0)
838 {
839 s.width(stream_width);
840 }
Anthony Barbier7068f992017-10-26 15:23:08 +0100841
842 if(std::is_same<typename std::decay<T>::type, half>::value)
843 {
844 // 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.
845 s << std::right << static_cast<T>(ptr[i]) << element_delim;
846 }
847 else
848 {
849 s << std::right << static_cast<print_type>(ptr[i]) << element_delim;
850 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100851 }
852}
853
854/** Identify the maximum width of n consecutive elements.
855 *
856 * @param[in] s The output stream which will be used to print the elements. Used to extract the stream format.
857 * @param[in] ptr Pointer to the elements.
858 * @param[in] n Number of elements.
859 *
860 * @return The maximum width of the elements.
861 */
862template <typename T>
863int max_consecutive_elements_display_width_impl(std::ostream &s, const T *ptr, unsigned int n)
864{
865 using print_type = typename std::conditional<std::is_floating_point<T>::value, T, int>::type;
866
867 int max_width = -1;
868 for(unsigned int i = 0; i < n; ++i)
869 {
870 std::stringstream ss;
871 ss.copyfmt(s);
Anthony Barbier7068f992017-10-26 15:23:08 +0100872
873 if(std::is_same<typename std::decay<T>::type, half>::value)
874 {
875 // 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.
876 ss << static_cast<T>(ptr[i]);
877 }
878 else
879 {
880 ss << static_cast<print_type>(ptr[i]);
881 }
882
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100883 max_width = std::max<int>(max_width, ss.str().size());
884 }
885 return max_width;
886}
887
888/** Print consecutive elements to an output stream.
889 *
890 * @param[out] s Output stream to print the elements to.
891 * @param[in] dt Data type of the elements
892 * @param[in] ptr Pointer to print the elements from.
893 * @param[in] n Number of elements to print.
894 * @param[in] stream_width (Optional) Width of the stream. If set to 0 the element's width is used. Defaults to 0.
895 * @param[in] element_delim (Optional) Delimeter among the consecutive elements. Defaults to space delimeter
896 */
897void print_consecutive_elements(std::ostream &s, DataType dt, const uint8_t *ptr, unsigned int n, int stream_width, const std::string &element_delim = " ");
898
899/** Identify the maximum width of n consecutive elements.
900 *
901 * @param[in] s Output stream to print the elements to.
902 * @param[in] dt Data type of the elements
903 * @param[in] ptr Pointer to print the elements from.
904 * @param[in] n Number of elements to print.
905 *
906 * @return The maximum width of the elements.
907 */
908int max_consecutive_elements_display_width(std::ostream &s, DataType dt, const uint8_t *ptr, unsigned int n);
909}
910#endif /*__ARM_COMPUTE_UTILS_H__ */