blob: 39ec6587de1b52e5b319be1ffd637aa23235bceb [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"
28#include "arm_compute/core/Types.h"
29
30#include <algorithm>
31#include <cstdint>
32#include <cstdlib>
33#include <numeric>
34#include <sstream>
35#include <string>
36#include <type_traits>
37#include <utility>
38
39namespace arm_compute
40{
41/** Computes the smallest number larger or equal to value that is a multiple of divisor. */
42template <typename S, typename T>
43inline auto ceil_to_multiple(S value, T divisor) -> decltype(((value + divisor - 1) / divisor) * divisor)
44{
45 ARM_COMPUTE_ERROR_ON(value < 0 || divisor <= 0);
46 return ((value + divisor - 1) / divisor) * divisor;
47}
48
49/** Computes the largest number smaller or equal to value that is a multiple of divisor. */
50template <typename S, typename T>
51inline auto floor_to_multiple(S value, T divisor) -> decltype((value / divisor) * divisor)
52{
53 ARM_COMPUTE_ERROR_ON(value < 0 || divisor <= 0);
54 return (value / divisor) * divisor;
55}
56
57/** Calculate the rounded up quotient of val / m. */
58template <typename S, typename T>
59constexpr auto DIV_CEIL(S val, T m) -> decltype((val + m - 1) / m)
60{
61 return (val + m - 1) / m;
62}
63
64/** Returns the arm_compute library build information
65 *
66 * Contains the version number and the build options used to build the library
67 *
68 * @return The arm_compute library build information
69 */
70std::string build_information();
71
72/** Load an entire file in memory
73 *
74 * @param[in] filename Name of the file to read.
75 * @param[in] binary Is it a binary file ?
76 *
77 * @return The content of the file.
78 */
79std::string read_file(const std::string &filename, bool binary);
80
Anthony Barbier6ff3b192017-09-04 18:44:23 +010081/** The size in bytes of the data type
82 *
83 * @param[in] data_type Input data type
84 *
85 * @return The size in bytes of the data type
86 */
87inline size_t data_size_from_type(DataType data_type)
88{
89 switch(data_type)
90 {
91 case DataType::U8:
92 case DataType::S8:
93 case DataType::QS8:
94 return 1;
95 case DataType::U16:
96 case DataType::S16:
97 case DataType::F16:
98 case DataType::QS16:
99 return 2;
100 case DataType::F32:
101 case DataType::U32:
102 case DataType::S32:
Pablo Tellof87cc7f2017-07-26 10:28:40 +0100103 case DataType::QS32:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100104 return 4;
105 case DataType::F64:
106 case DataType::U64:
107 case DataType::S64:
108 return 8;
109 case DataType::SIZET:
110 return sizeof(size_t);
111 default:
112 ARM_COMPUTE_ERROR("Invalid data type");
113 return 0;
114 }
115}
116
117/** The size in bytes of the pixel format
118 *
119 * @param[in] format Input format
120 *
121 * @return The size in bytes of the pixel format
122 */
123inline size_t pixel_size_from_format(Format format)
124{
125 switch(format)
126 {
127 case Format::U8:
128 return 1;
129 case Format::U16:
130 case Format::S16:
131 case Format::F16:
132 case Format::UV88:
133 case Format::YUYV422:
134 case Format::UYVY422:
135 return 2;
136 case Format::RGB888:
137 return 3;
138 case Format::RGBA8888:
139 return 4;
140 case Format::U32:
141 case Format::S32:
142 case Format::F32:
143 return 4;
144 //Doesn't make sense for planar formats:
145 case Format::NV12:
146 case Format::NV21:
147 case Format::IYUV:
148 case Format::YUV444:
149 default:
150 ARM_COMPUTE_ERROR("Undefined pixel size for given format");
151 return 0;
152 }
153}
154
155/** The size in bytes of the data type
156 *
157 * @param[in] dt Input data type
158 *
159 * @return The size in bytes of the data type
160 */
161inline size_t element_size_from_data_type(DataType dt)
162{
163 switch(dt)
164 {
165 case DataType::S8:
166 case DataType::U8:
167 case DataType::QS8:
168 return 1;
169 case DataType::U16:
170 case DataType::S16:
171 case DataType::QS16:
172 case DataType::F16:
173 return 2;
174 case DataType::U32:
175 case DataType::S32:
176 case DataType::F32:
Pablo Tellof87cc7f2017-07-26 10:28:40 +0100177 case DataType::QS32:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100178 return 4;
179 default:
180 ARM_COMPUTE_ERROR("Undefined element size for given data type");
181 return 0;
182 }
183}
184
185/** Return the data type used by a given single-planar pixel format
186 *
187 * @param[in] format Input format
188 *
189 * @return The size in bytes of the pixel format
190 */
191inline DataType data_type_from_format(Format format)
192{
193 switch(format)
194 {
195 case Format::U8:
196 case Format::UV88:
197 case Format::RGB888:
198 case Format::RGBA8888:
199 case Format::YUYV422:
200 case Format::UYVY422:
201 return DataType::U8;
202 case Format::U16:
203 return DataType::U16;
204 case Format::S16:
205 return DataType::S16;
206 case Format::U32:
207 return DataType::U32;
208 case Format::S32:
209 return DataType::S32;
210 case Format::F16:
211 return DataType::F16;
212 case Format::F32:
213 return DataType::F32;
214 //Doesn't make sense for planar formats:
215 case Format::NV12:
216 case Format::NV21:
217 case Format::IYUV:
218 case Format::YUV444:
219 default:
220 ARM_COMPUTE_ERROR("Not supported data_type for given format");
221 return DataType::UNKNOWN;
222 }
223}
224
225/** Return the plane index of a given channel given an input format.
226 *
227 * @param[in] format Input format
228 * @param[in] channel Input channel
229 *
230 * @return The plane index of the specific channel of the specific format
231 */
232inline int plane_idx_from_channel(Format format, Channel channel)
233{
234 switch(format)
235 {
236 case Format::NV12:
237 case Format::NV21:
238 {
239 switch(channel)
240 {
241 case Channel::Y:
242 return 0;
243 case Channel::U:
244 case Channel::V:
245 return 1;
246 default:
247 ARM_COMPUTE_ERROR("Not supported channel");
248 return 0;
249 }
250 }
251 case Format::IYUV:
252 case Format::YUV444:
253 {
254 switch(channel)
255 {
256 case Channel::Y:
257 return 0;
258 case Channel::U:
259 return 1;
260 case Channel::V:
261 return 2;
262 default:
263 ARM_COMPUTE_ERROR("Not supported channel");
264 return 0;
265 }
266 }
267 default:
268 ARM_COMPUTE_ERROR("Not supported format");
269 return 0;
270 }
271}
272
273/** Return the number of planes for a given format
274 *
275 * @param[in] format Input format
276 *
277 * @return The number of planes for a given image format.
278 */
279inline size_t num_planes_from_format(Format format)
280{
281 switch(format)
282 {
283 case Format::U8:
284 case Format::S16:
285 case Format::U16:
286 case Format::S32:
287 case Format::U32:
288 case Format::F16:
289 case Format::F32:
290 case Format::RGB888:
291 case Format::RGBA8888:
292 case Format::YUYV422:
293 case Format::UYVY422:
294 return 1;
295 case Format::NV12:
296 case Format::NV21:
297 return 2;
298 case Format::IYUV:
299 case Format::YUV444:
300 return 3;
301 default:
302 ARM_COMPUTE_ERROR("Not supported format");
303 return 0;
304 }
305}
306
307/** Return the number of channels for a given single-planar pixel format
308 *
309 * @param[in] format Input format
310 *
311 * @return The number of channels for a given image format.
312 */
313inline size_t num_channels_from_format(Format format)
314{
315 switch(format)
316 {
317 case Format::U8:
318 case Format::U16:
319 case Format::S16:
320 case Format::U32:
321 case Format::S32:
322 case Format::F16:
323 case Format::F32:
324 return 1;
325 // Because the U and V channels are subsampled
326 // these formats appear like having only 2 channels:
327 case Format::YUYV422:
328 case Format::UYVY422:
329 return 2;
330 case Format::UV88:
331 return 2;
332 case Format::RGB888:
333 return 3;
334 case Format::RGBA8888:
335 return 4;
336 //Doesn't make sense for planar formats:
337 case Format::NV12:
338 case Format::NV21:
339 case Format::IYUV:
340 case Format::YUV444:
341 default:
342 return 0;
343 }
344}
345
346/** Separate a 2D convolution into two 1D convolutions
347*
348* @param[in] conv 2D convolution
349* @param[out] conv_col 1D vertical convolution
350* @param[out] conv_row 1D horizontal convolution
351* @param[in] size Size of the 2D convolution
352*
353* @return true if the separation was successful
354*/
355inline bool separate_matrix(const int16_t *conv, int16_t *conv_col, int16_t *conv_row, uint8_t size)
356{
357 int32_t min_col = -1;
358 int16_t min_col_val = -1;
359
360 for(int32_t i = 0; i < size; ++i)
361 {
362 if(conv[i] != 0 && (min_col < 0 || abs(min_col_val) > abs(conv[i])))
363 {
364 min_col = i;
365 min_col_val = conv[i];
366 }
367 }
368
369 if(min_col < 0)
370 {
371 return false;
372 }
373
374 for(uint32_t j = 0; j < size; ++j)
375 {
376 conv_col[j] = conv[min_col + j * size];
377 }
378
379 for(uint32_t i = 0; i < size; i++)
380 {
381 if(static_cast<int>(i) == min_col)
382 {
383 conv_row[i] = 1;
384 }
385 else
386 {
387 int16_t coeff = conv[i] / conv[min_col];
388
389 for(uint32_t j = 1; j < size; ++j)
390 {
391 if(conv[i + j * size] != (conv_col[j] * coeff))
392 {
393 return false;
394 }
395 }
396
397 conv_row[i] = coeff;
398 }
399 }
400
401 return true;
402}
403
404/** Calculate the scale of the given square matrix
405 *
406 * The scale is the absolute value of the sum of all the coefficients in the matrix.
407 *
408 * @note If the coefficients add up to 0 then the scale is set to 1.
409 *
410 * @param[in] matrix Matrix coefficients
411 * @param[in] matrix_size Number of elements per side of the square matrix. (Number of coefficients = matrix_size * matrix_size).
412 *
413 * @return The absolute value of the sum of the coefficients if they don't add up to 0, otherwise 1.
414 */
415inline uint32_t calculate_matrix_scale(const int16_t *matrix, unsigned int matrix_size)
416{
417 const size_t size = matrix_size * matrix_size;
418
419 return std::max(1, std::abs(std::accumulate(matrix, matrix + size, 0)));
420}
421
422/** Calculate accurary required by the horizontal and vertical convolution computations
423 *
424 * @param[in] conv_col Pointer to the vertical vector of the separated convolution filter
425 * @param[in] conv_row Pointer to the horizontal vector of the convolution filter
426 * @param[in] size Number of elements per vector of the separated matrix
427 *
428 * @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
429 * element of the pair is the biggest data type needed for the second stage.
430 */
431inline std::pair<DataType, DataType> data_type_for_convolution(const int16_t *conv_col, const int16_t *conv_row, size_t size)
432{
433 DataType first_stage = DataType::UNKNOWN;
434 DataType second_stage = DataType::UNKNOWN;
435
436 auto gez = [](const int16_t &v)
437 {
438 return v >= 0;
439 };
440
441 auto accu_neg = [](const int &first, const int &second)
442 {
443 return first + (second < 0 ? second : 0);
444 };
445
446 auto accu_pos = [](const int &first, const int &second)
447 {
448 return first + (second > 0 ? second : 0);
449 };
450
451 const bool only_positive_coefficients = std::all_of(conv_row, conv_row + size, gez) && std::all_of(conv_col, conv_col + size, gez);
452
453 if(only_positive_coefficients)
454 {
455 const int max_row_value = std::accumulate(conv_row, conv_row + size, 0) * UINT8_MAX;
456 const int max_value = std::accumulate(conv_col, conv_col + size, 0) * max_row_value;
457
458 first_stage = (max_row_value <= UINT16_MAX) ? DataType::U16 : DataType::S32;
459
460 second_stage = (max_value <= UINT16_MAX) ? DataType::U16 : DataType::S32;
461 }
462 else
463 {
464 const int min_row_value = std::accumulate(conv_row, conv_row + size, 0, accu_neg) * UINT8_MAX;
465 const int max_row_value = std::accumulate(conv_row, conv_row + size, 0, accu_pos) * UINT8_MAX;
466 const int neg_coeffs_sum = std::accumulate(conv_col, conv_col + size, 0, accu_neg);
467 const int pos_coeffs_sum = std::accumulate(conv_col, conv_col + size, 0, accu_pos);
468 const int min_value = neg_coeffs_sum * max_row_value + pos_coeffs_sum * min_row_value;
469 const int max_value = neg_coeffs_sum * min_row_value + pos_coeffs_sum * max_row_value;
470
471 first_stage = ((INT16_MIN <= min_row_value) && (max_row_value <= INT16_MAX)) ? DataType::S16 : DataType::S32;
472
473 second_stage = ((INT16_MIN <= min_value) && (max_value <= INT16_MAX)) ? DataType::S16 : DataType::S32;
474 }
475
476 return std::make_pair(first_stage, second_stage);
477}
478
479/** Calculate the accuracy required by the squared convolution calculation.
480 *
481 *
482 * @param[in] conv Pointer to the squared convolution matrix
483 * @param[in] size The total size of the convolution matrix
484 *
485 * @return The return is the biggest data type needed to do the convolution
486 */
487inline DataType data_type_for_convolution_matrix(const int16_t *conv, size_t size)
488{
489 auto gez = [](const int16_t v)
490 {
491 return v >= 0;
492 };
493
494 const bool only_positive_coefficients = std::all_of(conv, conv + size, gez);
495
496 if(only_positive_coefficients)
497 {
498 const int max_conv_value = std::accumulate(conv, conv + size, 0) * UINT8_MAX;
499 if(max_conv_value <= UINT16_MAX)
500 {
501 return DataType::U16;
502 }
503 else
504 {
505 return DataType::S32;
506 }
507 }
508 else
509 {
510 const int min_value = std::accumulate(conv, conv + size, 0, [](int a, int b)
511 {
512 return b < 0 ? a + b : a;
513 })
514 * UINT8_MAX;
515
516 const int max_value = std::accumulate(conv, conv + size, 0, [](int a, int b)
517 {
518 return b > 0 ? a + b : a;
519 })
520 * UINT8_MAX;
521
522 if((INT16_MIN <= min_value) && (INT16_MAX >= max_value))
523 {
524 return DataType::S16;
525 }
526 else
527 {
528 return DataType::S32;
529 }
530 }
531}
532
533/** Returns expected width and height of output scaled tensor depending on dimensions rounding mode.
534 *
Gian Marco Iodice4e288692017-06-27 11:41:59 +0100535 * @param[in] width Width of input tensor (Number of columns)
536 * @param[in] height Height of input tensor (Number of rows)
537 * @param[in] kernel_width Kernel width.
538 * @param[in] kernel_height Kernel height.
539 * @param[in] pad_stride_info Pad and stride information.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100540 *
541 * @return A pair with the new width in the first position and the new height in the second.
542 */
Gian Marco Iodice4e288692017-06-27 11:41:59 +0100543const std::pair<unsigned int, unsigned int> scaled_dimensions(unsigned int width, unsigned int height,
544 unsigned int kernel_width, unsigned int kernel_height,
545 const PadStrideInfo &pad_stride_info);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100546
547/** Convert a tensor format into a string.
548 *
549 * @param[in] format @ref Format to be translated to string.
550 *
551 * @return The string describing the format.
552 */
553const std::string &string_from_format(Format format);
554
555/** Convert a channel identity into a string.
556 *
557 * @param[in] channel @ref Channel to be translated to string.
558 *
559 * @return The string describing the channel.
560 */
561const std::string &string_from_channel(Channel channel);
562
563/** Convert a data type identity into a string.
564 *
565 * @param[in] dt @ref DataType to be translated to string.
566 *
567 * @return The string describing the data type.
568 */
569const std::string &string_from_data_type(DataType dt);
570/** Convert a matrix pattern into a string.
571 *
572 * @param[in] pattern @ref MatrixPattern to be translated to string.
573 *
574 * @return The string describing the matrix pattern.
575 */
576const std::string &string_from_matrix_pattern(MatrixPattern pattern);
577/** Translates a given activation function to a string.
578 *
579 * @param[in] act @ref ActivationLayerInfo::ActivationFunction to be translated to string.
580 *
581 * @return The string describing the activation function.
582 */
583const std::string &string_from_activation_func(ActivationLayerInfo::ActivationFunction act);
584/** Translates a given non linear function to a string.
585 *
586 * @param[in] function @ref NonLinearFilterFunction to be translated to string.
587 *
588 * @return The string describing the non linear function.
589 */
590const std::string &string_from_non_linear_filter_function(NonLinearFilterFunction function);
591/** Translates a given interpolation policy to a string.
592 *
593 * @param[in] policy @ref InterpolationPolicy to be translated to string.
594 *
595 * @return The string describing the interpolation policy.
596 */
597const std::string &string_from_interpolation_policy(InterpolationPolicy policy);
598/** Translates a given border mode policy to a string.
599 *
600 * @param[in] border_mode @ref BorderMode to be translated to string.
601 *
602 * @return The string describing the border mode.
603 */
604const std::string &string_from_border_mode(BorderMode border_mode);
605/** Translates a given normalization type to a string.
606 *
607 * @param[in] type @ref NormType to be translated to string.
608 *
609 * @return The string describing the normalization type.
610 */
611const std::string &string_from_norm_type(NormType type);
612/** Lower a given string.
613 *
614 * @param[in] val Given string to lower.
615 *
616 * @return The lowered string
617 */
618std::string lower_string(const std::string &val);
619
620/** Check if a given data type is of floating point type
621 *
622 * @param[in] dt Input data type.
623 *
624 * @return True if data type is of floating point type, else false.
625 */
626inline bool is_data_type_float(DataType dt)
627{
628 switch(dt)
629 {
630 case DataType::F16:
631 case DataType::F32:
632 return true;
633 default:
634 return false;
635 }
636}
637
638/** Check if a given data type is of fixed point type
639 *
640 * @param[in] dt Input data type.
641 *
642 * @return True if data type is of fixed point type, else false.
643 */
644inline bool is_data_type_fixed_point(DataType dt)
645{
646 switch(dt)
647 {
648 case DataType::QS8:
649 case DataType::QS16:
Pablo Tellof87cc7f2017-07-26 10:28:40 +0100650 case DataType::QS32:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100651 return true;
652 default:
653 return false;
654 }
655}
656
Georgios Pinitas89010962017-08-04 14:58:27 +0100657/** Create a string with the float in full precision.
658 *
659 * @param val Floating point value
660 *
661 * @return String with the floating point value.
662 */
663inline std::string float_to_string_with_full_precision(float val)
664{
665 std::stringstream ss;
666 ss.precision(std::numeric_limits<float>::digits10 + 1);
667 ss << val;
668 return ss.str();
669}
670
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100671/** Print consecutive elements to an output stream.
672 *
673 * @param[out] s Output stream to print the elements to.
674 * @param[in] ptr Pointer to print the elements from.
675 * @param[in] n Number of elements to print.
676 * @param[in] stream_width (Optional) Width of the stream. If set to 0 the element's width is used. Defaults to 0.
677 * @param[in] element_delim (Optional) Delimeter among the consecutive elements. Defaults to space delimeter
678 */
679template <typename T>
680void print_consecutive_elements_impl(std::ostream &s, const T *ptr, unsigned int n, int stream_width = 0, const std::string &element_delim = " ")
681{
682 using print_type = typename std::conditional<std::is_floating_point<T>::value, T, int>::type;
683
684 for(unsigned int i = 0; i < n; ++i)
685 {
686 // Set stream width as it is not a "sticky" stream manipulator
687 if(stream_width != 0)
688 {
689 s.width(stream_width);
690 }
691 s << std::right << static_cast<print_type>(ptr[i]) << element_delim;
692 }
693}
694
695/** Identify the maximum width of n consecutive elements.
696 *
697 * @param[in] s The output stream which will be used to print the elements. Used to extract the stream format.
698 * @param[in] ptr Pointer to the elements.
699 * @param[in] n Number of elements.
700 *
701 * @return The maximum width of the elements.
702 */
703template <typename T>
704int max_consecutive_elements_display_width_impl(std::ostream &s, const T *ptr, unsigned int n)
705{
706 using print_type = typename std::conditional<std::is_floating_point<T>::value, T, int>::type;
707
708 int max_width = -1;
709 for(unsigned int i = 0; i < n; ++i)
710 {
711 std::stringstream ss;
712 ss.copyfmt(s);
713 ss << static_cast<print_type>(ptr[i]);
714 max_width = std::max<int>(max_width, ss.str().size());
715 }
716 return max_width;
717}
718
719/** Print consecutive elements to an output stream.
720 *
721 * @param[out] s Output stream to print the elements to.
722 * @param[in] dt Data type of the elements
723 * @param[in] ptr Pointer to print the elements from.
724 * @param[in] n Number of elements to print.
725 * @param[in] stream_width (Optional) Width of the stream. If set to 0 the element's width is used. Defaults to 0.
726 * @param[in] element_delim (Optional) Delimeter among the consecutive elements. Defaults to space delimeter
727 */
728void print_consecutive_elements(std::ostream &s, DataType dt, const uint8_t *ptr, unsigned int n, int stream_width, const std::string &element_delim = " ");
729
730/** Identify the maximum width of n consecutive elements.
731 *
732 * @param[in] s Output stream to print the elements to.
733 * @param[in] dt Data type of the elements
734 * @param[in] ptr Pointer to print the elements from.
735 * @param[in] n Number of elements to print.
736 *
737 * @return The maximum width of the elements.
738 */
739int max_consecutive_elements_display_width(std::ostream &s, DataType dt, const uint8_t *ptr, unsigned int n);
740}
741#endif /*__ARM_COMPUTE_UTILS_H__ */