| 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 88258 times.
✓ Branch 1 taken 394166 times.
|
482424 | if (value > std::numeric_limits<U>::max()) { |
| 25 | 88258 | return std::numeric_limits<U>::max(); | |
| 26 | } | ||
| 27 |
2/2✓ Branch 0 taken 311991 times.
✓ Branch 1 taken 82175 times.
|
394166 | if (value < 0) { |
| 28 | 82175 | return 0; | |
| 29 | } | ||
| 30 | |||
| 31 | 311991 | 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 182 times.
✓ Branch 1 taken 880 times.
✓ Branch 2 taken 61 times.
✓ Branch 3 taken 329 times.
✓ Branch 4 taken 31 times.
✓ Branch 5 taken 143 times.
|
1626 | if (value > static_cast<SrcType>(max_value)) { |
| 52 | 274 | return max_value; | |
| 53 | } | ||
| 54 | |||
| 55 | 1352 | return static_cast<DstType>(value); | |
| 56 | 1626 | } | |
| 57 | |||
| 58 | // Rounding shift right. | ||
| 59 | template <typename T> | ||
| 60 | 396118 | static T rounding_shift_right(T value, size_t shift) KLEIDICV_STREAMING { | |
| 61 | 396118 | return (value + (T{1} << (shift - 1))) >> shift; | |
| 62 | } | ||
| 63 | |||
| 64 | // When placed in a loop, it effectively disables loop vectorization. | ||
| 65 | 723838 | static inline void disable_loop_vectorization() KLEIDICV_STREAMING { | |
| 66 | 723838 | __asm__(""); | |
| 67 | 723838 | } | |
| 68 | |||
| 69 | // Helper class to unroll a loop as needed. | ||
| 70 | class LoopUnroll final { | ||
| 71 | public: | ||
| 72 | 62574 | explicit LoopUnroll(size_t length, size_t step) KLEIDICV_STREAMING | |
| 73 | 62574 | : length_(length), | |
| 74 | 62574 | step_(step), | |
| 75 | 62574 | index_(0), | |
| 76 | 62574 | 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 | 37014 | LoopUnroll &unroll_twice(CallbackType callback) KLEIDICV_STREAMING { | |
| 87 | 37014 | return unroll_n_times<2>(callback); | |
| 88 | } | ||
| 89 | |||
| 90 | // Unrolls the loop twice, if enabled. | ||
| 91 | template <bool Enable, typename CallbackType> | ||
| 92 | 35226 | LoopUnroll &unroll_twice_if([[maybe_unused]] CallbackType callback) | |
| 93 | KLEIDICV_STREAMING { | ||
| 94 | if constexpr (Enable) { | ||
| 95 | 35226 | 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 | 50474 | LoopUnroll &remaining(CallbackType callback) KLEIDICV_STREAMING { | |
| 133 |
24/24✓ Branch 0 taken 1894 times.
✓ Branch 1 taken 16634 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.
|
50474 | if (length_) { |
| 134 | 43115 | callback(length_, step_); | |
| 135 | 43115 | length_ = 0; | |
| 136 | 43115 | } | |
| 137 | |||
| 138 | 50474 | 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 | 75277 | 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 | 58753 | LoopUnroll &unroll_n_times(CallbackType callback) KLEIDICV_STREAMING { | |
| 158 | 58753 | 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 | 58753 | 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 20994 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.
|
713076 | for (index_ = 0; index_ < max_index; ++index_) { |
| 166 | 654323 | callback(step); | |
| 167 | 654323 | } | |
| 168 | |||
| 169 | // Adjust length to reflect the processed data. | ||
| 170 | 58753 | length_ -= step * index_; | |
| 171 | 58753 | return *this; | |
| 172 | 58753 | } | |
| 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 | 654612 | explicit LoopUnroll2(size_t length, size_t step) KLEIDICV_STREAMING | |
| 202 | 654612 | : length_(length), | |
| 203 | 654612 | step_(step), | |
| 204 | 654612 | 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 | 58852 | LoopUnroll2 &unroll_four_times(CallbackType callback) KLEIDICV_STREAMING { | |
| 215 | 58852 | return unroll_n_times<4>(callback); | |
| 216 | } | ||
| 217 | |||
| 218 | // Loop unrolled twice. | ||
| 219 | template <typename CallbackType> | ||
| 220 | 468584 | KLEIDICV_FORCE_INLINE LoopUnroll2 &unroll_twice(CallbackType callback) | |
| 221 | KLEIDICV_STREAMING { | ||
| 222 | 468584 | 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 | 294405 | KLEIDICV_FORCE_INLINE LoopUnroll2 &unroll_once(CallbackType callback) | |
| 238 | KLEIDICV_STREAMING { | ||
| 239 | 294405 | 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 | 71550 | LoopUnroll2 &tail(CallbackType callback) KLEIDICV_STREAMING { | |
| 255 |
47/56✓ Branch 0 taken 54059 times.
✓ Branch 1 taken 15842 times.
✓ Branch 2 taken 33736 times.
✓ Branch 3 taken 14506 times.
✓ Branch 4 taken 44474 times.
✓ Branch 5 taken 14074 times.
✓ Branch 6 taken 30133 times.
✓ Branch 7 taken 13236 times.
✓ Branch 8 taken 3445 times.
✓ Branch 9 taken 1388 times.
✓ Branch 10 taken 409 times.
✓ Branch 11 taken 922 times.
✓ Branch 12 taken 3220 times.
✓ Branch 13 taken 1274 times.
✓ Branch 14 taken 1496 times.
✓ Branch 15 taken 1204 times.
✓ Branch 16 taken 1408 times.
✓ Branch 17 taken 1162 times.
✓ Branch 18 taken 164 times.
✓ Branch 19 taken 86 times.
✓ Branch 20 taken 384 times.
✓ Branch 21 taken 856 times.
✓ Branch 22 taken 1332 times.
✓ Branch 23 taken 820 times.
✓ Branch 24 taken 540 times.
✓ Branch 25 taken 586 times.
✓ Branch 26 taken 572 times.
✓ Branch 27 taken 154 times.
✓ Branch 28 taken 480 times.
✓ Branch 29 taken 924 times.
✓ Branch 30 taken 816 times.
✓ Branch 31 taken 748 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 64 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 32 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 308 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.
|
248662 | while (index_ < length_) { |
| 256 | 177112 | disable_loop_vectorization(); | |
| 257 | 177112 | callback(index_++); | |
| 258 | } | ||
| 259 | |||
| 260 | 71550 | return *this; | |
| 261 | } | ||
| 262 | |||
| 263 | // Processes all remaining data at once. | ||
| 264 | template <typename CallbackType> | ||
| 265 | 539298 | LoopUnroll2 &remaining(CallbackType callback) KLEIDICV_STREAMING { | |
| 266 |
64/64✓ Branch 0 taken 651 times.
✓ Branch 1 taken 74562 times.
✓ Branch 2 taken 7818 times.
✓ Branch 3 taken 68205 times.
✓ Branch 4 taken 970 times.
✓ Branch 5 taken 64038 times.
✓ Branch 6 taken 10592 times.
✓ Branch 7 taken 70464 times.
✓ Branch 8 taken 947 times.
✓ Branch 9 taken 17269 times.
✓ Branch 10 taken 11123 times.
✓ Branch 11 taken 15411 times.
✓ Branch 12 taken 1130 times.
✓ Branch 13 taken 7578 times.
✓ Branch 14 taken 21272 times.
✓ Branch 15 taken 11508 times.
✓ Branch 16 taken 1920 times.
✓ Branch 17 taken 11426 times.
✓ Branch 18 taken 804 times.
✓ Branch 19 taken 10870 times.
✓ Branch 20 taken 1464 times.
✓ Branch 21 taken 7058 times.
✓ Branch 22 taken 1500 times.
✓ Branch 23 taken 10580 times.
✓ Branch 24 taken 2476 times.
✓ Branch 25 taken 12900 times.
✓ Branch 26 taken 1132 times.
✓ Branch 27 taken 9334 times.
✓ Branch 28 taken 2116 times.
✓ Branch 29 taken 8744 times.
✓ Branch 30 taken 2308 times.
✓ Branch 31 taken 10496 times.
✓ Branch 32 taken 104 times.
✓ Branch 33 taken 2384 times.
✓ Branch 34 taken 52 times.
✓ Branch 35 taken 6940 times.
✓ Branch 36 taken 478 times.
✓ Branch 37 taken 2742 times.
✓ Branch 38 taken 676 times.
✓ Branch 39 taken 7468 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.
|
539298 | if (remaining_length()) { |
| 267 | 461431 | callback(index_, length_); | |
| 268 | 461431 | index_ = length_; | |
| 269 | 461431 | } | |
| 270 | |||
| 271 | 539298 | 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 | 821841 | size_t step() const KLEIDICV_STREAMING { return step_; } | |
| 279 | |||
| 280 | // Returns the remaining length. | ||
| 281 | 1513811 | size_t remaining_length() const KLEIDICV_STREAMING { | |
| 282 | 1513811 | return length_ - index_; | |
| 283 | } | ||
| 284 | |||
| 285 | private: | ||
| 286 | template <const size_t UnrollFactor, typename CallbackType> | ||
| 287 | 821841 | KLEIDICV_FORCE_INLINE LoopUnroll2 &unroll_n_times(CallbackType callback) | |
| 288 | KLEIDICV_STREAMING { | ||
| 289 | 821841 | const size_t n_step = UnrollFactor * step(); | |
| 290 | 821841 | 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 3540 times.
✓ Branch 1 taken 1890 times.
✓ Branch 2 taken 2271 times.
✓ Branch 3 taken 4243 times.
✓ Branch 4 taken 3299 times.
✓ Branch 5 taken 1795 times.
✓ Branch 6 taken 2581 times.
✓ Branch 7 taken 6597 times.
✓ Branch 8 taken 915 times.
✓ Branch 9 taken 777 times.
✓ Branch 10 taken 525 times.
✓ Branch 11 taken 10501 times.
✓ Branch 12 taken 748 times.
✓ Branch 13 taken 788 times.
✓ Branch 14 taken 824 times.
✓ Branch 15 taken 20324 times.
✓ Branch 16 taken 386 times.
✓ Branch 17 taken 5988 times.
✓ Branch 18 taken 508 times.
✓ Branch 19 taken 454 times.
✓ Branch 20 taken 490 times.
✓ Branch 21 taken 1644 times.
✓ Branch 22 taken 502 times.
✓ Branch 23 taken 550 times.
✓ Branch 24 taken 442 times.
✓ Branch 25 taken 11450 times.
✓ Branch 26 taken 76 times.
✓ Branch 27 taken 3166 times.
✓ Branch 28 taken 518 times.
✓ Branch 29 taken 6154 times.
✓ Branch 30 taken 554 times.
✓ Branch 31 taken 3422 times.
✓ Branch 32 taken 32 times.
✓ Branch 33 taken 40 times.
✓ Branch 34 taken 16 times.
✓ Branch 35 taken 24 times.
✓ Branch 36 taken 144 times.
✓ Branch 37 taken 172 times.
✓ Branch 38 taken 208 times.
✓ Branch 39 taken 216 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.
|
114314 | if (length_ >= n_step) { |
| 299 | // External loop only ends when all data has been processed | ||
| 300 |
64/64✓ Branch 0 taken 3708 times.
✓ Branch 1 taken 1890 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 1425 times.
✓ Branch 9 taken 777 times.
✓ Branch 10 taken 15493 times.
✓ Branch 11 taken 10501 times.
✓ Branch 12 taken 1536 times.
✓ Branch 13 taken 788 times.
✓ Branch 14 taken 30396 times.
✓ Branch 15 taken 20324 times.
✓ Branch 16 taken 10766 times.
✓ Branch 17 taken 5988 times.
✓ Branch 18 taken 510 times.
✓ Branch 19 taken 454 times.
✓ Branch 20 taken 2806 times.
✓ Branch 21 taken 1644 times.
✓ Branch 22 taken 854 times.
✓ Branch 23 taken 550 times.
✓ Branch 24 taken 20714 times.
✓ Branch 25 taken 11450 times.
✓ Branch 26 taken 4718 times.
✓ Branch 27 taken 3166 times.
✓ Branch 28 taken 10900 times.
✓ Branch 29 taken 6154 times.
✓ Branch 30 taken 5222 times.
✓ Branch 31 taken 3422 times.
✓ Branch 32 taken 72 times.
✓ Branch 33 taken 40 times.
✓ Branch 34 taken 44 times.
✓ Branch 35 taken 24 times.
✓ Branch 36 taken 298 times.
✓ Branch 37 taken 172 times.
✓ Branch 38 taken 380 times.
✓ Branch 39 taken 216 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.
|
246883 | while (index_ < length_) { |
| 301 | // Internal loop checks if the vector path can be executed | ||
| 302 |
64/64✓ Branch 0 taken 7764 times.
✓ Branch 1 taken 3708 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 11633 times.
✓ Branch 9 taken 1425 times.
✓ Branch 10 taken 871013 times.
✓ Branch 11 taken 15493 times.
✓ Branch 12 taken 21824 times.
✓ Branch 13 taken 1536 times.
✓ Branch 14 taken 3476828 times.
✓ Branch 15 taken 30396 times.
✓ Branch 16 taken 199888 times.
✓ Branch 17 taken 10766 times.
✓ Branch 18 taken 1394 times.
✓ Branch 19 taken 510 times.
✓ Branch 20 taken 95058 times.
✓ Branch 21 taken 2806 times.
✓ Branch 22 taken 2778 times.
✓ Branch 23 taken 854 times.
✓ Branch 24 taken 24830 times.
✓ Branch 25 taken 20714 times.
✓ Branch 26 taken 4546 times.
✓ Branch 27 taken 4718 times.
✓ Branch 28 taken 12716 times.
✓ Branch 29 taken 10900 times.
✓ Branch 30 taken 6090 times.
✓ Branch 31 taken 5222 times.
✓ Branch 32 taken 592 times.
✓ Branch 33 taken 72 times.
✓ Branch 34 taken 356 times.
✓ Branch 35 taken 44 times.
✓ Branch 36 taken 2144 times.
✓ Branch 37 taken 298 times.
✓ Branch 38 taken 2668 times.
✓ Branch 39 taken 380 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.
|
5225091 | while (index_ < max_index) { |
| 303 | 5072419 | callback(index_); | |
| 304 | 5072419 | 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 1882 times.
✓ Branch 1 taken 1826 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 777 times.
✓ Branch 9 taken 648 times.
✓ Branch 10 taken 10333 times.
✓ Branch 11 taken 5160 times.
✓ Branch 12 taken 788 times.
✓ Branch 13 taken 748 times.
✓ Branch 14 taken 20324 times.
✓ Branch 15 taken 10072 times.
✓ Branch 16 taken 5988 times.
✓ Branch 17 taken 4778 times.
✓ Branch 18 taken 454 times.
✓ Branch 19 taken 56 times.
✓ Branch 20 taken 1644 times.
✓ Branch 21 taken 1162 times.
✓ Branch 22 taken 550 times.
✓ Branch 23 taken 304 times.
✓ Branch 24 taken 11030 times.
✓ Branch 25 taken 9684 times.
✓ Branch 26 taken 2554 times.
✓ Branch 27 taken 2164 times.
✓ Branch 28 taken 5880 times.
✓ Branch 29 taken 5020 times.
✓ Branch 30 taken 2810 times.
✓ Branch 31 taken 2412 times.
✓ Branch 32 taken 40 times.
✓ Branch 33 taken 32 times.
✓ Branch 34 taken 24 times.
✓ Branch 35 taken 20 times.
✓ Branch 36 taken 172 times.
✓ Branch 37 taken 126 times.
✓ Branch 38 taken 216 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.
|
152672 | if (remaining_length()) { |
| 310 | 61979 | index_ = length_ - n_step; | |
| 311 | 61979 | max_index = length_; | |
| 312 | 61979 | } | |
| 313 | } | ||
| 314 | 94211 | } | |
| 315 | } else { | ||
| 316 |
112/112✓ Branch 0 taken 11744 times.
✓ Branch 1 taken 90932 times.
✓ Branch 2 taken 12095 times.
✓ Branch 3 taken 92817 times.
✓ Branch 4 taken 10452 times.
✓ Branch 5 taken 75815 times.
✓ Branch 6 taken 11632 times.
✓ Branch 7 taken 88187 times.
✓ Branch 8 taken 52193 times.
✓ Branch 9 taken 52571 times.
✓ Branch 10 taken 4525 times.
✓ Branch 11 taken 43209 times.
✓ Branch 12 taken 26951 times.
✓ Branch 13 taken 27388 times.
✓ Branch 14 taken 4580 times.
✓ Branch 15 taken 29224 times.
✓ Branch 16 taken 1149 times.
✓ Branch 17 taken 8960 times.
✓ Branch 18 taken 1864 times.
✓ Branch 19 taken 10942 times.
✓ Branch 20 taken 4252 times.
✓ Branch 21 taken 11448 times.
✓ Branch 22 taken 4438 times.
✓ Branch 23 taken 15838 times.
✓ Branch 24 taken 3206 times.
✓ Branch 25 taken 5824 times.
✓ Branch 26 taken 770 times.
✓ Branch 27 taken 9026 times.
✓ Branch 28 taken 2318 times.
✓ Branch 29 taken 6694 times.
✓ Branch 30 taken 2096 times.
✓ Branch 31 taken 9254 times.
✓ Branch 32 taken 46126 times.
✓ Branch 33 taken 7806 times.
✓ Branch 34 taken 11646 times.
✓ Branch 35 taken 12310 times.
✓ Branch 36 taken 3254 times.
✓ Branch 37 taken 3694 times.
✓ Branch 38 taken 3794 times.
✓ Branch 39 taken 8618 times.
✓ Branch 40 taken 23124 times.
✓ Branch 41 taken 3974 times.
✓ Branch 42 taken 3450 times.
✓ Branch 43 taken 8580 times.
✓ Branch 44 taken 3182 times.
✓ Branch 45 taken 3796 times.
✓ Branch 46 taken 3818 times.
✓ Branch 47 taken 8720 times.
✓ Branch 48 taken 50532 times.
✓ Branch 49 taken 12848 times.
✓ Branch 50 taken 15086 times.
✓ Branch 51 taken 11450 times.
✓ Branch 52 taken 6102 times.
✓ Branch 53 taken 5576 times.
✓ Branch 54 taken 6622 times.
✓ Branch 55 taken 5366 times.
✓ Branch 56 taken 24612 times.
✓ Branch 57 taken 5748 times.
✓ Branch 58 taken 6298 times.
✓ Branch 59 taken 5748 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.
|
1096608 | while (index_ < max_index) { |
| 317 | 389081 | callback(index_); | |
| 318 | 389081 | index_ += n_step; | |
| 319 | } | ||
| 320 | } | ||
| 321 | |||
| 322 | 821841 | return *this; | |
| 323 | 821841 | } | |
| 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 | 14160 | bool any_null(Pointers... pointers) KLEIDICV_STREAMING { | |
| 333 |
12/12✓ Branch 0 taken 336 times.
✓ Branch 1 taken 2724 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 300 times.
✓ Branch 4 taken 304 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 300 times.
✓ Branch 8 taken 300 times.
✓ Branch 9 taken 4 times.
✓ Branch 10 taken 4 times.
✓ Branch 11 taken 296 times.
|
14160 | 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 | 78424 | bool is_misaligned(Value v) KLEIDICV_STREAMING { | |
| 345 | 78424 | constexpr size_t kMask = alignof(AlignType) - 1; | |
| 346 | static_assert(kMask == 0b0001 || kMask == 0b0011 || kMask == 0b0111 || | ||
| 347 | kMask == 0b1111); | ||
| 348 | 156848 | return (v & kMask) != 0; | |
| 349 | 78424 | } | |
| 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 | 14933 | T align_up(T value, size_t alignment) KLEIDICV_STREAMING { | |
| 355 | 14933 | return (value + alignment - 1) & ~(alignment - 1); | |
| 356 | } | ||
| 357 | |||
| 358 | template <typename T> | ||
| 359 | 6236 | T *align_up(T *value, size_t alignment) KLEIDICV_STREAMING { | |
| 360 | // NOLINTBEGIN(performance-no-int-to-ptr) | ||
| 361 | 6236 | return reinterpret_cast<T *>( | |
| 362 | 6236 | 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 | 78201 | 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 23184 times.
✓ Branch 1 taken 305 times.
✓ Branch 2 taken 15315 times.
✓ Branch 3 taken 241 times.
✓ Branch 4 taken 11560 times.
✓ Branch 5 taken 228 times.
✓ Branch 6 taken 5588 times.
✓ Branch 7 taken 192 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.
|
78201 | if (pointer == nullptr) { |
| 371 | 1206 | return KLEIDICV_ERROR_NULL_POINTER; | |
| 372 | } | ||
| 373 |
48/48✓ Branch 0 taken 20019 times.
✓ Branch 1 taken 3165 times.
✓ Branch 2 taken 19879 times.
✓ Branch 3 taken 140 times.
✓ Branch 4 taken 13629 times.
✓ Branch 5 taken 1686 times.
✓ Branch 6 taken 13533 times.
✓ Branch 7 taken 96 times.
✓ Branch 8 taken 10232 times.
✓ Branch 9 taken 1328 times.
✓ Branch 10 taken 10136 times.
✓ Branch 11 taken 96 times.
✓ Branch 12 taken 5128 times.
✓ Branch 13 taken 460 times.
✓ Branch 14 taken 5052 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.
|
76995 | if (height > 1 && is_misaligned<T>(stride)) { |
| 374 | 640 | return KLEIDICV_ERROR_ALIGNMENT; | |
| 375 | } | ||
| 376 | 76355 | return KLEIDICV_OK; | |
| 377 | 78201 | } | |
| 378 | |||
| 379 | // Specialisation for when stride misalignment is impossible. | ||
| 380 | template <typename T> | ||
| 381 | 100549 | 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 47949 times.
✓ Branch 1 taken 1117 times.
✓ Branch 2 taken 42424 times.
✓ Branch 3 taken 833 times.
✓ Branch 4 taken 4819 times.
✓ Branch 5 taken 40 times.
✓ Branch 6 taken 3343 times.
✓ Branch 7 taken 24 times.
|
100549 | if (pointer == nullptr) { |
| 384 | 2014 | return KLEIDICV_ERROR_NULL_POINTER; | |
| 385 | } | ||
| 386 | 98535 | return KLEIDICV_OK; | |
| 387 | 100549 | } | |
| 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 |