blob: edeae21c6fd66b6537b26986f84b98ee9d885b97 [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
Matthew Benthamf1aeab92023-05-30 13:35:34 +00002 * Copyright (c) 2016-2023 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_UTILS_H
25#define ARM_COMPUTE_UTILS_H
Anthony Barbier6ff3b192017-09-04 18:44:23 +010026
27#include "arm_compute/core/Error.h"
Giuseppe Rossinid7647d42018-07-17 18:13:13 +010028#include "arm_compute/core/PixelValue.h"
Michel Iwaniec5dfeae62017-11-29 10:48:23 +000029#include "arm_compute/core/Rounding.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010030#include "arm_compute/core/Types.h"
Georgios Pinitas51545e42020-02-11 15:29:01 +000031#include "arm_compute/core/Version.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010032
33#include <algorithm>
34#include <cstdint>
35#include <cstdlib>
Michalis Spyrou53860dd2019-07-01 14:20:56 +010036#include <iomanip>
Anthony Barbier6ff3b192017-09-04 18:44:23 +010037#include <numeric>
38#include <sstream>
39#include <string>
40#include <type_traits>
Giorgio Arena1e2af2a2020-10-15 17:39:41 +010041#include <unordered_map>
Anthony Barbier6ff3b192017-09-04 18:44:23 +010042#include <utility>
steniu017ce53c62017-09-29 14:55:00 +010043#include <vector>
Anthony Barbier6ff3b192017-09-04 18:44:23 +010044
45namespace arm_compute
46{
Giorgio Arena1e2af2a2020-10-15 17:39:41 +010047class ITensor;
Giorgio Arena4112eed2020-10-23 14:24:26 +010048class ITensorInfo;
Matthew Benthamf1aeab92023-05-30 13:35:34 +000049class ActivationLayerInfo;
Giorgio Arena1e2af2a2020-10-15 17:39:41 +010050
Anthony Barbier6ff3b192017-09-04 18:44:23 +010051/** Load an entire file in memory
52 *
53 * @param[in] filename Name of the file to read.
54 * @param[in] binary Is it a binary file ?
55 *
56 * @return The content of the file.
57 */
58std::string read_file(const std::string &filename, bool binary);
59
Anthony Barbier6ff3b192017-09-04 18:44:23 +010060/** The size in bytes of the data type
61 *
62 * @param[in] data_type Input data type
63 *
64 * @return The size in bytes of the data type
65 */
66inline size_t data_size_from_type(DataType data_type)
67{
68 switch(data_type)
69 {
70 case DataType::U8:
71 case DataType::S8:
Georgios Pinitas4c5469b2019-05-21 13:32:43 +010072 case DataType::QSYMM8:
Michel Iwaniec00633802017-10-12 14:14:15 +010073 case DataType::QASYMM8:
Georgios Pinitasdbdea0d2019-10-16 19:21:40 +010074 case DataType::QASYMM8_SIGNED:
Georgios Pinitas4c5469b2019-05-21 13:32:43 +010075 case DataType::QSYMM8_PER_CHANNEL:
Anthony Barbier6ff3b192017-09-04 18:44:23 +010076 return 1;
77 case DataType::U16:
78 case DataType::S16:
Manuel Bottini3689fcd2019-06-14 17:18:12 +010079 case DataType::QSYMM16:
Michele Di Giorgio35ea9a72019-08-23 12:02:06 +010080 case DataType::QASYMM16:
Georgios Pinitase8291ac2020-02-26 09:58:13 +000081 case DataType::BFLOAT16:
Anthony Barbier6ff3b192017-09-04 18:44:23 +010082 case DataType::F16:
Anthony Barbier6ff3b192017-09-04 18:44:23 +010083 return 2;
84 case DataType::F32:
85 case DataType::U32:
86 case DataType::S32:
87 return 4;
88 case DataType::F64:
89 case DataType::U64:
90 case DataType::S64:
91 return 8;
92 case DataType::SIZET:
93 return sizeof(size_t);
94 default:
95 ARM_COMPUTE_ERROR("Invalid data type");
96 return 0;
97 }
98}
99
100/** The size in bytes of the pixel format
101 *
102 * @param[in] format Input format
103 *
104 * @return The size in bytes of the pixel format
105 */
106inline size_t pixel_size_from_format(Format format)
107{
108 switch(format)
109 {
110 case Format::U8:
111 return 1;
112 case Format::U16:
113 case Format::S16:
Georgios Pinitase8291ac2020-02-26 09:58:13 +0000114 case Format::BFLOAT16:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100115 case Format::F16:
116 case Format::UV88:
117 case Format::YUYV422:
118 case Format::UYVY422:
119 return 2;
120 case Format::RGB888:
121 return 3;
122 case Format::RGBA8888:
123 return 4;
124 case Format::U32:
125 case Format::S32:
126 case Format::F32:
127 return 4;
128 //Doesn't make sense for planar formats:
129 case Format::NV12:
130 case Format::NV21:
131 case Format::IYUV:
132 case Format::YUV444:
133 default:
134 ARM_COMPUTE_ERROR("Undefined pixel size for given format");
135 return 0;
136 }
137}
138
139/** The size in bytes of the data type
140 *
141 * @param[in] dt Input data type
142 *
143 * @return The size in bytes of the data type
144 */
145inline size_t element_size_from_data_type(DataType dt)
146{
147 switch(dt)
148 {
149 case DataType::S8:
150 case DataType::U8:
Georgios Pinitas4c5469b2019-05-21 13:32:43 +0100151 case DataType::QSYMM8:
Michel Iwaniec00633802017-10-12 14:14:15 +0100152 case DataType::QASYMM8:
Georgios Pinitasdbdea0d2019-10-16 19:21:40 +0100153 case DataType::QASYMM8_SIGNED:
Georgios Pinitas4c5469b2019-05-21 13:32:43 +0100154 case DataType::QSYMM8_PER_CHANNEL:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100155 return 1;
156 case DataType::U16:
157 case DataType::S16:
Manuel Bottini3689fcd2019-06-14 17:18:12 +0100158 case DataType::QSYMM16:
Michele Di Giorgio35ea9a72019-08-23 12:02:06 +0100159 case DataType::QASYMM16:
Georgios Pinitase8291ac2020-02-26 09:58:13 +0000160 case DataType::BFLOAT16:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100161 case DataType::F16:
162 return 2;
163 case DataType::U32:
164 case DataType::S32:
165 case DataType::F32:
166 return 4;
167 default:
168 ARM_COMPUTE_ERROR("Undefined element size for given data type");
169 return 0;
170 }
171}
172
173/** Return the data type used by a given single-planar pixel format
174 *
175 * @param[in] format Input format
176 *
177 * @return The size in bytes of the pixel format
178 */
179inline DataType data_type_from_format(Format format)
180{
181 switch(format)
182 {
183 case Format::U8:
184 case Format::UV88:
185 case Format::RGB888:
186 case Format::RGBA8888:
187 case Format::YUYV422:
188 case Format::UYVY422:
189 return DataType::U8;
190 case Format::U16:
191 return DataType::U16;
192 case Format::S16:
193 return DataType::S16;
194 case Format::U32:
195 return DataType::U32;
196 case Format::S32:
197 return DataType::S32;
Georgios Pinitase8291ac2020-02-26 09:58:13 +0000198 case Format::BFLOAT16:
199 return DataType::BFLOAT16;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100200 case Format::F16:
201 return DataType::F16;
202 case Format::F32:
203 return DataType::F32;
204 //Doesn't make sense for planar formats:
205 case Format::NV12:
206 case Format::NV21:
207 case Format::IYUV:
208 case Format::YUV444:
209 default:
210 ARM_COMPUTE_ERROR("Not supported data_type for given format");
211 return DataType::UNKNOWN;
212 }
213}
214
215/** Return the plane index of a given channel given an input format.
216 *
217 * @param[in] format Input format
218 * @param[in] channel Input channel
219 *
220 * @return The plane index of the specific channel of the specific format
221 */
222inline int plane_idx_from_channel(Format format, Channel channel)
223{
224 switch(format)
225 {
Ioan-Cristian Szabo9414f642017-10-27 17:35:40 +0100226 // Single planar formats have a single plane
227 case Format::U8:
228 case Format::U16:
229 case Format::S16:
230 case Format::U32:
231 case Format::S32:
Georgios Pinitase8291ac2020-02-26 09:58:13 +0000232 case Format::BFLOAT16:
Ioan-Cristian Szabo9414f642017-10-27 17:35:40 +0100233 case Format::F16:
234 case Format::F32:
235 case Format::UV88:
236 case Format::RGB888:
237 case Format::RGBA8888:
238 case Format::YUYV422:
239 case Format::UYVY422:
240 return 0;
241 // Multi planar formats
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100242 case Format::NV12:
243 case Format::NV21:
244 {
Ioan-Cristian Szabo9414f642017-10-27 17:35:40 +0100245 // Channel U and V share the same plane of format UV88
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100246 switch(channel)
247 {
248 case Channel::Y:
249 return 0;
250 case Channel::U:
251 case Channel::V:
252 return 1;
253 default:
254 ARM_COMPUTE_ERROR("Not supported channel");
255 return 0;
256 }
257 }
258 case Format::IYUV:
259 case Format::YUV444:
260 {
261 switch(channel)
262 {
263 case Channel::Y:
264 return 0;
265 case Channel::U:
266 return 1;
267 case Channel::V:
268 return 2;
269 default:
270 ARM_COMPUTE_ERROR("Not supported channel");
271 return 0;
272 }
273 }
274 default:
275 ARM_COMPUTE_ERROR("Not supported format");
276 return 0;
277 }
278}
279
Ioan-Cristian Szabo9414f642017-10-27 17:35:40 +0100280/** Return the channel index of a given channel given an input format.
281 *
282 * @param[in] format Input format
283 * @param[in] channel Input channel
284 *
285 * @return The channel index of the specific channel of the specific format
286 */
287inline int channel_idx_from_format(Format format, Channel channel)
288{
289 switch(format)
290 {
291 case Format::RGB888:
292 {
293 switch(channel)
294 {
295 case Channel::R:
296 return 0;
297 case Channel::G:
298 return 1;
299 case Channel::B:
300 return 2;
301 default:
302 ARM_COMPUTE_ERROR("Not supported channel");
303 return 0;
304 }
305 }
306 case Format::RGBA8888:
307 {
308 switch(channel)
309 {
310 case Channel::R:
311 return 0;
312 case Channel::G:
313 return 1;
314 case Channel::B:
315 return 2;
316 case Channel::A:
317 return 3;
318 default:
319 ARM_COMPUTE_ERROR("Not supported channel");
320 return 0;
321 }
322 }
323 case Format::YUYV422:
324 {
325 switch(channel)
326 {
327 case Channel::Y:
328 return 0;
329 case Channel::U:
330 return 1;
331 case Channel::V:
332 return 3;
333 default:
334 ARM_COMPUTE_ERROR("Not supported channel");
335 return 0;
336 }
337 }
338 case Format::UYVY422:
339 {
340 switch(channel)
341 {
342 case Channel::Y:
343 return 1;
344 case Channel::U:
345 return 0;
346 case Channel::V:
347 return 2;
348 default:
349 ARM_COMPUTE_ERROR("Not supported channel");
350 return 0;
351 }
352 }
353 case Format::NV12:
354 {
355 switch(channel)
356 {
357 case Channel::Y:
358 return 0;
359 case Channel::U:
360 return 0;
361 case Channel::V:
362 return 1;
363 default:
364 ARM_COMPUTE_ERROR("Not supported channel");
365 return 0;
366 }
367 }
368 case Format::NV21:
369 {
370 switch(channel)
371 {
372 case Channel::Y:
373 return 0;
374 case Channel::U:
375 return 1;
376 case Channel::V:
377 return 0;
378 default:
379 ARM_COMPUTE_ERROR("Not supported channel");
380 return 0;
381 }
382 }
383 case Format::YUV444:
384 case Format::IYUV:
385 {
386 switch(channel)
387 {
388 case Channel::Y:
389 return 0;
390 case Channel::U:
391 return 0;
392 case Channel::V:
393 return 0;
394 default:
395 ARM_COMPUTE_ERROR("Not supported channel");
396 return 0;
397 }
398 }
399 default:
400 ARM_COMPUTE_ERROR("Not supported format");
401 return 0;
402 }
403}
404
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100405/** Return the number of planes for a given format
406 *
407 * @param[in] format Input format
408 *
409 * @return The number of planes for a given image format.
410 */
411inline size_t num_planes_from_format(Format format)
412{
413 switch(format)
414 {
415 case Format::U8:
416 case Format::S16:
417 case Format::U16:
418 case Format::S32:
419 case Format::U32:
Georgios Pinitase8291ac2020-02-26 09:58:13 +0000420 case Format::BFLOAT16:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100421 case Format::F16:
422 case Format::F32:
423 case Format::RGB888:
424 case Format::RGBA8888:
425 case Format::YUYV422:
426 case Format::UYVY422:
427 return 1;
428 case Format::NV12:
429 case Format::NV21:
430 return 2;
431 case Format::IYUV:
432 case Format::YUV444:
433 return 3;
434 default:
435 ARM_COMPUTE_ERROR("Not supported format");
436 return 0;
437 }
438}
439
440/** Return the number of channels for a given single-planar pixel format
441 *
442 * @param[in] format Input format
443 *
444 * @return The number of channels for a given image format.
445 */
446inline size_t num_channels_from_format(Format format)
447{
448 switch(format)
449 {
450 case Format::U8:
451 case Format::U16:
452 case Format::S16:
453 case Format::U32:
454 case Format::S32:
Georgios Pinitase8291ac2020-02-26 09:58:13 +0000455 case Format::BFLOAT16:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100456 case Format::F16:
457 case Format::F32:
458 return 1;
459 // Because the U and V channels are subsampled
460 // these formats appear like having only 2 channels:
461 case Format::YUYV422:
462 case Format::UYVY422:
463 return 2;
464 case Format::UV88:
465 return 2;
466 case Format::RGB888:
467 return 3;
468 case Format::RGBA8888:
469 return 4;
470 //Doesn't make sense for planar formats:
471 case Format::NV12:
472 case Format::NV21:
473 case Format::IYUV:
474 case Format::YUV444:
475 default:
476 return 0;
477 }
478}
479
Chunosovd621bca2017-11-03 17:33:15 +0700480/** Return the promoted data type of a given data type.
481 *
482 * @note If promoted data type is not supported an error will be thrown
483 *
484 * @param[in] dt Data type to get the promoted type of.
485 *
486 * @return Promoted data type
487 */
488inline DataType get_promoted_data_type(DataType dt)
489{
490 switch(dt)
491 {
492 case DataType::U8:
493 return DataType::U16;
494 case DataType::S8:
495 return DataType::S16;
Chunosovd621bca2017-11-03 17:33:15 +0700496 case DataType::U16:
497 return DataType::U32;
498 case DataType::S16:
499 return DataType::S32;
Georgios Pinitas4c5469b2019-05-21 13:32:43 +0100500 case DataType::QSYMM8:
Chunosovd621bca2017-11-03 17:33:15 +0700501 case DataType::QASYMM8:
Georgios Pinitasdbdea0d2019-10-16 19:21:40 +0100502 case DataType::QASYMM8_SIGNED:
Georgios Pinitas4c5469b2019-05-21 13:32:43 +0100503 case DataType::QSYMM8_PER_CHANNEL:
Manuel Bottini3689fcd2019-06-14 17:18:12 +0100504 case DataType::QSYMM16:
Michele Di Giorgio35ea9a72019-08-23 12:02:06 +0100505 case DataType::QASYMM16:
Georgios Pinitase8291ac2020-02-26 09:58:13 +0000506 case DataType::BFLOAT16:
Chunosovd621bca2017-11-03 17:33:15 +0700507 case DataType::F16:
508 case DataType::U32:
509 case DataType::S32:
510 case DataType::F32:
Chunosovd621bca2017-11-03 17:33:15 +0700511 ARM_COMPUTE_ERROR("Unsupported data type promotions!");
512 default:
513 ARM_COMPUTE_ERROR("Undefined data type!");
514 }
515 return DataType::UNKNOWN;
516}
517
Georgios Pinitas6e1791b2019-12-02 19:01:25 +0000518/** Compute the mininum and maximum values a data type can take
519 *
520 * @param[in] dt Data type to get the min/max bounds of
521 *
522 * @return A tuple (min,max) with the minimum and maximum values respectively wrapped in PixelValue.
523 */
524inline std::tuple<PixelValue, PixelValue> get_min_max(DataType dt)
525{
Michalis Spyroue7be8a02019-12-12 16:16:09 +0000526 PixelValue min{};
527 PixelValue max{};
Georgios Pinitas6e1791b2019-12-02 19:01:25 +0000528 switch(dt)
529 {
530 case DataType::U8:
531 case DataType::QASYMM8:
532 {
Michalis Spyroue7be8a02019-12-12 16:16:09 +0000533 min = PixelValue(static_cast<int32_t>(std::numeric_limits<uint8_t>::lowest()));
534 max = PixelValue(static_cast<int32_t>(std::numeric_limits<uint8_t>::max()));
Georgios Pinitas6e1791b2019-12-02 19:01:25 +0000535 break;
536 }
537 case DataType::S8:
538 case DataType::QSYMM8:
539 case DataType::QASYMM8_SIGNED:
540 case DataType::QSYMM8_PER_CHANNEL:
541 {
Michalis Spyroue7be8a02019-12-12 16:16:09 +0000542 min = PixelValue(static_cast<int32_t>(std::numeric_limits<int8_t>::lowest()));
543 max = PixelValue(static_cast<int32_t>(std::numeric_limits<int8_t>::max()));
Georgios Pinitas6e1791b2019-12-02 19:01:25 +0000544 break;
545 }
546 case DataType::U16:
547 case DataType::QASYMM16:
548 {
Michalis Spyroue7be8a02019-12-12 16:16:09 +0000549 min = PixelValue(static_cast<int32_t>(std::numeric_limits<uint16_t>::lowest()));
550 max = PixelValue(static_cast<int32_t>(std::numeric_limits<uint16_t>::max()));
Georgios Pinitas6e1791b2019-12-02 19:01:25 +0000551 break;
552 }
553 case DataType::S16:
554 case DataType::QSYMM16:
555 {
Michalis Spyroue7be8a02019-12-12 16:16:09 +0000556 min = PixelValue(static_cast<int32_t>(std::numeric_limits<int16_t>::lowest()));
557 max = PixelValue(static_cast<int32_t>(std::numeric_limits<int16_t>::max()));
Georgios Pinitas6e1791b2019-12-02 19:01:25 +0000558 break;
559 }
560 case DataType::U32:
561 {
562 min = PixelValue(std::numeric_limits<uint32_t>::lowest());
563 max = PixelValue(std::numeric_limits<uint32_t>::max());
564 break;
565 }
566 case DataType::S32:
567 {
568 min = PixelValue(std::numeric_limits<int32_t>::lowest());
569 max = PixelValue(std::numeric_limits<int32_t>::max());
570 break;
571 }
Georgios Pinitase8291ac2020-02-26 09:58:13 +0000572 case DataType::BFLOAT16:
573 {
574 min = PixelValue(bfloat16::lowest());
575 max = PixelValue(bfloat16::max());
576 break;
577 }
Luca Foschianiee939fb2020-01-28 10:38:07 +0000578 case DataType::F16:
579 {
580 min = PixelValue(std::numeric_limits<half>::lowest());
581 max = PixelValue(std::numeric_limits<half>::max());
582 break;
583 }
Georgios Pinitas6e1791b2019-12-02 19:01:25 +0000584 case DataType::F32:
585 {
586 min = PixelValue(std::numeric_limits<float>::lowest());
587 max = PixelValue(std::numeric_limits<float>::max());
588 break;
589 }
590 default:
591 ARM_COMPUTE_ERROR("Undefined data type!");
592 }
593 return std::make_tuple(min, max);
594}
595
Ioan-Cristian Szabo9414f642017-10-27 17:35:40 +0100596/** Return true if the given format has horizontal subsampling.
597 *
598 * @param[in] format Format to determine subsampling.
599 *
600 * @return True if the format can be subsampled horizontaly.
601 */
602inline bool has_format_horizontal_subsampling(Format format)
603{
604 return (format == Format::YUYV422 || format == Format::UYVY422 || format == Format::NV12 || format == Format::NV21 || format == Format::IYUV || format == Format::UV88) ? true : false;
605}
606
607/** Return true if the given format has vertical subsampling.
608 *
609 * @param[in] format Format to determine subsampling.
610 *
611 * @return True if the format can be subsampled verticaly.
612 */
613inline bool has_format_vertical_subsampling(Format format)
614{
615 return (format == Format::NV12 || format == Format::NV21 || format == Format::IYUV || format == Format::UV88) ? true : false;
616}
617
Ioan-Cristian Szabo9414f642017-10-27 17:35:40 +0100618/** Calculate subsampled shape for a given format and channel
619 *
620 * @param[in] shape Shape of the tensor to calculate the extracted channel.
621 * @param[in] format Format of the tensor.
622 * @param[in] channel Channel to create tensor shape to be extracted.
623 *
624 * @return The subsampled tensor shape.
625 */
626inline TensorShape calculate_subsampled_shape(const TensorShape &shape, Format format, Channel channel = Channel::UNKNOWN)
627{
628 TensorShape output{ shape };
629
630 // Subsample shape only for U or V channel
631 if(Channel::U == channel || Channel::V == channel || Channel::UNKNOWN == channel)
632 {
633 // Subsample width for the tensor shape when channel is U or V
634 if(has_format_horizontal_subsampling(format))
635 {
636 output.set(0, output.x() / 2U);
637 }
638
639 // Subsample height for the tensor shape when channel is U or V
640 if(has_format_vertical_subsampling(format))
641 {
642 output.set(1, output.y() / 2U);
643 }
644 }
645
646 return output;
647}
648
Pablo Tello35767bc2018-12-05 17:36:30 +0000649/** Permutes the given dimensions according the permutation vector
650 *
651 * @param[in,out] dimensions Dimensions to be permuted.
652 * @param[in] perm Vector describing the permutation.
653 *
654 */
655template <typename T>
656inline void permute_strides(Dimensions<T> &dimensions, const PermutationVector &perm)
657{
658 const auto old_dim = utility::make_array<Dimensions<T>::num_max_dimensions>(dimensions.begin(), dimensions.end());
659 for(unsigned int i = 0; i < perm.num_dimensions(); ++i)
660 {
661 T dimension_val = old_dim[i];
662 dimensions.set(perm[i], dimension_val);
663 }
664}
665
Georgios Pinitas4074c992018-01-30 18:13:46 +0000666/** Calculate padding requirements in case of SAME padding
667 *
668 * @param[in] input_shape Input shape
669 * @param[in] weights_shape Weights shape
670 * @param[in] conv_info Convolution information (containing strides)
Isabella Gottardi6a914402019-01-30 15:45:42 +0000671 * @param[in] data_layout (Optional) Data layout of the input and weights tensor
Pablo Tello01bbacb2019-04-30 10:32:42 +0100672 * @param[in] dilation (Optional) Dilation factor used in the convolution.
Giorgio Arena17203582019-08-02 16:00:41 +0100673 * @param[in] rounding_type (Optional) Dimension rounding type when down-scaling.
Georgios Pinitas4074c992018-01-30 18:13:46 +0000674 *
675 * @return PadStrideInfo for SAME padding
676 */
Giorgio Arena17203582019-08-02 16:00:41 +0100677PadStrideInfo calculate_same_pad(TensorShape input_shape, TensorShape weights_shape, PadStrideInfo conv_info, DataLayout data_layout = DataLayout::NCHW, const Size2D &dilation = Size2D(1u, 1u),
678 const DimensionRoundingType &rounding_type = DimensionRoundingType::FLOOR);
Georgios Pinitas4074c992018-01-30 18:13:46 +0000679
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100680/** Returns expected width and height of the deconvolution's output tensor.
681 *
Matthew Jacksonb9070a42019-08-22 16:13:27 +0100682 * @param[in] in_width Width of input tensor (Number of columns)
683 * @param[in] in_height Height of input tensor (Number of rows)
684 * @param[in] kernel_width Kernel width.
685 * @param[in] kernel_height Kernel height.
686 * @param[in] pad_stride_info Pad and stride information.
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100687 *
688 * @return A pair with the new width in the first position and the new height in the second.
689 */
Pablo Tello01bbacb2019-04-30 10:32:42 +0100690std::pair<unsigned int, unsigned int> deconvolution_output_dimensions(unsigned int in_width, unsigned int in_height,
691 unsigned int kernel_width, unsigned int kernel_height,
Matthew Jacksonb9070a42019-08-22 16:13:27 +0100692 const PadStrideInfo &pad_stride_info);
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100693
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100694/** Returns expected width and height of output scaled tensor depending on dimensions rounding mode.
695 *
Gian Marco Iodice4e288692017-06-27 11:41:59 +0100696 * @param[in] width Width of input tensor (Number of columns)
697 * @param[in] height Height of input tensor (Number of rows)
698 * @param[in] kernel_width Kernel width.
699 * @param[in] kernel_height Kernel height.
700 * @param[in] pad_stride_info Pad and stride information.
Alex Gilday7da29b62018-03-23 14:16:00 +0000701 * @param[in] dilation (Optional) Dilation, in elements, across x and y. Defaults to (1, 1).
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100702 *
703 * @return A pair with the new width in the first position and the new height in the second.
704 */
Georgios Pinitas80838f12019-12-12 18:23:13 +0000705std::pair<unsigned int, unsigned int> scaled_dimensions(int width, int height,
706 int kernel_width, int kernel_height,
Pablo Tello01bbacb2019-04-30 10:32:42 +0100707 const PadStrideInfo &pad_stride_info,
708 const Size2D &dilation = Size2D(1U, 1U));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100709
Freddie Liardetafcbb8f2021-05-04 12:41:16 +0100710/** Returns calculated width and height of output scaled tensor depending on dimensions rounding mode.
711 *
712 * @param[in] width Width of input tensor (Number of columns)
713 * @param[in] height Height of input tensor (Number of rows)
714 * @param[in] kernel_width Kernel width.
715 * @param[in] kernel_height Kernel height.
716 * @param[in] pad_stride_info Pad and stride information.
717 *
718 * @return A pair with the new width in the first position and the new height in the second, returned values can be < 1
719 */
720std::pair<int, int> scaled_dimensions_signed(int width, int height,
721 int kernel_width, int kernel_height,
722 const PadStrideInfo &pad_stride_info);
723
ramelg0137515692022-02-26 22:06:20 +0000724/** Returns calculated width, height and depth of output scaled tensor depending on dimensions rounding mode.
725 *
726 * @param[in] width Width of input tensor
727 * @param[in] height Height of input tensor
728 * @param[in] depth Depth of input tensor
729 * @param[in] kernel_width Kernel width.
730 * @param[in] kernel_height Kernel height.
731 * @param[in] kernel_depth Kernel depth.
732 * @param[in] pool3d_info Pad and stride and round information for 3d pooling
733 *
734 * @return A tuple with the new width in the first position, the new height in the second, and the new depth in the third.
735 * Returned values can be < 1
736 */
737std::tuple<int, int, int> scaled_3d_dimensions_signed(int width, int height, int depth,
738 int kernel_width, int kernel_height, int kernel_depth,
739 const Pooling3dLayerInfo &pool3d_info);
740
Sang-Hoon Park2697fd82019-10-15 16:49:24 +0100741/** Check if the given reduction operation should be handled in a serial way.
742 *
743 * @param[in] op Reduction operation to perform
744 * @param[in] dt Data type
745 * @param[in] axis Axis along which to reduce
746 *
747 * @return True if the given reduction operation should be handled in a serial way.
748 */
749bool needs_serialized_reduction(ReductionOperation op, DataType dt, unsigned int axis);
750
Sang-Hoon Park0779fec2019-11-13 17:08:12 +0000751/** Returns output quantization information for softmax layer
752 *
753 * @param[in] input_type The data type of the input tensor
754 * @param[in] is_log True for log softmax
755 *
756 * @return Quantization information for the output tensor
757 */
758QuantizationInfo get_softmax_output_quantization_info(DataType input_type, bool is_log);
759
Sang-Hoon Park4715cf92020-01-08 16:02:47 +0000760/** Returns a pair of minimum and maximum values for a quantized activation
761 *
762 * @param[in] act_info The information for activation
763 * @param[in] data_type The used data type
764 * @param[in] oq_info The output quantization information
765 *
766 * @return The pair with minimum and maximum values
767 */
Matthew Benthamf1aeab92023-05-30 13:35:34 +0000768std::pair<int32_t, int32_t> get_quantized_activation_min_max(const ActivationLayerInfo& act_info, DataType data_type, UniformQuantizationInfo oq_info);
Sang-Hoon Park4715cf92020-01-08 16:02:47 +0000769
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100770/** Convert a tensor format into a string.
771 *
772 * @param[in] format @ref Format to be translated to string.
773 *
774 * @return The string describing the format.
775 */
776const std::string &string_from_format(Format format);
777
778/** Convert a channel identity into a string.
779 *
780 * @param[in] channel @ref Channel to be translated to string.
781 *
782 * @return The string describing the channel.
783 */
784const std::string &string_from_channel(Channel channel);
Michele Di Giorgiobf3c6622018-03-08 11:52:27 +0000785/** Convert a data layout identity into a string.
786 *
787 * @param[in] dl @ref DataLayout to be translated to string.
788 *
789 * @return The string describing the data layout.
790 */
791const std::string &string_from_data_layout(DataLayout dl);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100792/** Convert a data type identity into a string.
793 *
794 * @param[in] dt @ref DataType to be translated to string.
795 *
796 * @return The string describing the data type.
797 */
798const std::string &string_from_data_type(DataType dt);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100799/** Translates a given activation function to a string.
800 *
801 * @param[in] act @ref ActivationLayerInfo::ActivationFunction to be translated to string.
802 *
803 * @return The string describing the activation function.
804 */
Matthew Benthamf1aeab92023-05-30 13:35:34 +0000805const std::string &string_from_activation_func(const ActivationFunction& act);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100806/** Translates a given interpolation policy to a string.
807 *
808 * @param[in] policy @ref InterpolationPolicy to be translated to string.
809 *
810 * @return The string describing the interpolation policy.
811 */
812const std::string &string_from_interpolation_policy(InterpolationPolicy policy);
813/** Translates a given border mode policy to a string.
814 *
815 * @param[in] border_mode @ref BorderMode to be translated to string.
816 *
817 * @return The string describing the border mode.
818 */
819const std::string &string_from_border_mode(BorderMode border_mode);
820/** Translates a given normalization type to a string.
821 *
822 * @param[in] type @ref NormType to be translated to string.
823 *
824 * @return The string describing the normalization type.
825 */
826const std::string &string_from_norm_type(NormType type);
Georgios Pinitascdf51452017-08-31 14:21:36 +0100827/** Translates a given pooling type to a string.
828 *
829 * @param[in] type @ref PoolingType to be translated to string.
830 *
831 * @return The string describing the pooling type.
832 */
833const std::string &string_from_pooling_type(PoolingType type);
SiCongLic4270cf2021-12-22 11:22:40 +0000834/** Check if the pool region is entirely outside the input tensor
835 *
836 * @param[in] info @ref PoolingLayerInfo to be checked.
837 *
838 * @return True if the pool region is entirely outside the input tensor, False otherwise.
839 */
840bool is_pool_region_entirely_outside_input(const PoolingLayerInfo &info);
ramelg0137515692022-02-26 22:06:20 +0000841/** Check if the 3d pool region is entirely outside the input tensor
842 *
843 * @param[in] info @ref Pooling3dLayerInfo to be checked.
844 *
845 * @return True if the pool region is entirely outside the input tensor, False otherwise.
846 */
847bool is_pool_3d_region_entirely_outside_input(const Pooling3dLayerInfo &info);
848/** Check if the 3D padding is symmetric i.e. padding in each opposite sides are euqal (left=right, top=bottom and front=back)
849 *
850 * @param[in] info @ref Padding3D input 3D padding object to check if it is symmetric
851 *
852 * @return True if padding is symmetric
853 */
854inline bool is_symmetric(const Padding3D& info)
855{
856 return ((info.left == info.right) && (info.top == info.bottom) && (info.front == info.back));
857}
Gian Marco Iodice4b908652018-10-18 10:21:02 +0100858/** Translates a given GEMMLowp output stage to a string.
859 *
860 * @param[in] output_stage @ref GEMMLowpOutputStageInfo to be translated to string.
861 *
862 * @return The string describing the GEMMLowp output stage
863 */
864const std::string &string_from_gemmlowp_output_stage(GEMMLowpOutputStageType output_stage);
Giuseppe Rossinid7647d42018-07-17 18:13:13 +0100865/** Convert a PixelValue to a string, represented through the specific data type
866 *
867 * @param[in] value The PixelValue to convert
868 * @param[in] data_type The type to be used to convert the @p value
869 *
870 * @return String representation of the PixelValue through the given data type.
871 */
872std::string string_from_pixel_value(const PixelValue &value, const DataType data_type);
SiCong Lie357a252020-08-09 20:05:52 +0100873/** Convert a string to DataType
874 *
875 * @param[in] name The name of the data type
876 *
877 * @return DataType
878 */
879DataType data_type_from_name(const std::string &name);
Giorgio Arena1e2af2a2020-10-15 17:39:41 +0100880/** Stores padding information before configuring a kernel
881 *
Giorgio Arena4112eed2020-10-23 14:24:26 +0100882 * @param[in] infos list of tensor infos to store the padding info for
883 *
884 * @return An unordered map where each tensor info pointer is paired with its original padding info
885 */
886std::unordered_map<const ITensorInfo *, PaddingSize> get_padding_info(std::initializer_list<const ITensorInfo *> infos);
887/** Stores padding information before configuring a kernel
888 *
Giorgio Arena1e2af2a2020-10-15 17:39:41 +0100889 * @param[in] tensors list of tensors to store the padding info for
890 *
Giorgio Arena4112eed2020-10-23 14:24:26 +0100891 * @return An unordered map where each tensor info pointer is paired with its original padding info
Giorgio Arena1e2af2a2020-10-15 17:39:41 +0100892 */
Giorgio Arena4112eed2020-10-23 14:24:26 +0100893std::unordered_map<const ITensorInfo *, PaddingSize> get_padding_info(std::initializer_list<const ITensor *> tensors);
Giorgio Arena1e2af2a2020-10-15 17:39:41 +0100894/** Check if the previously stored padding info has changed after configuring a kernel
895 *
Giorgio Arena4112eed2020-10-23 14:24:26 +0100896 * @param[in] padding_map an unordered map where each tensor info pointer is paired with its original padding info
Giorgio Arena1e2af2a2020-10-15 17:39:41 +0100897 *
Giorgio Arena4112eed2020-10-23 14:24:26 +0100898 * @return true if any of the tensor infos has changed its paddings
Giorgio Arena1e2af2a2020-10-15 17:39:41 +0100899 */
Giorgio Arena4112eed2020-10-23 14:24:26 +0100900bool has_padding_changed(const std::unordered_map<const ITensorInfo *, PaddingSize> &padding_map);
Giorgio Arena1e2af2a2020-10-15 17:39:41 +0100901
SiCong Lie357a252020-08-09 20:05:52 +0100902/** Input Stream operator for @ref DataType
903 *
904 * @param[in] stream Stream to parse
905 * @param[out] data_type Output data type
906 *
907 * @return Updated stream
908 */
909inline ::std::istream &operator>>(::std::istream &stream, DataType &data_type)
910{
911 std::string value;
912 stream >> value;
913 data_type = data_type_from_name(value);
914 return stream;
915}
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100916/** Lower a given string.
917 *
918 * @param[in] val Given string to lower.
919 *
920 * @return The lowered string
921 */
922std::string lower_string(const std::string &val);
923
ramelg019cca5922021-11-11 10:05:00 +0000924/** Raise a given string to upper case
925 *
926 * @param[in] val Given string to lower.
927 *
928 * @return The upper case string
929 */
930std::string upper_string(const std::string &val);
931
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100932/** Check if a given data type is of floating point type
933 *
934 * @param[in] dt Input data type.
935 *
936 * @return True if data type is of floating point type, else false.
937 */
938inline bool is_data_type_float(DataType dt)
939{
940 switch(dt)
941 {
942 case DataType::F16:
943 case DataType::F32:
944 return true;
945 default:
946 return false;
947 }
948}
949
Georgios Pinitas05078ec2017-11-02 13:06:59 +0000950/** Check if a given data type is of quantized type
951 *
952 * @note Quantized is considered a super-set of fixed-point and asymmetric data types.
953 *
954 * @param[in] dt Input data type.
955 *
956 * @return True if data type is of quantized type, else false.
957 */
958inline bool is_data_type_quantized(DataType dt)
959{
960 switch(dt)
961 {
Georgios Pinitas4c5469b2019-05-21 13:32:43 +0100962 case DataType::QSYMM8:
Georgios Pinitas05078ec2017-11-02 13:06:59 +0000963 case DataType::QASYMM8:
Georgios Pinitasdbdea0d2019-10-16 19:21:40 +0100964 case DataType::QASYMM8_SIGNED:
Georgios Pinitas4c5469b2019-05-21 13:32:43 +0100965 case DataType::QSYMM8_PER_CHANNEL:
Manuel Bottini3689fcd2019-06-14 17:18:12 +0100966 case DataType::QSYMM16:
Michele Di Giorgio35ea9a72019-08-23 12:02:06 +0100967 case DataType::QASYMM16:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100968 return true;
969 default:
970 return false;
971 }
972}
973
Georgios Pinitas05078ec2017-11-02 13:06:59 +0000974/** Check if a given data type is of asymmetric quantized type
975 *
976 * @param[in] dt Input data type.
977 *
Michele Di Giorgio6997fc92019-06-18 10:23:22 +0100978 * @return True if data type is of asymmetric quantized type, else false.
Georgios Pinitas05078ec2017-11-02 13:06:59 +0000979 */
Anton Lokhmotovaf6204c2017-11-08 09:34:19 +0000980inline bool is_data_type_quantized_asymmetric(DataType dt)
Georgios Pinitas05078ec2017-11-02 13:06:59 +0000981{
982 switch(dt)
983 {
984 case DataType::QASYMM8:
Georgios Pinitasdbdea0d2019-10-16 19:21:40 +0100985 case DataType::QASYMM8_SIGNED:
Michele Di Giorgio35ea9a72019-08-23 12:02:06 +0100986 case DataType::QASYMM16:
Georgios Pinitas05078ec2017-11-02 13:06:59 +0000987 return true;
988 default:
989 return false;
990 }
991}
992
Georgios Pinitas6e1791b2019-12-02 19:01:25 +0000993/** Check if a given data type is of asymmetric quantized signed type
994 *
995 * @param[in] dt Input data type.
996 *
997 * @return True if data type is of asymmetric quantized signed type, else false.
998 */
999inline bool is_data_type_quantized_asymmetric_signed(DataType dt)
1000{
1001 switch(dt)
1002 {
1003 case DataType::QASYMM8_SIGNED:
1004 return true;
1005 default:
1006 return false;
1007 }
1008}
1009
Michele Di Giorgio6997fc92019-06-18 10:23:22 +01001010/** Check if a given data type is of symmetric quantized type
1011 *
1012 * @param[in] dt Input data type.
1013 *
1014 * @return True if data type is of symmetric quantized type, else false.
1015 */
1016inline bool is_data_type_quantized_symmetric(DataType dt)
1017{
1018 switch(dt)
1019 {
1020 case DataType::QSYMM8:
1021 case DataType::QSYMM8_PER_CHANNEL:
1022 case DataType::QSYMM16:
1023 return true;
1024 default:
1025 return false;
1026 }
1027}
1028
Michalis Spyrouc8530212019-08-22 11:44:04 +01001029/** Check if a given data type is of per channel type
1030 *
1031 * @param[in] dt Input data type.
1032 *
1033 * @return True if data type is of per channel type, else false.
1034 */
1035inline bool is_data_type_quantized_per_channel(DataType dt)
1036{
1037 switch(dt)
1038 {
1039 case DataType::QSYMM8_PER_CHANNEL:
Michalis Spyrouc8530212019-08-22 11:44:04 +01001040 return true;
1041 default:
1042 return false;
1043 }
1044}
1045
Georgios Pinitas89010962017-08-04 14:58:27 +01001046/** Create a string with the float in full precision.
1047 *
1048 * @param val Floating point value
1049 *
1050 * @return String with the floating point value.
1051 */
1052inline std::string float_to_string_with_full_precision(float val)
1053{
1054 std::stringstream ss;
Georgios Pinitas7900a9e2018-11-23 11:44:58 +00001055 ss.precision(std::numeric_limits<float>::max_digits10);
Georgios Pinitas89010962017-08-04 14:58:27 +01001056 ss << val;
Giorgio Arena73023022018-09-04 14:55:55 +01001057
1058 if(val != static_cast<int>(val))
1059 {
1060 ss << "f";
1061 }
1062
Georgios Pinitas89010962017-08-04 14:58:27 +01001063 return ss.str();
1064}
1065
Michalis Spyrouf63885b2019-01-16 14:18:09 +00001066/** Returns the number of elements required to go from start to end with the wanted step
1067 *
1068 * @param[in] start start value
1069 * @param[in] end end value
1070 * @param[in] step step value between each number in the wanted sequence
1071 *
1072 * @return number of elements to go from start value to end value using the wanted step
1073 */
1074inline size_t num_of_elements_in_range(const float start, const float end, const float step)
1075{
1076 ARM_COMPUTE_ERROR_ON_MSG(step == 0, "Range Step cannot be 0");
1077 return size_t(std::ceil((end - start) / step));
1078}
1079
1080/** Returns true if the value can be represented by the given data type
1081 *
Georgios Pinitas4c5469b2019-05-21 13:32:43 +01001082 * @param[in] val value to be checked
1083 * @param[in] dt data type that is checked
1084 * @param[in] qinfo (Optional) quantization info if the data type is QASYMM8
Michalis Spyrouf63885b2019-01-16 14:18:09 +00001085 *
1086 * @return true if the data type can hold the value.
1087 */
1088template <typename T>
Georgios Pinitas4c5469b2019-05-21 13:32:43 +01001089bool check_value_range(T val, DataType dt, QuantizationInfo qinfo = QuantizationInfo())
Michalis Spyrouf63885b2019-01-16 14:18:09 +00001090{
1091 switch(dt)
1092 {
1093 case DataType::U8:
Georgios Pinitase874ef92019-09-09 17:40:33 +01001094 {
1095 const auto val_u8 = static_cast<uint8_t>(val);
Georgios Pinitas41c15172021-02-22 23:43:33 +00001096 return ((val_u8 == val) && val >= std::numeric_limits<uint8_t>::lowest() && val <= std::numeric_limits<uint8_t>::max());
Georgios Pinitase874ef92019-09-09 17:40:33 +01001097 }
Michalis Spyrouf63885b2019-01-16 14:18:09 +00001098 case DataType::QASYMM8:
1099 {
Georgios Pinitas4c5469b2019-05-21 13:32:43 +01001100 double min = static_cast<double>(dequantize_qasymm8(0, qinfo));
1101 double max = static_cast<double>(dequantize_qasymm8(std::numeric_limits<uint8_t>::max(), qinfo));
Michalis Spyrouf63885b2019-01-16 14:18:09 +00001102 return ((double)val >= min && (double)val <= max);
1103 }
1104 case DataType::S8:
Georgios Pinitase874ef92019-09-09 17:40:33 +01001105 {
1106 const auto val_s8 = static_cast<int8_t>(val);
Georgios Pinitas41c15172021-02-22 23:43:33 +00001107 return ((val_s8 == val) && val >= std::numeric_limits<int8_t>::lowest() && val <= std::numeric_limits<int8_t>::max());
Georgios Pinitase874ef92019-09-09 17:40:33 +01001108 }
Michalis Spyrouf63885b2019-01-16 14:18:09 +00001109 case DataType::U16:
Georgios Pinitase874ef92019-09-09 17:40:33 +01001110 {
1111 const auto val_u16 = static_cast<uint16_t>(val);
Georgios Pinitas41c15172021-02-22 23:43:33 +00001112 return ((val_u16 == val) && val >= std::numeric_limits<uint16_t>::lowest() && val <= std::numeric_limits<uint16_t>::max());
Georgios Pinitase874ef92019-09-09 17:40:33 +01001113 }
Michalis Spyrouf63885b2019-01-16 14:18:09 +00001114 case DataType::S16:
Georgios Pinitase874ef92019-09-09 17:40:33 +01001115 {
1116 const auto val_s16 = static_cast<int16_t>(val);
Georgios Pinitas41c15172021-02-22 23:43:33 +00001117 return ((val_s16 == val) && val >= std::numeric_limits<int16_t>::lowest() && val <= std::numeric_limits<int16_t>::max());
Georgios Pinitase874ef92019-09-09 17:40:33 +01001118 }
Michalis Spyrouf63885b2019-01-16 14:18:09 +00001119 case DataType::U32:
Georgios Pinitase874ef92019-09-09 17:40:33 +01001120 {
Mohammed Suhail Munshi2134d1b2022-02-08 15:23:00 +00001121 const auto val_d64 = static_cast<double>(val);
Georgios Pinitase874ef92019-09-09 17:40:33 +01001122 const auto val_u32 = static_cast<uint32_t>(val);
Mohammed Suhail Munshi2134d1b2022-02-08 15:23:00 +00001123 return ((val_u32 == val_d64) && val_d64 >= std::numeric_limits<uint32_t>::lowest() && val_d64 <= std::numeric_limits<uint32_t>::max());
Georgios Pinitase874ef92019-09-09 17:40:33 +01001124 }
Michalis Spyrouf63885b2019-01-16 14:18:09 +00001125 case DataType::S32:
Georgios Pinitase874ef92019-09-09 17:40:33 +01001126 {
Mohammed Suhail Munshi2134d1b2022-02-08 15:23:00 +00001127 const auto val_d64 = static_cast<double>(val);
Georgios Pinitase874ef92019-09-09 17:40:33 +01001128 const auto val_s32 = static_cast<int32_t>(val);
Mohammed Suhail Munshi2134d1b2022-02-08 15:23:00 +00001129 return ((val_s32 == val_d64) && val_d64 >= std::numeric_limits<int32_t>::lowest() && val_d64 <= std::numeric_limits<int32_t>::max());
Georgios Pinitase874ef92019-09-09 17:40:33 +01001130 }
Georgios Pinitase8291ac2020-02-26 09:58:13 +00001131 case DataType::BFLOAT16:
1132 return (val >= bfloat16::lowest() && val <= bfloat16::max());
Michalis Spyrouf63885b2019-01-16 14:18:09 +00001133 case DataType::F16:
1134 return (val >= std::numeric_limits<half>::lowest() && val <= std::numeric_limits<half>::max());
1135 case DataType::F32:
1136 return (val >= std::numeric_limits<float>::lowest() && val <= std::numeric_limits<float>::max());
Michalis Spyrouf63885b2019-01-16 14:18:09 +00001137 default:
1138 ARM_COMPUTE_ERROR("Data type not supported");
1139 return false;
1140 }
1141}
1142
Giorgio Arenad304adb2020-10-02 10:20:11 +01001143/** Returns the adjusted vector size in case it is less than the input's first dimension, getting rounded down to its closest valid vector size
1144 *
1145 * @param[in] vec_size vector size to be adjusted
1146 * @param[in] dim0 size of the first dimension
1147 *
1148 * @return the number of element processed along the X axis per thread
1149 */
1150inline unsigned int adjust_vec_size(unsigned int vec_size, size_t dim0)
1151{
1152 ARM_COMPUTE_ERROR_ON(vec_size > 16);
1153
Giorgio Arena79acd772020-10-22 14:29:50 +01001154 if((vec_size >= dim0) && (dim0 == 3))
Giorgio Arenad304adb2020-10-02 10:20:11 +01001155 {
1156 return dim0;
1157 }
1158
1159 while(vec_size > dim0)
1160 {
1161 vec_size >>= 1;
1162 }
1163
1164 return vec_size;
1165}
1166
Giorgio Arena5ae8d802021-11-18 18:02:13 +00001167/** Returns the suffix string of CPU kernel implementation names based on the given data type
1168 *
1169 * @param[in] data_type The data type the CPU kernel implemetation uses
1170 *
1171 * @return the suffix string of CPU kernel implementations
1172 */
1173inline std::string cpu_impl_dt(const DataType &data_type)
1174{
1175 std::string ret = "";
1176
1177 switch(data_type)
1178 {
1179 case DataType::F32:
1180 ret = "fp32";
1181 break;
1182 case DataType::F16:
1183 ret = "fp16";
1184 break;
1185 case DataType::U8:
1186 ret = "u8";
1187 break;
1188 case DataType::S16:
1189 ret = "s16";
1190 break;
1191 case DataType::S32:
1192 ret = "s32";
1193 break;
1194 case DataType::QASYMM8:
1195 ret = "qu8";
1196 break;
1197 case DataType::QASYMM8_SIGNED:
1198 ret = "qs8";
1199 break;
1200 case DataType::QSYMM16:
1201 ret = "qs16";
1202 break;
Dana Zlotnikebbae942022-02-03 12:52:15 +02001203 case DataType::QSYMM8_PER_CHANNEL:
1204 ret = "qp8";
1205 break;
Yair Schwarzbaum298b2c02022-02-01 08:55:56 +02001206 case DataType::BFLOAT16:
1207 ret = "bf16";
1208 break;
Giorgio Arena5ae8d802021-11-18 18:02:13 +00001209 default:
1210 ARM_COMPUTE_ERROR("Unsupported.");
1211 }
1212
1213 return ret;
1214}
1215
giuros01edc21e42018-11-16 14:45:31 +00001216#ifdef ARM_COMPUTE_ASSERTS_ENABLED
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001217/** Print consecutive elements to an output stream.
1218 *
1219 * @param[out] s Output stream to print the elements to.
1220 * @param[in] ptr Pointer to print the elements from.
1221 * @param[in] n Number of elements to print.
1222 * @param[in] stream_width (Optional) Width of the stream. If set to 0 the element's width is used. Defaults to 0.
1223 * @param[in] element_delim (Optional) Delimeter among the consecutive elements. Defaults to space delimeter
1224 */
1225template <typename T>
1226void print_consecutive_elements_impl(std::ostream &s, const T *ptr, unsigned int n, int stream_width = 0, const std::string &element_delim = " ")
1227{
1228 using print_type = typename std::conditional<std::is_floating_point<T>::value, T, int>::type;
Michalis Spyrou53860dd2019-07-01 14:20:56 +01001229 std::ios stream_status(nullptr);
1230 stream_status.copyfmt(s);
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001231
1232 for(unsigned int i = 0; i < n; ++i)
1233 {
1234 // Set stream width as it is not a "sticky" stream manipulator
1235 if(stream_width != 0)
1236 {
1237 s.width(stream_width);
1238 }
Anthony Barbier7068f992017-10-26 15:23:08 +01001239
1240 if(std::is_same<typename std::decay<T>::type, half>::value)
1241 {
1242 // 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.
1243 s << std::right << static_cast<T>(ptr[i]) << element_delim;
1244 }
Georgios Pinitase8291ac2020-02-26 09:58:13 +00001245 else if(std::is_same<typename std::decay<T>::type, bfloat16>::value)
1246 {
Georgios Pinitasc7b183a2020-03-06 18:12:09 +00001247 // We use T instead of print_type here is because the std::is_floating_point<bfloat16> returns false and then the print_type becomes int.
Georgios Pinitase8291ac2020-02-26 09:58:13 +00001248 s << std::right << float(ptr[i]) << element_delim;
1249 }
Anthony Barbier7068f992017-10-26 15:23:08 +01001250 else
1251 {
1252 s << std::right << static_cast<print_type>(ptr[i]) << element_delim;
1253 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001254 }
Michalis Spyrou53860dd2019-07-01 14:20:56 +01001255
1256 // Restore output stream flags
1257 s.copyfmt(stream_status);
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001258}
1259
1260/** Identify the maximum width of n consecutive elements.
1261 *
1262 * @param[in] s The output stream which will be used to print the elements. Used to extract the stream format.
1263 * @param[in] ptr Pointer to the elements.
1264 * @param[in] n Number of elements.
1265 *
1266 * @return The maximum width of the elements.
1267 */
1268template <typename T>
1269int max_consecutive_elements_display_width_impl(std::ostream &s, const T *ptr, unsigned int n)
1270{
1271 using print_type = typename std::conditional<std::is_floating_point<T>::value, T, int>::type;
1272
1273 int max_width = -1;
1274 for(unsigned int i = 0; i < n; ++i)
1275 {
1276 std::stringstream ss;
1277 ss.copyfmt(s);
Anthony Barbier7068f992017-10-26 15:23:08 +01001278
1279 if(std::is_same<typename std::decay<T>::type, half>::value)
1280 {
1281 // 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.
1282 ss << static_cast<T>(ptr[i]);
1283 }
Georgios Pinitase8291ac2020-02-26 09:58:13 +00001284 else if(std::is_same<typename std::decay<T>::type, bfloat16>::value)
1285 {
1286 // We use T instead of print_type here is because the std::is_floating_point<bfloat> returns false and then the print_type becomes int.
1287 ss << float(ptr[i]);
1288 }
Anthony Barbier7068f992017-10-26 15:23:08 +01001289 else
1290 {
1291 ss << static_cast<print_type>(ptr[i]);
1292 }
1293
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001294 max_width = std::max<int>(max_width, ss.str().size());
1295 }
1296 return max_width;
1297}
1298
1299/** Print consecutive elements to an output stream.
1300 *
1301 * @param[out] s Output stream to print the elements to.
1302 * @param[in] dt Data type of the elements
1303 * @param[in] ptr Pointer to print the elements from.
1304 * @param[in] n Number of elements to print.
1305 * @param[in] stream_width (Optional) Width of the stream. If set to 0 the element's width is used. Defaults to 0.
1306 * @param[in] element_delim (Optional) Delimeter among the consecutive elements. Defaults to space delimeter
1307 */
1308void print_consecutive_elements(std::ostream &s, DataType dt, const uint8_t *ptr, unsigned int n, int stream_width, const std::string &element_delim = " ");
1309
1310/** Identify the maximum width of n consecutive elements.
1311 *
1312 * @param[in] s Output stream to print the elements to.
1313 * @param[in] dt Data type of the elements
1314 * @param[in] ptr Pointer to print the elements from.
1315 * @param[in] n Number of elements to print.
1316 *
1317 * @return The maximum width of the elements.
1318 */
1319int max_consecutive_elements_display_width(std::ostream &s, DataType dt, const uint8_t *ptr, unsigned int n);
giuros01edc21e42018-11-16 14:45:31 +00001320#endif /* ARM_COMPUTE_ASSERTS_ENABLED */
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001321}
Michalis Spyrouf4643372019-11-29 16:17:13 +00001322#endif /*ARM_COMPUTE_UTILS_H */