| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // SPDX-FileCopyrightText: 2023 - 2025 Arm Limited and/or its affiliates <open-source-office@arm.com> | ||
| 2 | // | ||
| 3 | // SPDX-License-Identifier: Apache-2.0 | ||
| 4 | |||
| 5 | #ifndef KLEIDICV_UTILS_H | ||
| 6 | #define KLEIDICV_UTILS_H | ||
| 7 | |||
| 8 | #include <algorithm> | ||
| 9 | #include <limits> | ||
| 10 | #include <type_traits> | ||
| 11 | |||
| 12 | #include "kleidicv/config.h" | ||
| 13 | #include "kleidicv/ctypes.h" | ||
| 14 | #include "kleidicv/kleidicv.h" | ||
| 15 | #include "kleidicv/traits.h" | ||
| 16 | |||
| 17 | namespace KLEIDICV_TARGET_NAMESPACE { | ||
| 18 | |||
| 19 | // Saturating cast from signed to unsigned type. | ||
| 20 | template <typename S, typename U, | ||
| 21 | std::enable_if_t<std::numeric_limits<S>::is_signed, bool> = true, | ||
| 22 | std::enable_if_t<not std::numeric_limits<U>::is_signed, bool> = true> | ||
| 23 | 482424 | static U saturating_cast(S value) KLEIDICV_STREAMING { | |
| 24 |
2/2✓ Branch 0 taken 88017 times.
✓ Branch 1 taken 394407 times.
|
482424 | if (value > std::numeric_limits<U>::max()) { |
| 25 | 88017 | return std::numeric_limits<U>::max(); | |
| 26 | } | ||
| 27 |
2/2✓ Branch 0 taken 307181 times.
✓ Branch 1 taken 87226 times.
|
394407 | if (value < 0) { |
| 28 | 87226 | return 0; | |
| 29 | } | ||
| 30 | |||
| 31 | 307181 | return static_cast<U>(value); | |
| 32 | 482424 | } | |
| 33 | |||
| 34 | // Saturating cast from unsigned to unsigned type. | ||
| 35 | template < | ||
| 36 | typename SrcType, typename DstType, | ||
| 37 | std::enable_if_t<std::is_unsigned_v<DstType> && std::is_unsigned_v<SrcType>, | ||
| 38 | bool> = true> | ||
| 39 | 1292 | static DstType saturating_cast(SrcType value) KLEIDICV_STREAMING { | |
| 40 | 1292 | return static_cast<DstType>(value); | |
| 41 | } | ||
| 42 | |||
| 43 | // Saturating cast from unsigned to signed type. | ||
| 44 | template < | ||
| 45 | typename SrcType, typename DstType, | ||
| 46 | std::enable_if_t<std::is_signed_v<DstType> && std::is_unsigned_v<SrcType>, | ||
| 47 | bool> = true> | ||
| 48 | 1626 | static DstType saturating_cast(SrcType value) KLEIDICV_STREAMING { | |
| 49 | 1626 | DstType max_value = std::numeric_limits<DstType>::max(); | |
| 50 | |||
| 51 |
6/6✓ Branch 0 taken 212 times.
✓ Branch 1 taken 850 times.
✓ Branch 2 taken 69 times.
✓ Branch 3 taken 321 times.
✓ Branch 4 taken 34 times.
✓ Branch 5 taken 140 times.
|
1626 | if (value > static_cast<SrcType>(max_value)) { |
| 52 | 315 | return max_value; | |
| 53 | } | ||
| 54 | |||
| 55 | 1311 | return static_cast<DstType>(value); | |
| 56 | 1626 | } | |
| 57 | |||
| 58 | // Rounding shift right. | ||
| 59 | template <typename T> | ||
| 60 | 446800 | static T rounding_shift_right(T value, size_t shift) KLEIDICV_STREAMING { | |
| 61 | 446800 | return (value + (T{1} << (shift - 1))) >> shift; | |
| 62 | } | ||
| 63 | |||
| 64 | // When placed in a loop, it effectively disables loop vectorization. | ||
| 65 | 834542 | static inline void disable_loop_vectorization() KLEIDICV_STREAMING { | |
| 66 | 834542 | __asm__(""); | |
| 67 | 834542 | } | |
| 68 | |||
| 69 | // Helper class to unroll a loop as needed. | ||
| 70 | class LoopUnroll final { | ||
| 71 | public: | ||
| 72 | 62578 | explicit LoopUnroll(size_t length, size_t step) KLEIDICV_STREAMING | |
| 73 | 62578 | : length_(length), | |
| 74 | 62578 | step_(step), | |
| 75 | 62578 | index_(0), | |
| 76 | 62578 | can_avoid_tail_(length >= step) {} | |
| 77 | |||
| 78 | // Loop unrolled four times. | ||
| 79 | template <typename CallbackType> | ||
| 80 | LoopUnroll &unroll_four_times(CallbackType callback) KLEIDICV_STREAMING { | ||
| 81 | return unroll_n_times<4>(callback); | ||
| 82 | } | ||
| 83 | |||
| 84 | // Loop unrolled twice. | ||
| 85 | template <typename CallbackType> | ||
| 86 | 37018 | LoopUnroll &unroll_twice(CallbackType callback) KLEIDICV_STREAMING { | |
| 87 | 37018 | return unroll_n_times<2>(callback); | |
| 88 | } | ||
| 89 | |||
| 90 | // Unrolls the loop twice, if enabled. | ||
| 91 | template <bool Enable, typename CallbackType> | ||
| 92 | 35230 | LoopUnroll &unroll_twice_if([[maybe_unused]] CallbackType callback) | |
| 93 | KLEIDICV_STREAMING { | ||
| 94 | if constexpr (Enable) { | ||
| 95 | 35230 | return unroll_twice(callback); | |
| 96 | } | ||
| 97 | |||
| 98 | return *this; | ||
| 99 | } | ||
| 100 | |||
| 101 | // Loop unrolled once. | ||
| 102 | template <typename CallbackType> | ||
| 103 | 15991 | LoopUnroll &unroll_once(CallbackType callback) KLEIDICV_STREAMING { | |
| 104 | 15991 | return unroll_n_times<1>(callback); | |
| 105 | } | ||
| 106 | |||
| 107 | // Unrolls the loop once, if enabled. | ||
| 108 | template <bool Enable, typename CallbackType> | ||
| 109 | 4328 | LoopUnroll &unroll_once_if([[maybe_unused]] CallbackType callback) | |
| 110 | KLEIDICV_STREAMING { | ||
| 111 | if constexpr (Enable) { | ||
| 112 | 4328 | return unroll_once(callback); | |
| 113 | } | ||
| 114 | |||
| 115 | return *this; | ||
| 116 | } | ||
| 117 | |||
| 118 | // Processes trailing data. | ||
| 119 | template <typename CallbackType> | ||
| 120 | 7582 | LoopUnroll &tail(CallbackType callback) KLEIDICV_STREAMING { | |
| 121 |
16/16✓ Branch 0 taken 40 times.
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 56 times.
✓ Branch 4 taken 2072 times.
✓ Branch 5 taken 2637 times.
✓ Branch 6 taken 1000 times.
✓ Branch 7 taken 1415 times.
✓ Branch 8 taken 40 times.
✓ Branch 9 taken 58 times.
✓ Branch 10 taken 1499 times.
✓ Branch 11 taken 1965 times.
✓ Branch 12 taken 112 times.
✓ Branch 13 taken 178 times.
✓ Branch 14 taken 839 times.
✓ Branch 15 taken 1225 times.
|
13224 | for (index_ = 0; index_ < remaining_length(); ++index_) { |
| 122 | 5642 | disable_loop_vectorization(); | |
| 123 | 5642 | callback(index_); | |
| 124 | 5642 | } | |
| 125 | |||
| 126 | 7582 | length_ = 0; | |
| 127 | 7582 | return *this; | |
| 128 | } | ||
| 129 | |||
| 130 | // Processes all remaining data at once. | ||
| 131 | template <typename CallbackType> | ||
| 132 | 50478 | LoopUnroll &remaining(CallbackType callback) KLEIDICV_STREAMING { | |
| 133 |
24/24✓ Branch 0 taken 1894 times.
✓ Branch 1 taken 16638 times.
✓ Branch 2 taken 1164 times.
✓ Branch 3 taken 6533 times.
✓ Branch 4 taken 984 times.
✓ Branch 5 taken 5710 times.
✓ Branch 6 taken 1066 times.
✓ Branch 7 taken 5108 times.
✓ Branch 8 taken 770 times.
✓ Branch 9 taken 3379 times.
✓ Branch 10 taken 511 times.
✓ Branch 11 taken 2479 times.
✓ Branch 12 taken 470 times.
✓ Branch 13 taken 1172 times.
✓ Branch 14 taken 452 times.
✓ Branch 15 taken 980 times.
✓ Branch 16 taken 8 times.
✓ Branch 17 taken 376 times.
✓ Branch 18 taken 24 times.
✓ Branch 19 taken 120 times.
✓ Branch 20 taken 8 times.
✓ Branch 21 taken 248 times.
✓ Branch 22 taken 8 times.
✓ Branch 23 taken 376 times.
|
50478 | if (length_) { |
| 134 | 43119 | callback(length_, step_); | |
| 135 | 43119 | length_ = 0; | |
| 136 | 43119 | } | |
| 137 | |||
| 138 | 50478 | return *this; | |
| 139 | } | ||
| 140 | |||
| 141 | // Returns true if there is nothing left to process. | ||
| 142 | bool empty() const KLEIDICV_STREAMING { return length_ == 0; } | ||
| 143 | |||
| 144 | // Returns the step value. | ||
| 145 | 2928 | size_t step() const KLEIDICV_STREAMING { return step_; } | |
| 146 | |||
| 147 | // Returns the remaining length. | ||
| 148 | 75281 | size_t remaining_length() const KLEIDICV_STREAMING { return length_; } | |
| 149 | |||
| 150 | // Returns true if it is possible to avoid the tail loop. | ||
| 151 | bool can_avoid_tail() const KLEIDICV_STREAMING { return can_avoid_tail_; } | ||
| 152 | |||
| 153 | // Instructs the loop logic to prepare to avoid the tail loop. | ||
| 154 | void avoid_tail() KLEIDICV_STREAMING { length_ = step(); } | ||
| 155 | |||
| 156 | template <const size_t UnrollFactor, typename CallbackType> | ||
| 157 | 58757 | LoopUnroll &unroll_n_times(CallbackType callback) KLEIDICV_STREAMING { | |
| 158 | 58757 | const size_t step = UnrollFactor * step_; | |
| 159 | // In practice step will never be zero and we don't want to spend | ||
| 160 | // instructions on checking that. | ||
| 161 | // NOLINTBEGIN(clang-analyzer-core.DivideZero) | ||
| 162 | 58757 | const size_t max_index = remaining_length() / step; | |
| 163 | // NOLINTEND(clang-analyzer-core.DivideZero) | ||
| 164 | |||
| 165 |
24/24✓ Branch 0 taken 468419 times.
✓ Branch 1 taken 20998 times.
✓ Branch 2 taken 37531 times.
✓ Branch 3 taken 7215 times.
✓ Branch 4 taken 31048 times.
✓ Branch 5 taken 6857 times.
✓ Branch 6 taken 34386 times.
✓ Branch 7 taken 8540 times.
✓ Branch 8 taken 25440 times.
✓ Branch 9 taken 4152 times.
✓ Branch 10 taken 22564 times.
✓ Branch 11 taken 3623 times.
✓ Branch 12 taken 16136 times.
✓ Branch 13 taken 3547 times.
✓ Branch 14 taken 15599 times.
✓ Branch 15 taken 2657 times.
✓ Branch 16 taken 1040 times.
✓ Branch 17 taken 384 times.
✓ Branch 18 taken 400 times.
✓ Branch 19 taken 144 times.
✓ Branch 20 taken 720 times.
✓ Branch 21 taken 256 times.
✓ Branch 22 taken 1040 times.
✓ Branch 23 taken 384 times.
|
713080 | for (index_ = 0; index_ < max_index; ++index_) { |
| 166 | 654323 | callback(step); | |
| 167 | 654323 | } | |
| 168 | |||
| 169 | // Adjust length to reflect the processed data. | ||
| 170 | 58757 | length_ -= step * index_; | |
| 171 | 58757 | return *this; | |
| 172 | 58757 | } | |
| 173 | |||
| 174 | // Instructs the loop logic to avoid the tail loop. | ||
| 175 | template <typename CallbackType> | ||
| 176 | 1666 | bool try_avoid_tail_loop(CallbackType callback) KLEIDICV_STREAMING { | |
| 177 |
8/8✓ Branch 0 taken 290 times.
✓ Branch 1 taken 242 times.
✓ Branch 2 taken 248 times.
✓ Branch 3 taken 130 times.
✓ Branch 4 taken 248 times.
✓ Branch 5 taken 130 times.
✓ Branch 6 taken 248 times.
✓ Branch 7 taken 130 times.
|
1666 | if (KLEIDICV_UNLIKELY(!can_avoid_tail_)) { |
| 178 | 1034 | return false; | |
| 179 | } | ||
| 180 | |||
| 181 |
8/8✓ Branch 0 taken 150 times.
✓ Branch 1 taken 92 times.
✓ Branch 2 taken 74 times.
✓ Branch 3 taken 56 times.
✓ Branch 4 taken 74 times.
✓ Branch 5 taken 56 times.
✓ Branch 6 taken 74 times.
✓ Branch 7 taken 56 times.
|
632 | if (KLEIDICV_UNLIKELY(!remaining_length())) { |
| 182 | 372 | return false; | |
| 183 | } | ||
| 184 | |||
| 185 | 260 | callback(step() - remaining_length()); | |
| 186 | 260 | length_ = step(); | |
| 187 | 260 | return true; | |
| 188 | 1666 | } | |
| 189 | |||
| 190 | private: | ||
| 191 | size_t length_; | ||
| 192 | size_t step_; | ||
| 193 | size_t index_; | ||
| 194 | bool can_avoid_tail_; | ||
| 195 | }; // end of class LoopUnroll | ||
| 196 | |||
| 197 | // This is the same as LoopUnroll, except that it passes indices to callbacks. | ||
| 198 | template <class Tail = UsesTailPath> | ||
| 199 | class LoopUnroll2 final { | ||
| 200 | public: | ||
| 201 | 705384 | explicit LoopUnroll2(size_t length, size_t step) KLEIDICV_STREAMING | |
| 202 | 705384 | : length_(length), | |
| 203 | 705384 | step_(step), | |
| 204 | 705384 | index_(0) {} | |
| 205 | |||
| 206 | 384 | explicit LoopUnroll2(size_t start_index, size_t length, | |
| 207 | size_t step) KLEIDICV_STREAMING | ||
| 208 | 384 | : length_(length), | |
| 209 | 384 | step_(step), | |
| 210 | 384 | index_(std::min(start_index, length)) {} | |
| 211 | |||
| 212 | // Loop unrolled four times. | ||
| 213 | template <typename CallbackType> | ||
| 214 | 58860 | LoopUnroll2 &unroll_four_times(CallbackType callback) KLEIDICV_STREAMING { | |
| 215 | 58860 | return unroll_n_times<4>(callback); | |
| 216 | } | ||
| 217 | |||
| 218 | // Loop unrolled twice. | ||
| 219 | template <typename CallbackType> | ||
| 220 | 531588 | KLEIDICV_FORCE_INLINE LoopUnroll2 &unroll_twice(CallbackType callback) | |
| 221 | KLEIDICV_STREAMING { | ||
| 222 | 531588 | return unroll_n_times<2>(callback); | |
| 223 | } | ||
| 224 | |||
| 225 | // Unrolls the loop twice, if enabled. | ||
| 226 | template <bool Enable, typename CallbackType> | ||
| 227 | LoopUnroll2 &unroll_twice_if(CallbackType callback) KLEIDICV_STREAMING { | ||
| 228 | if constexpr (Enable) { | ||
| 229 | return unroll_twice(callback); | ||
| 230 | } | ||
| 231 | |||
| 232 | return *this; | ||
| 233 | } | ||
| 234 | |||
| 235 | // Loop unrolled once. | ||
| 236 | template <typename CallbackType> | ||
| 237 | 336963 | KLEIDICV_FORCE_INLINE LoopUnroll2 &unroll_once(CallbackType callback) | |
| 238 | KLEIDICV_STREAMING { | ||
| 239 | 336963 | return unroll_n_times<1>(callback); | |
| 240 | } | ||
| 241 | |||
| 242 | // Unrolls the loop once, if enabled. | ||
| 243 | template <bool Enable, typename CallbackType> | ||
| 244 | LoopUnroll2 &unroll_once_if(CallbackType callback) KLEIDICV_STREAMING { | ||
| 245 | if constexpr (Enable) { | ||
| 246 | return unroll_once(callback); | ||
| 247 | } | ||
| 248 | |||
| 249 | return *this; | ||
| 250 | } | ||
| 251 | |||
| 252 | // Processes trailing data. | ||
| 253 | template <typename CallbackType> | ||
| 254 | 82176 | LoopUnroll2 &tail(CallbackType callback) KLEIDICV_STREAMING { | |
| 255 |
50/56✓ Branch 0 taken 89133 times.
✓ Branch 1 taken 22289 times.
✓ Branch 2 taken 44501 times.
✓ Branch 3 taken 18804 times.
✓ Branch 4 taken 44475 times.
✓ Branch 5 taken 14075 times.
✓ Branch 6 taken 30133 times.
✓ Branch 7 taken 13236 times.
✓ Branch 8 taken 1744 times.
✓ Branch 9 taken 716 times.
✓ Branch 10 taken 112 times.
✓ Branch 11 taken 250 times.
✓ Branch 12 taken 3696 times.
✓ Branch 13 taken 1290 times.
✓ Branch 14 taken 1396 times.
✓ Branch 15 taken 1220 times.
✓ Branch 16 taken 2240 times.
✓ Branch 17 taken 970 times.
✓ Branch 18 taken 684 times.
✓ Branch 19 taken 504 times.
✓ Branch 20 taken 1300 times.
✓ Branch 21 taken 1466 times.
✓ Branch 22 taken 976 times.
✓ Branch 23 taken 786 times.
✓ Branch 24 taken 492 times.
✓ Branch 25 taken 552 times.
✓ Branch 26 taken 520 times.
✓ Branch 27 taken 120 times.
✓ Branch 28 taken 432 times.
✓ Branch 29 taken 890 times.
✓ Branch 30 taken 1384 times.
✓ Branch 31 taken 854 times.
✓ Branch 32 taken 148 times.
✓ Branch 33 taken 170 times.
✓ Branch 34 taken 388 times.
✓ Branch 35 taken 172 times.
✓ Branch 36 taken 196 times.
✓ Branch 37 taken 448 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 416 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 64 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 32 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 308 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 416 times.
✓ Branch 48 taken 168 times.
✓ Branch 49 taken 514 times.
✓ Branch 50 taken 4 times.
✓ Branch 51 taken 48 times.
✓ Branch 52 taken 272 times.
✓ Branch 53 taken 818 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 748 times.
|
306570 | while (index_ < length_) { |
| 256 | 224394 | disable_loop_vectorization(); | |
| 257 | 224394 | callback(index_++); | |
| 258 | } | ||
| 259 | |||
| 260 | 82176 | return *this; | |
| 261 | } | ||
| 262 | |||
| 263 | // Processes all remaining data at once. | ||
| 264 | template <typename CallbackType> | ||
| 265 | 579360 | LoopUnroll2 &remaining(CallbackType callback) KLEIDICV_STREAMING { | |
| 266 |
64/64✓ Branch 0 taken 3446 times.
✓ Branch 1 taken 90864 times.
✓ Branch 2 taken 8892 times.
✓ Branch 3 taken 81141 times.
✓ Branch 4 taken 1378 times.
✓ Branch 5 taken 66369 times.
✓ Branch 6 taken 11294 times.
✓ Branch 7 taken 72058 times.
✓ Branch 8 taken 1474 times.
✓ Branch 9 taken 17006 times.
✓ Branch 10 taken 10184 times.
✓ Branch 11 taken 14334 times.
✓ Branch 12 taken 1162 times.
✓ Branch 13 taken 7594 times.
✓ Branch 14 taken 21484 times.
✓ Branch 15 taken 11344 times.
✓ Branch 16 taken 1920 times.
✓ Branch 17 taken 10850 times.
✓ Branch 18 taken 660 times.
✓ Branch 19 taken 10438 times.
✓ Branch 20 taken 1464 times.
✓ Branch 21 taken 8888 times.
✓ Branch 22 taken 1950 times.
✓ Branch 23 taken 11960 times.
✓ Branch 24 taken 2476 times.
✓ Branch 25 taken 12798 times.
✓ Branch 26 taken 1102 times.
✓ Branch 27 taken 9262 times.
✓ Branch 28 taken 2116 times.
✓ Branch 29 taken 8642 times.
✓ Branch 30 taken 2278 times.
✓ Branch 31 taken 10424 times.
✓ Branch 32 taken 104 times.
✓ Branch 33 taken 2702 times.
✓ Branch 34 taken 142 times.
✓ Branch 35 taken 7168 times.
✓ Branch 36 taken 478 times.
✓ Branch 37 taken 3162 times.
✓ Branch 38 taken 796 times.
✓ Branch 39 taken 7768 times.
✓ Branch 40 taken 104 times.
✓ Branch 41 taken 2384 times.
✓ Branch 42 taken 52 times.
✓ Branch 43 taken 6940 times.
✓ Branch 44 taken 478 times.
✓ Branch 45 taken 2742 times.
✓ Branch 46 taken 676 times.
✓ Branch 47 taken 7468 times.
✓ Branch 48 taken 896 times.
✓ Branch 49 taken 784 times.
✓ Branch 50 taken 176 times.
✓ Branch 51 taken 114 times.
✓ Branch 52 taken 1310 times.
✓ Branch 53 taken 1282 times.
✓ Branch 54 taken 1178 times.
✓ Branch 55 taken 1212 times.
✓ Branch 56 taken 866 times.
✓ Branch 57 taken 2128 times.
✓ Branch 58 taken 866 times.
✓ Branch 59 taken 2136 times.
✓ Branch 60 taken 866 times.
✓ Branch 61 taken 2128 times.
✓ Branch 62 taken 866 times.
✓ Branch 63 taken 2136 times.
|
579360 | if (remaining_length()) { |
| 267 | 496226 | callback(index_, length_); | |
| 268 | 496226 | index_ = length_; | |
| 269 | 496226 | } | |
| 270 | |||
| 271 | 579360 | return *this; | |
| 272 | } | ||
| 273 | |||
| 274 | // Returns true if there is nothing left to process. | ||
| 275 | bool empty() const KLEIDICV_STREAMING { return length_ == index_; } | ||
| 276 | |||
| 277 | // Returns the step value. | ||
| 278 | 927411 | size_t step() const KLEIDICV_STREAMING { return step_; } | |
| 279 | |||
| 280 | // Returns the remaining length. | ||
| 281 | 1661345 | size_t remaining_length() const KLEIDICV_STREAMING { | |
| 282 | 1661345 | return length_ - index_; | |
| 283 | } | ||
| 284 | |||
| 285 | private: | ||
| 286 | template <const size_t UnrollFactor, typename CallbackType> | ||
| 287 | 927411 | KLEIDICV_FORCE_INLINE LoopUnroll2 &unroll_n_times(CallbackType callback) | |
| 288 | KLEIDICV_STREAMING { | ||
| 289 | 927411 | const size_t n_step = UnrollFactor * step(); | |
| 290 | 927411 | size_t max_index = index_ + (remaining_length() / n_step) * n_step; | |
| 291 | |||
| 292 | // A tail mechanism is built into the single vector processing loop, if | ||
| 293 | // enabled. The single vector path is executed iteratively, and at the end | ||
| 294 | // it rewinds the loop to one vector before the end of the data, and | ||
| 295 | // executes one final vector path, so the scalar path can be omitted. | ||
| 296 | if constexpr (try_to_avoid_tail_loop<Tail> && (UnrollFactor == 1)) { | ||
| 297 | // Enter this loop only if there's enough data for a full vector | ||
| 298 |
60/64✓ Branch 0 taken 3717 times.
✓ Branch 1 taken 3862 times.
✓ Branch 2 taken 2271 times.
✓ Branch 3 taken 4243 times.
✓ Branch 4 taken 3300 times.
✓ Branch 5 taken 1795 times.
✓ Branch 6 taken 2581 times.
✓ Branch 7 taken 6597 times.
✓ Branch 8 taken 564 times.
✓ Branch 9 taken 456 times.
✓ Branch 10 taken 142 times.
✓ Branch 11 taken 10212 times.
✓ Branch 12 taken 840 times.
✓ Branch 13 taken 712 times.
✓ Branch 14 taken 756 times.
✓ Branch 15 taken 20408 times.
✓ Branch 16 taken 506 times.
✓ Branch 17 taken 5676 times.
✓ Branch 18 taken 364 times.
✓ Branch 19 taken 406 times.
✓ Branch 20 taken 460 times.
✓ Branch 21 taken 2284 times.
✓ Branch 22 taken 960 times.
✓ Branch 23 taken 702 times.
✓ Branch 24 taken 416 times.
✓ Branch 25 taken 11442 times.
✓ Branch 26 taken 50 times.
✓ Branch 27 taken 3158 times.
✓ Branch 28 taken 516 times.
✓ Branch 29 taken 6122 times.
✓ Branch 30 taken 528 times.
✓ Branch 31 taken 3414 times.
✓ Branch 32 taken 90 times.
✓ Branch 33 taken 88 times.
✓ Branch 34 taken 98 times.
✓ Branch 35 taken 48 times.
✓ Branch 36 taken 188 times.
✓ Branch 37 taken 268 times.
✓ Branch 38 taken 316 times.
✓ Branch 39 taken 248 times.
✓ Branch 40 taken 32 times.
✓ Branch 41 taken 40 times.
✓ Branch 42 taken 16 times.
✓ Branch 43 taken 24 times.
✓ Branch 44 taken 144 times.
✓ Branch 45 taken 172 times.
✓ Branch 46 taken 208 times.
✓ Branch 47 taken 216 times.
✓ Branch 48 taken 318 times.
✓ Branch 49 taken 334 times.
✓ Branch 50 taken 20 times.
✓ Branch 51 taken 174 times.
✓ Branch 52 taken 450 times.
✓ Branch 53 taken 506 times.
✓ Branch 54 taken 336 times.
✓ Branch 55 taken 558 times.
✗ Branch 56 not taken.
✓ Branch 57 taken 2994 times.
✗ Branch 58 not taken.
✓ Branch 59 taken 3002 times.
✗ Branch 60 not taken.
✓ Branch 61 taken 2994 times.
✗ Branch 62 not taken.
✓ Branch 63 taken 3002 times.
|
116344 | if (length_ >= n_step) { |
| 299 | // External loop only ends when all data has been processed | ||
| 300 |
64/64✓ Branch 0 taken 5428 times.
✓ Branch 1 taken 3862 times.
✓ Branch 2 taken 6978 times.
✓ Branch 3 taken 4243 times.
✓ Branch 4 taken 3450 times.
✓ Branch 5 taken 1795 times.
✓ Branch 6 taken 10022 times.
✓ Branch 7 taken 6597 times.
✓ Branch 8 taken 872 times.
✓ Branch 9 taken 456 times.
✓ Branch 10 taken 15324 times.
✓ Branch 11 taken 10212 times.
✓ Branch 12 taken 1352 times.
✓ Branch 13 taken 712 times.
✓ Branch 14 taken 30476 times.
✓ Branch 15 taken 20408 times.
✓ Branch 16 taken 10142 times.
✓ Branch 17 taken 5676 times.
✓ Branch 18 taken 462 times.
✓ Branch 19 taken 406 times.
✓ Branch 20 taken 4086 times.
✓ Branch 21 taken 2284 times.
✓ Branch 22 taken 1006 times.
✓ Branch 23 taken 702 times.
✓ Branch 24 taken 20698 times.
✓ Branch 25 taken 11442 times.
✓ Branch 26 taken 4710 times.
✓ Branch 27 taken 3158 times.
✓ Branch 28 taken 10836 times.
✓ Branch 29 taken 6122 times.
✓ Branch 30 taken 5214 times.
✓ Branch 31 taken 3414 times.
✓ Branch 32 taken 168 times.
✓ Branch 33 taken 88 times.
✓ Branch 34 taken 68 times.
✓ Branch 35 taken 48 times.
✓ Branch 36 taken 490 times.
✓ Branch 37 taken 268 times.
✓ Branch 38 taken 412 times.
✓ Branch 39 taken 248 times.
✓ Branch 40 taken 72 times.
✓ Branch 41 taken 40 times.
✓ Branch 42 taken 44 times.
✓ Branch 43 taken 24 times.
✓ Branch 44 taken 298 times.
✓ Branch 45 taken 172 times.
✓ Branch 46 taken 380 times.
✓ Branch 47 taken 216 times.
✓ Branch 48 taken 474 times.
✓ Branch 49 taken 334 times.
✓ Branch 50 taken 226 times.
✓ Branch 51 taken 174 times.
✓ Branch 52 taken 644 times.
✓ Branch 53 taken 506 times.
✓ Branch 54 taken 946 times.
✓ Branch 55 taken 558 times.
✓ Branch 56 taken 4510 times.
✓ Branch 57 taken 2994 times.
✓ Branch 58 taken 5138 times.
✓ Branch 59 taken 3002 times.
✓ Branch 60 taken 4510 times.
✓ Branch 61 taken 2994 times.
✓ Branch 62 taken 5138 times.
✓ Branch 63 taken 3002 times.
|
250731 | while (index_ < length_) { |
| 301 | // Internal loop checks if the vector path can be executed | ||
| 302 |
64/64✓ Branch 0 taken 8948 times.
✓ Branch 1 taken 5428 times.
✓ Branch 2 taken 59100 times.
✓ Branch 3 taken 6978 times.
✓ Branch 4 taken 9249 times.
✓ Branch 5 taken 3450 times.
✓ Branch 6 taken 221736 times.
✓ Branch 7 taken 10022 times.
✓ Branch 8 taken 10760 times.
✓ Branch 9 taken 872 times.
✓ Branch 10 taken 870876 times.
✓ Branch 11 taken 15324 times.
✓ Branch 12 taken 21372 times.
✓ Branch 13 taken 1352 times.
✓ Branch 14 taken 3476908 times.
✓ Branch 15 taken 30476 times.
✓ Branch 16 taken 198640 times.
✓ Branch 17 taken 10142 times.
✓ Branch 18 taken 1346 times.
✓ Branch 19 taken 462 times.
✓ Branch 20 taken 97298 times.
✓ Branch 21 taken 4086 times.
✓ Branch 22 taken 2930 times.
✓ Branch 23 taken 1006 times.
✓ Branch 24 taken 24782 times.
✓ Branch 25 taken 20698 times.
✓ Branch 26 taken 4538 times.
✓ Branch 27 taken 4710 times.
✓ Branch 28 taken 12636 times.
✓ Branch 29 taken 10836 times.
✓ Branch 30 taken 6082 times.
✓ Branch 31 taken 5214 times.
✓ Branch 32 taken 736 times.
✓ Branch 33 taken 168 times.
✓ Branch 34 taken 380 times.
✓ Branch 35 taken 68 times.
✓ Branch 36 taken 2400 times.
✓ Branch 37 taken 490 times.
✓ Branch 38 taken 2700 times.
✓ Branch 39 taken 412 times.
✓ Branch 40 taken 488 times.
✓ Branch 41 taken 72 times.
✓ Branch 42 taken 356 times.
✓ Branch 43 taken 44 times.
✓ Branch 44 taken 2040 times.
✓ Branch 45 taken 298 times.
✓ Branch 46 taken 2668 times.
✓ Branch 47 taken 380 times.
✓ Branch 48 taken 1470 times.
✓ Branch 49 taken 474 times.
✓ Branch 50 taken 838 times.
✓ Branch 51 taken 226 times.
✓ Branch 52 taken 3326 times.
✓ Branch 53 taken 644 times.
✓ Branch 54 taken 3970 times.
✓ Branch 55 taken 946 times.
✓ Branch 56 taken 4238 times.
✓ Branch 57 taken 4510 times.
✓ Branch 58 taken 8290 times.
✓ Branch 59 taken 5138 times.
✓ Branch 60 taken 4238 times.
✓ Branch 61 taken 4510 times.
✓ Branch 62 taken 8290 times.
✓ Branch 63 taken 5138 times.
|
5228203 | while (index_ < max_index) { |
| 303 | 5073629 | callback(index_); | |
| 304 | 5073629 | index_ += n_step; | |
| 305 | } | ||
| 306 | // Check if a final iteration is needed. The double loop is needed to | ||
| 307 | // avoid the repetition of the callback function, which is usually | ||
| 308 | // inlined into the binary. (Save some code space) | ||
| 309 |
64/64✓ Branch 0 taken 2836 times.
✓ Branch 1 taken 2592 times.
✓ Branch 2 taken 4227 times.
✓ Branch 3 taken 2751 times.
✓ Branch 4 taken 1795 times.
✓ Branch 5 taken 1655 times.
✓ Branch 6 taken 6413 times.
✓ Branch 7 taken 3609 times.
✓ Branch 8 taken 456 times.
✓ Branch 9 taken 416 times.
✓ Branch 10 taken 10212 times.
✓ Branch 11 taken 5112 times.
✓ Branch 12 taken 712 times.
✓ Branch 13 taken 640 times.
✓ Branch 14 taken 20308 times.
✓ Branch 15 taken 10168 times.
✓ Branch 16 taken 5676 times.
✓ Branch 17 taken 4466 times.
✓ Branch 18 taken 406 times.
✓ Branch 19 taken 56 times.
✓ Branch 20 taken 2284 times.
✓ Branch 21 taken 1802 times.
✓ Branch 22 taken 702 times.
✓ Branch 23 taken 304 times.
✓ Branch 24 taken 11022 times.
✓ Branch 25 taken 9676 times.
✓ Branch 26 taken 2546 times.
✓ Branch 27 taken 2164 times.
✓ Branch 28 taken 5848 times.
✓ Branch 29 taken 4988 times.
✓ Branch 30 taken 2802 times.
✓ Branch 31 taken 2412 times.
✓ Branch 32 taken 88 times.
✓ Branch 33 taken 80 times.
✓ Branch 34 taken 48 times.
✓ Branch 35 taken 20 times.
✓ Branch 36 taken 268 times.
✓ Branch 37 taken 222 times.
✓ Branch 38 taken 248 times.
✓ Branch 39 taken 164 times.
✓ Branch 40 taken 40 times.
✓ Branch 41 taken 32 times.
✓ Branch 42 taken 24 times.
✓ Branch 43 taken 20 times.
✓ Branch 44 taken 172 times.
✓ Branch 45 taken 126 times.
✓ Branch 46 taken 216 times.
✓ Branch 47 taken 164 times.
✓ Branch 48 taken 334 times.
✓ Branch 49 taken 140 times.
✓ Branch 50 taken 174 times.
✓ Branch 51 taken 52 times.
✓ Branch 52 taken 506 times.
✓ Branch 53 taken 138 times.
✓ Branch 54 taken 558 times.
✓ Branch 55 taken 388 times.
✓ Branch 56 taken 2382 times.
✓ Branch 57 taken 2128 times.
✓ Branch 58 taken 3002 times.
✓ Branch 59 taken 2136 times.
✓ Branch 60 taken 2382 times.
✓ Branch 61 taken 2128 times.
✓ Branch 62 taken 3002 times.
✓ Branch 63 taken 2136 times.
|
154574 | if (remaining_length()) { |
| 310 | 62885 | index_ = length_ - n_step; | |
| 311 | 62885 | max_index = length_; | |
| 312 | 62885 | } | |
| 313 | } | ||
| 314 | 96157 | } | |
| 315 | } else { | ||
| 316 |
112/112✓ Branch 0 taken 64024 times.
✓ Branch 1 taken 116424 times.
✓ Branch 2 taken 18177 times.
✓ Branch 3 taken 116561 times.
✓ Branch 4 taken 28720 times.
✓ Branch 5 taken 99491 times.
✓ Branch 6 taken 31196 times.
✓ Branch 7 taken 114155 times.
✓ Branch 8 taken 75743 times.
✓ Branch 9 taken 54891 times.
✓ Branch 10 taken 33783 times.
✓ Branch 11 taken 45301 times.
✓ Branch 12 taken 26134 times.
✓ Branch 13 taken 25982 times.
✓ Branch 14 taken 3764 times.
✓ Branch 15 taken 27208 times.
✓ Branch 16 taken 1020 times.
✓ Branch 17 taken 6910 times.
✓ Branch 18 taken 1032 times.
✓ Branch 19 taken 10956 times.
✓ Branch 20 taken 4108 times.
✓ Branch 21 taken 11602 times.
✓ Branch 22 taken 4558 times.
✓ Branch 23 taken 16026 times.
✓ Branch 24 taken 1982 times.
✓ Branch 25 taken 5248 times.
✓ Branch 26 taken 626 times.
✓ Branch 27 taken 8450 times.
✓ Branch 28 taken 2174 times.
✓ Branch 29 taken 6118 times.
✓ Branch 30 taken 4592 times.
✓ Branch 31 taken 11084 times.
✓ Branch 32 taken 46582 times.
✓ Branch 33 taken 9636 times.
✓ Branch 34 taken 12102 times.
✓ Branch 35 taken 14140 times.
✓ Branch 36 taken 3182 times.
✓ Branch 37 taken 3592 times.
✓ Branch 38 taken 3770 times.
✓ Branch 39 taken 8516 times.
✓ Branch 40 taken 23100 times.
✓ Branch 41 taken 3872 times.
✓ Branch 42 taken 3354 times.
✓ Branch 43 taken 8478 times.
✓ Branch 44 taken 3158 times.
✓ Branch 45 taken 3694 times.
✓ Branch 46 taken 3794 times.
✓ Branch 47 taken 8618 times.
✓ Branch 48 taken 50772 times.
✓ Branch 49 taken 13166 times.
✓ Branch 50 taken 15158 times.
✓ Branch 51 taken 11768 times.
✓ Branch 52 taken 6174 times.
✓ Branch 53 taken 5894 times.
✓ Branch 54 taken 6974 times.
✓ Branch 55 taken 5786 times.
✓ Branch 56 taken 24708 times.
✓ Branch 57 taken 6168 times.
✓ Branch 58 taken 6394 times.
✓ Branch 59 taken 6168 times.
✓ Branch 60 taken 2228 times.
✓ Branch 61 taken 3122 times.
✓ Branch 62 taken 2238 times.
✓ Branch 63 taken 3122 times.
✓ Branch 64 taken 52 times.
✓ Branch 65 taken 8 times.
✓ Branch 66 taken 8 times.
✓ Branch 67 taken 8 times.
✓ Branch 68 taken 112 times.
✓ Branch 69 taken 8 times.
✓ Branch 70 taken 52 times.
✓ Branch 71 taken 8 times.
✓ Branch 72 taken 8 times.
✓ Branch 73 taken 8 times.
✓ Branch 74 taken 112 times.
✓ Branch 75 taken 8 times.
✓ Branch 76 taken 52 times.
✓ Branch 77 taken 8 times.
✓ Branch 78 taken 8 times.
✓ Branch 79 taken 8 times.
✓ Branch 80 taken 112 times.
✓ Branch 81 taken 8 times.
✓ Branch 82 taken 52 times.
✓ Branch 83 taken 8 times.
✓ Branch 84 taken 8 times.
✓ Branch 85 taken 8 times.
✓ Branch 86 taken 112 times.
✓ Branch 87 taken 8 times.
✓ Branch 88 taken 130 times.
✓ Branch 89 taken 138 times.
✓ Branch 90 taken 138 times.
✓ Branch 91 taken 138 times.
✓ Branch 92 taken 510 times.
✓ Branch 93 taken 146 times.
✓ Branch 94 taken 130 times.
✓ Branch 95 taken 138 times.
✓ Branch 96 taken 138 times.
✓ Branch 97 taken 138 times.
✓ Branch 98 taken 510 times.
✓ Branch 99 taken 146 times.
✓ Branch 100 taken 1966 times.
✓ Branch 101 taken 2994 times.
✓ Branch 102 taken 2110 times.
✓ Branch 103 taken 2994 times.
✓ Branch 104 taken 6154 times.
✓ Branch 105 taken 3002 times.
✓ Branch 106 taken 1966 times.
✓ Branch 107 taken 2994 times.
✓ Branch 108 taken 2110 times.
✓ Branch 109 taken 2994 times.
✓ Branch 110 taken 6154 times.
✓ Branch 111 taken 3002 times.
|
1349092 | while (index_ < max_index) { |
| 317 | 538025 | callback(index_); | |
| 318 | 538025 | index_ += n_step; | |
| 319 | } | ||
| 320 | } | ||
| 321 | |||
| 322 | 927411 | return *this; | |
| 323 | 927411 | } | |
| 324 | |||
| 325 | size_t length_; | ||
| 326 | size_t step_; | ||
| 327 | size_t index_; | ||
| 328 | }; // end of class LoopUnroll2 | ||
| 329 | |||
| 330 | // Check whether any of the arguments are null pointers. | ||
| 331 | template <typename... Pointers> | ||
| 332 | 6776 | bool any_null(Pointers... pointers) KLEIDICV_STREAMING { | |
| 333 |
4/4✓ Branch 0 taken 36 times.
✓ Branch 1 taken 2992 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 272 times.
|
6776 | return (... || (pointers == nullptr)); |
| 334 | } | ||
| 335 | |||
| 336 | #define CHECK_POINTERS(...) \ | ||
| 337 | do { \ | ||
| 338 | if (KLEIDICV_TARGET_NAMESPACE::any_null(__VA_ARGS__)) { \ | ||
| 339 | return KLEIDICV_ERROR_NULL_POINTER; \ | ||
| 340 | } \ | ||
| 341 | } while (false) | ||
| 342 | |||
| 343 | template <typename AlignType, typename Value> | ||
| 344 | 79199 | bool is_misaligned(Value v) KLEIDICV_STREAMING { | |
| 345 | 79199 | constexpr size_t kMask = alignof(AlignType) - 1; | |
| 346 | static_assert(kMask == 0b0001 || kMask == 0b0011 || kMask == 0b0111 || | ||
| 347 | kMask == 0b1111); | ||
| 348 | 158398 | return (v & kMask) != 0; | |
| 349 | 79199 | } | |
| 350 | |||
| 351 | // Return value aligned up to the next multiple of alignment | ||
| 352 | // Assumes alignment is a power of two. | ||
| 353 | template <typename T> | ||
| 354 | 31697 | T align_up(T value, size_t alignment) KLEIDICV_STREAMING { | |
| 355 | 31697 | return (value + alignment - 1) & ~(alignment - 1); | |
| 356 | } | ||
| 357 | |||
| 358 | template <typename T> | ||
| 359 | 2640 | T *align_up(T *value, size_t alignment) KLEIDICV_STREAMING { | |
| 360 | // NOLINTBEGIN(performance-no-int-to-ptr) | ||
| 361 | 2640 | return reinterpret_cast<T *>( | |
| 362 | 2640 | align_up(reinterpret_cast<uintptr_t>(value), alignment)); | |
| 363 | // NOLINTEND(performance-no-int-to-ptr) | ||
| 364 | } | ||
| 365 | |||
| 366 | // Specialisation for when stride misalignment is possible. | ||
| 367 | template <typename T> | ||
| 368 | 78963 | std::enable_if_t<alignof(T) != 1, kleidicv_error_t> check_pointer_and_stride( | |
| 369 | T *pointer, size_t stride, size_t height) KLEIDICV_STREAMING { | ||
| 370 |
24/24✓ Branch 0 taken 24345 times.
✓ Branch 1 taken 305 times.
✓ Branch 2 taken 15496 times.
✓ Branch 3 taken 241 times.
✓ Branch 4 taken 11272 times.
✓ Branch 5 taken 224 times.
✓ Branch 6 taken 5304 times.
✓ Branch 7 taken 188 times.
✓ Branch 8 taken 5940 times.
✓ Branch 9 taken 84 times.
✓ Branch 10 taken 4112 times.
✓ Branch 11 taken 68 times.
✓ Branch 12 taken 2400 times.
✓ Branch 13 taken 20 times.
✓ Branch 14 taken 1596 times.
✓ Branch 15 taken 12 times.
✓ Branch 16 taken 2900 times.
✓ Branch 17 taken 20 times.
✓ Branch 18 taken 2096 times.
✓ Branch 19 taken 12 times.
✓ Branch 20 taken 1552 times.
✓ Branch 21 taken 16 times.
✓ Branch 22 taken 752 times.
✓ Branch 23 taken 8 times.
|
78963 | if (pointer == nullptr) { |
| 371 | 1198 | return KLEIDICV_ERROR_NULL_POINTER; | |
| 372 | } | ||
| 373 |
48/48✓ Branch 0 taken 21175 times.
✓ Branch 1 taken 3170 times.
✓ Branch 2 taken 21035 times.
✓ Branch 3 taken 140 times.
✓ Branch 4 taken 13820 times.
✓ Branch 5 taken 1676 times.
✓ Branch 6 taken 13724 times.
✓ Branch 7 taken 96 times.
✓ Branch 8 taken 9944 times.
✓ Branch 9 taken 1328 times.
✓ Branch 10 taken 9848 times.
✓ Branch 11 taken 96 times.
✓ Branch 12 taken 4844 times.
✓ Branch 13 taken 460 times.
✓ Branch 14 taken 4768 times.
✓ Branch 15 taken 76 times.
✓ Branch 16 taken 5304 times.
✓ Branch 17 taken 636 times.
✓ Branch 18 taken 5216 times.
✓ Branch 19 taken 88 times.
✓ Branch 20 taken 3752 times.
✓ Branch 21 taken 360 times.
✓ Branch 22 taken 3680 times.
✓ Branch 23 taken 72 times.
✓ Branch 24 taken 2200 times.
✓ Branch 25 taken 200 times.
✓ Branch 26 taken 2184 times.
✓ Branch 27 taken 16 times.
✓ Branch 28 taken 1508 times.
✓ Branch 29 taken 88 times.
✓ Branch 30 taken 1500 times.
✓ Branch 31 taken 8 times.
✓ Branch 32 taken 2660 times.
✓ Branch 33 taken 240 times.
✓ Branch 34 taken 2644 times.
✓ Branch 35 taken 16 times.
✓ Branch 36 taken 1968 times.
✓ Branch 37 taken 128 times.
✓ Branch 38 taken 1960 times.
✓ Branch 39 taken 8 times.
✓ Branch 40 taken 1352 times.
✓ Branch 41 taken 200 times.
✓ Branch 42 taken 1336 times.
✓ Branch 43 taken 16 times.
✓ Branch 44 taken 664 times.
✓ Branch 45 taken 88 times.
✓ Branch 46 taken 656 times.
✓ Branch 47 taken 8 times.
|
77765 | if (height > 1 && is_misaligned<T>(stride)) { |
| 374 | 640 | return KLEIDICV_ERROR_ALIGNMENT; | |
| 375 | } | ||
| 376 | 77125 | return KLEIDICV_OK; | |
| 377 | 78963 | } | |
| 378 | |||
| 379 | // Specialisation for when stride misalignment is impossible. | ||
| 380 | template <typename T> | ||
| 381 | 105233 | std::enable_if_t<alignof(T) == 1, kleidicv_error_t> check_pointer_and_stride( | |
| 382 | T *pointer, size_t /*stride*/, size_t /*height*/) KLEIDICV_STREAMING { | ||
| 383 |
8/8✓ Branch 0 taken 50776 times.
✓ Branch 1 taken 1127 times.
✓ Branch 2 taken 44261 times.
✓ Branch 3 taken 843 times.
✓ Branch 4 taken 4819 times.
✓ Branch 5 taken 40 times.
✓ Branch 6 taken 3343 times.
✓ Branch 7 taken 24 times.
|
105233 | if (pointer == nullptr) { |
| 384 | 2034 | return KLEIDICV_ERROR_NULL_POINTER; | |
| 385 | } | ||
| 386 | 103199 | return KLEIDICV_OK; | |
| 387 | 105233 | } | |
| 388 | |||
| 389 | #define CHECK_POINTER_AND_STRIDE(pointer, stride, height) \ | ||
| 390 | do { \ | ||
| 391 | if (kleidicv_error_t ptr_stride_err = \ | ||
| 392 | KLEIDICV_TARGET_NAMESPACE::check_pointer_and_stride( \ | ||
| 393 | pointer, stride, height)) { \ | ||
| 394 | return ptr_stride_err; \ | ||
| 395 | } \ | ||
| 396 | } while (false) | ||
| 397 | |||
| 398 | #define MAKE_POINTER_CHECK_ALIGNMENT(ElementType, name, from) \ | ||
| 399 | if constexpr (alignof(ElementType) > 1) { \ | ||
| 400 | if (KLEIDICV_TARGET_NAMESPACE::is_misaligned<ElementType>( \ | ||
| 401 | reinterpret_cast<uintptr_t>(from))) { \ | ||
| 402 | return KLEIDICV_ERROR_ALIGNMENT; \ | ||
| 403 | } \ | ||
| 404 | } \ | ||
| 405 | ElementType *name = reinterpret_cast<ElementType *>(from) | ||
| 406 | |||
| 407 | // Check whether the image size is acceptable by limiting it. | ||
| 408 | #define CHECK_IMAGE_SIZE(width, height) \ | ||
| 409 | do { \ | ||
| 410 | size_t image_size = 0; \ | ||
| 411 | if (__builtin_mul_overflow(width, height, &image_size)) { \ | ||
| 412 | return KLEIDICV_ERROR_RANGE; \ | ||
| 413 | } \ | ||
| 414 | \ | ||
| 415 | if (image_size > KLEIDICV_MAX_IMAGE_PIXELS) { \ | ||
| 416 | return KLEIDICV_ERROR_RANGE; \ | ||
| 417 | } \ | ||
| 418 | } while (false) | ||
| 419 | |||
| 420 | // Check whether the rectangle size is acceptable by limiting it. | ||
| 421 | #define CHECK_RECTANGLE_SIZE(rect) CHECK_IMAGE_SIZE(rect.width, rect.height) | ||
| 422 | |||
| 423 | } // namespace KLEIDICV_TARGET_NAMESPACE | ||
| 424 | |||
| 425 | #endif // KLEIDICV_UTILS_H | ||
| 426 |