| 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 | 140376 | static U saturating_cast(S value) KLEIDICV_STREAMING { | |
| 24 |
2/2✓ Branch 0 taken 27853 times.
✓ Branch 1 taken 112523 times.
|
140376 | if (value > std::numeric_limits<U>::max()) { |
| 25 | 27853 | return std::numeric_limits<U>::max(); | |
| 26 | } | ||
| 27 |
2/2✓ Branch 0 taken 84464 times.
✓ Branch 1 taken 28059 times.
|
112523 | if (value < 0) { |
| 28 | 28059 | return 0; | |
| 29 | } | ||
| 30 | |||
| 31 | 84464 | return static_cast<U>(value); | |
| 32 | 140376 | } | |
| 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 | 764 | static DstType saturating_cast(SrcType value) KLEIDICV_STREAMING { | |
| 40 | 764 | 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 | 1042 | static DstType saturating_cast(SrcType value) KLEIDICV_STREAMING { | |
| 49 | 1042 | DstType max_value = std::numeric_limits<DstType>::max(); | |
| 50 | |||
| 51 |
6/6✓ Branch 0 taken 103 times.
✓ Branch 1 taken 575 times.
✓ Branch 2 taken 46 times.
✓ Branch 3 taken 200 times.
✓ Branch 4 taken 30 times.
✓ Branch 5 taken 88 times.
|
1042 | if (value > static_cast<SrcType>(max_value)) { |
| 52 | 179 | return max_value; | |
| 53 | } | ||
| 54 | |||
| 55 | 863 | return static_cast<DstType>(value); | |
| 56 | 1042 | } | |
| 57 | |||
| 58 | // Rounding shift right. | ||
| 59 | template <typename T> | ||
| 60 | 310054 | static T rounding_shift_right(T value, size_t shift) KLEIDICV_STREAMING { | |
| 61 | 310054 | return (value + (T{1} << (shift - 1))) >> shift; | |
| 62 | } | ||
| 63 | |||
| 64 | // When placed in a loop, it effectively disables loop vectorization. | ||
| 65 | 650562 | static inline void disable_loop_vectorization() KLEIDICV_STREAMING { | |
| 66 | 650562 | __asm__(""); | |
| 67 | 650562 | } | |
| 68 | |||
| 69 | // Helper class to unroll a loop as needed. | ||
| 70 | class LoopUnroll final { | ||
| 71 | public: | ||
| 72 | 57408 | explicit LoopUnroll(size_t length, size_t step) KLEIDICV_STREAMING | |
| 73 | 57408 | : length_(length), | |
| 74 | 57408 | step_(step), | |
| 75 | 57408 | index_(0), | |
| 76 | 57408 | 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 | 33068 | LoopUnroll &unroll_twice(CallbackType callback) KLEIDICV_STREAMING { | |
| 87 | 33068 | return unroll_n_times<2>(callback); | |
| 88 | } | ||
| 89 | |||
| 90 | // Unrolls the loop twice, if enabled. | ||
| 91 | template <bool Enable, typename CallbackType> | ||
| 92 | 38023 | LoopUnroll &unroll_twice_if([[maybe_unused]] CallbackType callback) | |
| 93 | KLEIDICV_STREAMING { | ||
| 94 | if constexpr (Enable) { | ||
| 95 | 31496 | return unroll_twice(callback); | |
| 96 | } | ||
| 97 | |||
| 98 | 6527 | return *this; | |
| 99 | } | ||
| 100 | |||
| 101 | // Loop unrolled once. | ||
| 102 | template <typename CallbackType> | ||
| 103 | 14864 | LoopUnroll &unroll_once(CallbackType callback) KLEIDICV_STREAMING { | |
| 104 | 14864 | return unroll_n_times<1>(callback); | |
| 105 | } | ||
| 106 | |||
| 107 | // Unrolls the loop once, if enabled. | ||
| 108 | template <bool Enable, typename CallbackType> | ||
| 109 | 38216 | LoopUnroll &unroll_once_if([[maybe_unused]] CallbackType callback) | |
| 110 | KLEIDICV_STREAMING { | ||
| 111 | if constexpr (Enable) { | ||
| 112 | 3939 | return unroll_once(callback); | |
| 113 | } | ||
| 114 | |||
| 115 | 34277 | 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 | 45320 | LoopUnroll &remaining(CallbackType callback) KLEIDICV_STREAMING { | |
| 133 |
24/24✓ Branch 0 taken 2319 times.
✓ Branch 1 taken 14774 times.
✓ Branch 2 taken 1485 times.
✓ Branch 3 taken 5194 times.
✓ Branch 4 taken 1275 times.
✓ Branch 5 taken 4755 times.
✓ Branch 6 taken 1299 times.
✓ Branch 7 taken 4064 times.
✓ Branch 8 taken 876 times.
✓ Branch 9 taken 2767 times.
✓ Branch 10 taken 541 times.
✓ Branch 11 taken 2089 times.
✓ Branch 12 taken 452 times.
✓ Branch 13 taken 1010 times.
✓ Branch 14 taken 434 times.
✓ Branch 15 taken 818 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.
|
45320 | if (length_) { |
| 134 | 36591 | callback(length_, step_); | |
| 135 | 36591 | length_ = 0; | |
| 136 | 36591 | } | |
| 137 | |||
| 138 | 45320 | 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 | 2362 | size_t step() const KLEIDICV_STREAMING { return step_; } | |
| 146 | |||
| 147 | // Returns the remaining length. | ||
| 148 | 69588 | 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 | 53488 | LoopUnroll &unroll_n_times(CallbackType callback) KLEIDICV_STREAMING { | |
| 158 | 53488 | 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 | 53488 | const size_t max_index = remaining_length() / step; | |
| 163 | // NOLINTEND(clang-analyzer-core.DivideZero) | ||
| 164 | |||
| 165 |
24/24✓ Branch 0 taken 469103 times.
✓ Branch 1 taken 19589 times.
✓ Branch 2 taken 37862 times.
✓ Branch 3 taken 6154 times.
✓ Branch 4 taken 31291 times.
✓ Branch 5 taken 6179 times.
✓ Branch 6 taken 34494 times.
✓ Branch 7 taken 7785 times.
✓ Branch 8 taken 25678 times.
✓ Branch 9 taken 3594 times.
✓ Branch 10 taken 22699 times.
✓ Branch 11 taken 3193 times.
✓ Branch 12 taken 16202 times.
✓ Branch 13 taken 3349 times.
✓ Branch 14 taken 15653 times.
✓ Branch 15 taken 2477 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.
|
709670 | for (index_ = 0; index_ < max_index; ++index_) { |
| 166 | 656182 | callback(step); | |
| 167 | 656182 | } | |
| 168 | |||
| 169 | // Adjust length to reflect the processed data. | ||
| 170 | 53488 | length_ -= step * index_; | |
| 171 | 53488 | return *this; | |
| 172 | 53488 | } | |
| 173 | |||
| 174 | // Instructs the loop logic to avoid the tail loop. | ||
| 175 | template <typename CallbackType> | ||
| 176 | 1653 | bool try_avoid_tail_loop(CallbackType callback) KLEIDICV_STREAMING { | |
| 177 |
8/8✓ Branch 0 taken 262 times.
✓ Branch 1 taken 245 times.
✓ Branch 2 taken 228 times.
✓ Branch 3 taken 154 times.
✓ Branch 4 taken 228 times.
✓ Branch 5 taken 154 times.
✓ Branch 6 taken 228 times.
✓ Branch 7 taken 154 times.
|
1653 | if (KLEIDICV_UNLIKELY(!can_avoid_tail_)) { |
| 178 | 946 | return false; | |
| 179 | } | ||
| 180 | |||
| 181 |
8/8✓ Branch 0 taken 178 times.
✓ Branch 1 taken 67 times.
✓ Branch 2 taken 112 times.
✓ Branch 3 taken 42 times.
✓ Branch 4 taken 112 times.
✓ Branch 5 taken 42 times.
✓ Branch 6 taken 112 times.
✓ Branch 7 taken 42 times.
|
707 | if (KLEIDICV_UNLIKELY(!remaining_length())) { |
| 182 | 514 | return false; | |
| 183 | } | ||
| 184 | |||
| 185 | 193 | callback(step() - remaining_length()); | |
| 186 | 193 | length_ = step(); | |
| 187 | 193 | return true; | |
| 188 | 1653 | } | |
| 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 | 393028 | explicit LoopUnroll2(size_t length, size_t step) KLEIDICV_STREAMING | |
| 202 | 393028 | : length_(length), | |
| 203 | 393028 | step_(step), | |
| 204 | 393028 | 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 | 58744 | LoopUnroll2 &unroll_four_times(CallbackType callback) KLEIDICV_STREAMING { | |
| 215 | 58744 | return unroll_n_times<4>(callback); | |
| 216 | } | ||
| 217 | |||
| 218 | // Loop unrolled twice. | ||
| 219 | template <typename CallbackType> | ||
| 220 | 207320 | LoopUnroll2 &unroll_twice(CallbackType callback) KLEIDICV_STREAMING { | |
| 221 | 207320 | return unroll_n_times<2>(callback); | |
| 222 | } | ||
| 223 | |||
| 224 | // Unrolls the loop twice, if enabled. | ||
| 225 | template <bool Enable, typename CallbackType> | ||
| 226 | LoopUnroll2 &unroll_twice_if(CallbackType callback) KLEIDICV_STREAMING { | ||
| 227 | if constexpr (Enable) { | ||
| 228 | return unroll_twice(callback); | ||
| 229 | } | ||
| 230 | |||
| 231 | return *this; | ||
| 232 | } | ||
| 233 | |||
| 234 | // Loop unrolled once. | ||
| 235 | template <typename CallbackType> | ||
| 236 | 275653 | LoopUnroll2 &unroll_once(CallbackType callback) KLEIDICV_STREAMING { | |
| 237 | 275653 | return unroll_n_times<1>(callback); | |
| 238 | } | ||
| 239 | |||
| 240 | // Unrolls the loop once, if enabled. | ||
| 241 | template <bool Enable, typename CallbackType> | ||
| 242 | LoopUnroll2 &unroll_once_if(CallbackType callback) KLEIDICV_STREAMING { | ||
| 243 | if constexpr (Enable) { | ||
| 244 | return unroll_once(callback); | ||
| 245 | } | ||
| 246 | |||
| 247 | return *this; | ||
| 248 | } | ||
| 249 | |||
| 250 | // Processes trailing data. | ||
| 251 | template <typename CallbackType> | ||
| 252 | 53798 | LoopUnroll2 &tail(CallbackType callback) KLEIDICV_STREAMING { | |
| 253 |
47/56✓ Branch 0 taken 42289 times.
✓ Branch 1 taken 11410 times.
✓ Branch 2 taken 21966 times.
✓ Branch 3 taken 10074 times.
✓ Branch 4 taken 32704 times.
✓ Branch 5 taken 9642 times.
✓ Branch 6 taken 18363 times.
✓ Branch 7 taken 8804 times.
✓ Branch 8 taken 3485 times.
✓ Branch 9 taken 1394 times.
✓ Branch 10 taken 329 times.
✓ Branch 11 taken 910 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 1168 times.
✓ Branch 18 taken 164 times.
✓ Branch 19 taken 74 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 592 times.
✓ Branch 26 taken 572 times.
✓ Branch 27 taken 142 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 520 times.
✓ Branch 50 taken 4 times.
✓ Branch 51 taken 36 times.
✓ Branch 52 taken 272 times.
✓ Branch 53 taken 818 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 748 times.
|
183790 | while (index_ < length_) { |
| 254 | 129992 | disable_loop_vectorization(); | |
| 255 | 129992 | callback(index_++); | |
| 256 | } | ||
| 257 | |||
| 258 | 53798 | return *this; | |
| 259 | } | ||
| 260 | |||
| 261 | // Processes all remaining data at once. | ||
| 262 | template <typename CallbackType> | ||
| 263 | 295618 | LoopUnroll2 &remaining(CallbackType callback) KLEIDICV_STREAMING { | |
| 264 |
64/64✓ Branch 0 taken 597 times.
✓ Branch 1 taken 46504 times.
✓ Branch 2 taken 7764 times.
✓ Branch 3 taken 37835 times.
✓ Branch 4 taken 916 times.
✓ Branch 5 taken 40556 times.
✓ Branch 6 taken 10538 times.
✓ Branch 7 taken 33230 times.
✓ Branch 8 taken 947 times.
✓ Branch 9 taken 3511 times.
✓ Branch 10 taken 11123 times.
✓ Branch 11 taken 1575 times.
✓ Branch 12 taken 1130 times.
✓ Branch 13 taken 2954 times.
✓ Branch 14 taken 21272 times.
✓ Branch 15 taken 2284 times.
✓ Branch 16 taken 1900 times.
✓ Branch 17 taken 6804 times.
✓ Branch 18 taken 804 times.
✓ Branch 19 taken 1610 times.
✓ Branch 20 taken 1464 times.
✓ Branch 21 taken 2434 times.
✓ Branch 22 taken 1500 times.
✓ Branch 23 taken 1356 times.
✓ Branch 24 taken 2456 times.
✓ Branch 25 taken 10614 times.
✓ Branch 26 taken 1132 times.
✓ Branch 27 taken 2410 times.
✓ Branch 28 taken 2116 times.
✓ Branch 29 taken 6456 times.
✓ Branch 30 taken 2308 times.
✓ Branch 31 taken 3608 times.
✓ Branch 32 taken 104 times.
✓ Branch 33 taken 96 times.
✓ Branch 34 taken 52 times.
✓ Branch 35 taken 52 times.
✓ Branch 36 taken 478 times.
✓ Branch 37 taken 454 times.
✓ Branch 38 taken 676 times.
✓ Branch 39 taken 580 times.
✓ Branch 40 taken 104 times.
✓ Branch 41 taken 96 times.
✓ Branch 42 taken 52 times.
✓ Branch 43 taken 52 times.
✓ Branch 44 taken 478 times.
✓ Branch 45 taken 454 times.
✓ Branch 46 taken 676 times.
✓ Branch 47 taken 580 times.
✓ Branch 48 taken 896 times.
✓ Branch 49 taken 802 times.
✓ Branch 50 taken 176 times.
✓ Branch 51 taken 78 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.
|
295618 | if (remaining_length()) { |
| 265 | 218007 | callback(index_, length_); | |
| 266 | 218007 | index_ = length_; | |
| 267 | 218007 | } | |
| 268 | |||
| 269 | 295618 | return *this; | |
| 270 | } | ||
| 271 | |||
| 272 | // Returns true if there is nothing left to process. | ||
| 273 | bool empty() const KLEIDICV_STREAMING { return length_ == index_; } | ||
| 274 | |||
| 275 | // Returns the step value. | ||
| 276 | 541717 | size_t step() const KLEIDICV_STREAMING { return step_; } | |
| 277 | |||
| 278 | // Returns the remaining length. | ||
| 279 | 989869 | size_t remaining_length() const KLEIDICV_STREAMING { | |
| 280 | 989869 | return length_ - index_; | |
| 281 | } | ||
| 282 | |||
| 283 | private: | ||
| 284 | template <const size_t UnrollFactor, typename CallbackType> | ||
| 285 | 541717 | LoopUnroll2 &unroll_n_times(CallbackType callback) KLEIDICV_STREAMING { | |
| 286 | 541717 | const size_t n_step = UnrollFactor * step(); | |
| 287 | 541717 | size_t max_index = index_ + (remaining_length() / n_step) * n_step; | |
| 288 | |||
| 289 | // A tail mechanism is built into the single vector processing loop, if | ||
| 290 | // enabled. The single vector path is executed iteratively, and at the end | ||
| 291 | // it rewinds the loop to one vector before the end of the data, and | ||
| 292 | // executes one final vector path, so the scalar path can be omitted. | ||
| 293 | if constexpr (try_to_avoid_tail_loop<Tail> && (UnrollFactor == 1)) { | ||
| 294 | // Enter this loop only if there's enough data for a full vector | ||
| 295 |
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 919 times.
✓ Branch 9 taken 779 times.
✓ Branch 10 taken 517 times.
✓ Branch 11 taken 10497 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 5958 times.
✓ Branch 18 taken 508 times.
✓ Branch 19 taken 442 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 11420 times.
✓ Branch 26 taken 76 times.
✓ Branch 27 taken 3154 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 340 times.
✓ Branch 50 taken 20 times.
✓ Branch 51 taken 162 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.
|
114218 | if (length_ >= n_step) { |
| 296 | // External loop only ends when all data has been processed | ||
| 297 |
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 1429 times.
✓ Branch 9 taken 779 times.
✓ Branch 10 taken 15485 times.
✓ Branch 11 taken 10497 times.
✓ Branch 12 taken 1536 times.
✓ Branch 13 taken 788 times.
✓ Branch 14 taken 30396 times.
✓ Branch 15 taken 20324 times.
✓ Branch 16 taken 10726 times.
✓ Branch 17 taken 5958 times.
✓ Branch 18 taken 486 times.
✓ Branch 19 taken 442 times.
✓ Branch 20 taken 2806 times.
✓ Branch 21 taken 1644 times.
✓ Branch 22 taken 854 times.
✓ Branch 23 taken 550 times.
✓ Branch 24 taken 20680 times.
✓ Branch 25 taken 11420 times.
✓ Branch 26 taken 4694 times.
✓ Branch 27 taken 3154 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 486 times.
✓ Branch 49 taken 340 times.
✓ Branch 50 taken 202 times.
✓ Branch 51 taken 162 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.
|
246653 | while (index_ < length_) { |
| 298 | // Internal loop checks if the vector path can be executed | ||
| 299 |
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 11639 times.
✓ Branch 9 taken 1429 times.
✓ Branch 10 taken 871001 times.
✓ Branch 11 taken 15485 times.
✓ Branch 12 taken 21824 times.
✓ Branch 13 taken 1536 times.
✓ Branch 14 taken 3476828 times.
✓ Branch 15 taken 30396 times.
✓ Branch 16 taken 199720 times.
✓ Branch 17 taken 10726 times.
✓ Branch 18 taken 1358 times.
✓ Branch 19 taken 486 times.
✓ Branch 20 taken 95058 times.
✓ Branch 21 taken 2806 times.
✓ Branch 22 taken 2778 times.
✓ Branch 23 taken 854 times.
✓ Branch 24 taken 24782 times.
✓ Branch 25 taken 20680 times.
✓ Branch 26 taken 4510 times.
✓ Branch 27 taken 4694 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 1502 times.
✓ Branch 49 taken 486 times.
✓ Branch 50 taken 774 times.
✓ Branch 51 taken 202 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.
|
5224627 | while (index_ < max_index) { |
| 300 | 5072093 | callback(index_); | |
| 301 | 5072093 | index_ += n_step; | |
| 302 | } | ||
| 303 | // Check if a final iteration is needed. The double loop is needed to | ||
| 304 | // avoid the repetition of the callback function, which is usually | ||
| 305 | // inlined into the binary. (Save some code space) | ||
| 306 |
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 779 times.
✓ Branch 9 taken 650 times.
✓ Branch 10 taken 10329 times.
✓ Branch 11 taken 5156 times.
✓ Branch 12 taken 788 times.
✓ Branch 13 taken 748 times.
✓ Branch 14 taken 20324 times.
✓ Branch 15 taken 10072 times.
✓ Branch 16 taken 5958 times.
✓ Branch 17 taken 4768 times.
✓ Branch 18 taken 442 times.
✓ Branch 19 taken 44 times.
✓ Branch 20 taken 1644 times.
✓ Branch 21 taken 1162 times.
✓ Branch 22 taken 550 times.
✓ Branch 23 taken 304 times.
✓ Branch 24 taken 11006 times.
✓ Branch 25 taken 9674 times.
✓ Branch 26 taken 2542 times.
✓ Branch 27 taken 2152 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 340 times.
✓ Branch 49 taken 146 times.
✓ Branch 50 taken 162 times.
✓ Branch 51 taken 40 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.
|
152534 | if (remaining_length()) { |
| 307 | 61927 | index_ = length_ - n_step; | |
| 308 | 61927 | max_index = length_; | |
| 309 | 61927 | } | |
| 310 | } | ||
| 311 | 94119 | } | |
| 312 | } else { | ||
| 313 |
112/112✓ Branch 0 taken 11632 times.
✓ Branch 1 taken 58308 times.
✓ Branch 2 taken 11897 times.
✓ Branch 3 taken 57961 times.
✓ Branch 4 taken 10340 times.
✓ Branch 5 taken 47847 times.
✓ Branch 6 taken 11434 times.
✓ Branch 7 taken 46467 times.
✓ Branch 8 taken 52055 times.
✓ Branch 9 taken 34169 times.
✓ Branch 10 taken 4319 times.
✓ Branch 11 taken 24765 times.
✓ Branch 12 taken 26839 times.
✓ Branch 13 taken 18156 times.
✓ Branch 14 taken 4382 times.
✓ Branch 15 taken 15392 times.
✓ Branch 16 taken 1053 times.
✓ Branch 17 taken 4354 times.
✓ Branch 18 taken 1672 times.
✓ Branch 19 taken 1682 times.
✓ Branch 20 taken 4140 times.
✓ Branch 21 taken 6824 times.
✓ Branch 22 taken 4278 times.
✓ Branch 23 taken 6614 times.
✓ Branch 24 taken 3222 times.
✓ Branch 25 taken 3554 times.
✓ Branch 26 taken 690 times.
✓ Branch 27 taken 2102 times.
✓ Branch 28 taken 2318 times.
✓ Branch 29 taken 4406 times.
✓ Branch 30 taken 2048 times.
✓ Branch 31 taken 2366 times.
✓ Branch 32 taken 46096 times.
✓ Branch 33 taken 5482 times.
✓ Branch 34 taken 11548 times.
✓ Branch 35 taken 5386 times.
✓ Branch 36 taken 3254 times.
✓ Branch 37 taken 1406 times.
✓ Branch 38 taken 3746 times.
✓ Branch 39 taken 1730 times.
✓ Branch 40 taken 23124 times.
✓ Branch 41 taken 1686 times.
✓ Branch 42 taken 3402 times.
✓ Branch 43 taken 1692 times.
✓ Branch 44 taken 3182 times.
✓ Branch 45 taken 1508 times.
✓ Branch 46 taken 3770 times.
✓ Branch 47 taken 1832 times.
✓ Branch 48 taken 50536 times.
✓ Branch 49 taken 12830 times.
✓ Branch 50 taken 14968 times.
✓ Branch 51 taken 11378 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.
|
814248 | while (index_ < max_index) { |
| 314 | 386749 | callback(index_); | |
| 315 | 386749 | index_ += n_step; | |
| 316 | } | ||
| 317 | } | ||
| 318 | |||
| 319 | 541717 | return *this; | |
| 320 | 541717 | } | |
| 321 | |||
| 322 | size_t length_; | ||
| 323 | size_t step_; | ||
| 324 | size_t index_; | ||
| 325 | }; // end of class LoopUnroll2 | ||
| 326 | |||
| 327 | // Check whether any of the arguments are null pointers. | ||
| 328 | template <typename... Pointers> | ||
| 329 | 18220 | bool any_null(Pointers... pointers) KLEIDICV_STREAMING { | |
| 330 |
12/12✓ Branch 0 taken 296 times.
✓ Branch 1 taken 2724 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 260 times.
✓ Branch 4 taken 264 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 260 times.
✓ Branch 8 taken 260 times.
✓ Branch 9 taken 4 times.
✓ Branch 10 taken 4 times.
✓ Branch 11 taken 256 times.
|
18220 | return (... || (pointers == nullptr)); |
| 331 | } | ||
| 332 | |||
| 333 | #define CHECK_POINTERS(...) \ | ||
| 334 | do { \ | ||
| 335 | if (KLEIDICV_TARGET_NAMESPACE::any_null(__VA_ARGS__)) { \ | ||
| 336 | return KLEIDICV_ERROR_NULL_POINTER; \ | ||
| 337 | } \ | ||
| 338 | } while (false) | ||
| 339 | |||
| 340 | template <typename AlignType, typename Value> | ||
| 341 | 70588 | bool is_misaligned(Value v) KLEIDICV_STREAMING { | |
| 342 | 70588 | constexpr size_t kMask = alignof(AlignType) - 1; | |
| 343 | static_assert(kMask == 0b0001 || kMask == 0b0011 || kMask == 0b0111 || | ||
| 344 | kMask == 0b1111); | ||
| 345 | 141176 | return (v & kMask) != 0; | |
| 346 | 70588 | } | |
| 347 | |||
| 348 | // Return value aligned up to the next multiple of alignment | ||
| 349 | // Assumes alignment is a power of two. | ||
| 350 | template <typename T> | ||
| 351 | 13933 | T align_up(T value, size_t alignment) KLEIDICV_STREAMING { | |
| 352 | 13933 | return (value + alignment - 1) & ~(alignment - 1); | |
| 353 | } | ||
| 354 | |||
| 355 | template <typename T> | ||
| 356 | 6048 | T *align_up(T *value, size_t alignment) KLEIDICV_STREAMING { | |
| 357 | // NOLINTBEGIN(performance-no-int-to-ptr) | ||
| 358 | 6048 | return reinterpret_cast<T *>( | |
| 359 | 6048 | align_up(reinterpret_cast<uintptr_t>(value), alignment)); | |
| 360 | // NOLINTEND(performance-no-int-to-ptr) | ||
| 361 | } | ||
| 362 | |||
| 363 | // Specialisation for when stride misalignment is possible. | ||
| 364 | template <typename T> | ||
| 365 | 67533 | std::enable_if_t<alignof(T) != 1, kleidicv_error_t> check_pointer_and_stride( | |
| 366 | T *pointer, size_t stride, size_t height) KLEIDICV_STREAMING { | ||
| 367 |
24/24✓ Branch 0 taken 19146 times.
✓ Branch 1 taken 305 times.
✓ Branch 2 taken 12709 times.
✓ Branch 3 taken 241 times.
✓ Branch 4 taken 10096 times.
✓ Branch 5 taken 228 times.
✓ Branch 6 taken 5188 times.
✓ Branch 7 taken 192 times.
✓ Branch 8 taken 5364 times.
✓ Branch 9 taken 84 times.
✓ Branch 10 taken 3824 times.
✓ Branch 11 taken 68 times.
✓ Branch 12 taken 2112 times.
✓ Branch 13 taken 20 times.
✓ Branch 14 taken 1452 times.
✓ Branch 15 taken 12 times.
✓ Branch 16 taken 2612 times.
✓ Branch 17 taken 20 times.
✓ Branch 18 taken 1952 times.
✓ Branch 19 taken 12 times.
✓ Branch 20 taken 1264 times.
✓ Branch 21 taken 16 times.
✓ Branch 22 taken 608 times.
✓ Branch 23 taken 8 times.
|
67533 | if (pointer == nullptr) { |
| 368 | 1206 | return KLEIDICV_ERROR_NULL_POINTER; | |
| 369 | } | ||
| 370 |
48/48✓ Branch 0 taken 17141 times.
✓ Branch 1 taken 2005 times.
✓ Branch 2 taken 17001 times.
✓ Branch 3 taken 140 times.
✓ Branch 4 taken 11767 times.
✓ Branch 5 taken 942 times.
✓ Branch 6 taken 11671 times.
✓ Branch 7 taken 96 times.
✓ Branch 8 taken 9112 times.
✓ Branch 9 taken 984 times.
✓ Branch 10 taken 9016 times.
✓ Branch 11 taken 96 times.
✓ Branch 12 taken 4832 times.
✓ Branch 13 taken 356 times.
✓ Branch 14 taken 4756 times.
✓ Branch 15 taken 76 times.
✓ Branch 16 taken 4856 times.
✓ Branch 17 taken 508 times.
✓ Branch 18 taken 4768 times.
✓ Branch 19 taken 88 times.
✓ Branch 20 taken 3528 times.
✓ Branch 21 taken 296 times.
✓ Branch 22 taken 3456 times.
✓ Branch 23 taken 72 times.
✓ Branch 24 taken 1976 times.
✓ Branch 25 taken 136 times.
✓ Branch 26 taken 1960 times.
✓ Branch 27 taken 16 times.
✓ Branch 28 taken 1396 times.
✓ Branch 29 taken 56 times.
✓ Branch 30 taken 1388 times.
✓ Branch 31 taken 8 times.
✓ Branch 32 taken 2436 times.
✓ Branch 33 taken 176 times.
✓ Branch 34 taken 2420 times.
✓ Branch 35 taken 16 times.
✓ Branch 36 taken 1856 times.
✓ Branch 37 taken 96 times.
✓ Branch 38 taken 1848 times.
✓ Branch 39 taken 8 times.
✓ Branch 40 taken 1128 times.
✓ Branch 41 taken 136 times.
✓ Branch 42 taken 1112 times.
✓ Branch 43 taken 16 times.
✓ Branch 44 taken 552 times.
✓ Branch 45 taken 56 times.
✓ Branch 46 taken 544 times.
✓ Branch 47 taken 8 times.
|
66327 | if (height > 1 && is_misaligned<T>(stride)) { |
| 371 | 640 | return KLEIDICV_ERROR_ALIGNMENT; | |
| 372 | } | ||
| 373 | 65687 | return KLEIDICV_OK; | |
| 374 | 67533 | } | |
| 375 | |||
| 376 | // Specialisation for when stride misalignment is impossible. | ||
| 377 | template <typename T> | ||
| 378 | 73272 | std::enable_if_t<alignof(T) == 1, kleidicv_error_t> check_pointer_and_stride( | |
| 379 | T *pointer, size_t /*stride*/, size_t /*height*/) KLEIDICV_STREAMING { | ||
| 380 |
8/8✓ Branch 0 taken 34947 times.
✓ Branch 1 taken 1232 times.
✓ Branch 2 taken 28967 times.
✓ Branch 3 taken 908 times.
✓ Branch 4 taken 4171 times.
✓ Branch 5 taken 40 times.
✓ Branch 6 taken 2983 times.
✓ Branch 7 taken 24 times.
|
73272 | if (pointer == nullptr) { |
| 381 | 2204 | return KLEIDICV_ERROR_NULL_POINTER; | |
| 382 | } | ||
| 383 | 71068 | return KLEIDICV_OK; | |
| 384 | 73272 | } | |
| 385 | |||
| 386 | #define CHECK_POINTER_AND_STRIDE(pointer, stride, height) \ | ||
| 387 | do { \ | ||
| 388 | if (kleidicv_error_t ptr_stride_err = \ | ||
| 389 | KLEIDICV_TARGET_NAMESPACE::check_pointer_and_stride( \ | ||
| 390 | pointer, stride, height)) { \ | ||
| 391 | return ptr_stride_err; \ | ||
| 392 | } \ | ||
| 393 | } while (false) | ||
| 394 | |||
| 395 | #define MAKE_POINTER_CHECK_ALIGNMENT(ElementType, name, from) \ | ||
| 396 | if constexpr (alignof(ElementType) > 1) { \ | ||
| 397 | if (KLEIDICV_TARGET_NAMESPACE::is_misaligned<ElementType>( \ | ||
| 398 | reinterpret_cast<uintptr_t>(from))) { \ | ||
| 399 | return KLEIDICV_ERROR_ALIGNMENT; \ | ||
| 400 | } \ | ||
| 401 | } \ | ||
| 402 | ElementType *name = reinterpret_cast<ElementType *>(from) | ||
| 403 | |||
| 404 | // Check whether the image size is acceptable by limiting it. | ||
| 405 | #define CHECK_IMAGE_SIZE(width, height) \ | ||
| 406 | do { \ | ||
| 407 | size_t image_size = 0; \ | ||
| 408 | if (__builtin_mul_overflow(width, height, &image_size)) { \ | ||
| 409 | return KLEIDICV_ERROR_RANGE; \ | ||
| 410 | } \ | ||
| 411 | \ | ||
| 412 | if (image_size > KLEIDICV_MAX_IMAGE_PIXELS) { \ | ||
| 413 | return KLEIDICV_ERROR_RANGE; \ | ||
| 414 | } \ | ||
| 415 | } while (false) | ||
| 416 | |||
| 417 | // Check whether the rectangle size is acceptable by limiting it. | ||
| 418 | #define CHECK_RECTANGLE_SIZE(rect) CHECK_IMAGE_SIZE(rect.width, rect.height) | ||
| 419 | |||
| 420 | } // namespace KLEIDICV_TARGET_NAMESPACE | ||
| 421 | |||
| 422 | #endif // KLEIDICV_UTILS_H | ||
| 423 |