KleidiCV Coverage Report


Directory: ./
File: kleidicv/src/filters/median_blur_sorting_network_neon.cpp
Date: 2025-09-25 14:13:34
Exec Total Coverage
Lines: 92 92 100.0%
Functions: 133 133 100.0%
Branches: 42 42 100.0%

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 #include "kleidicv/ctypes.h"
6 #include "kleidicv/filters/filter_2d_neon.h"
7 #include "kleidicv/filters/median_blur.h"
8 #include "kleidicv/filters/process_filter_2d.h"
9 #include "kleidicv/kleidicv.h"
10 #include "kleidicv/neon.h"
11 #include "kleidicv/workspace/border_3x3.h"
12 #include "kleidicv/workspace/border_5x5.h"
13 #include "kleidicv/workspace/border_7x7.h"
14 #include "median_blur_sorting_network_3x3.h"
15 #include "median_blur_sorting_network_5x5.h"
16 #include "median_blur_sorting_network_7x7.h"
17
18 namespace kleidicv::neon {
19
20 // Primary template for Median Blur filters.
21 template <typename ScalarType, size_t KernelSize>
22 class MedianBlurSortingNetwork;
23
24 template <typename ScalarType>
25 class VectorizedComparator {
26 public:
27 using SourceVectorType = typename VecTraits<ScalarType>::VectorType;
28
29 4255498 static void compare_and_swap(SourceVectorType& left, SourceVectorType& right,
30 Monostate&) {
31 4255498 SourceVectorType max_value = vmaxq(left, right);
32 4255498 SourceVectorType min_value = vminq(left, right);
33 4255498 left = min_value;
34 4255498 right = max_value;
35 4255498 }
36
37 470532 static void min(SourceVectorType& left, SourceVectorType& right, Monostate&) {
38 470532 left = vminq(left, right);
39 470532 }
40
41 456960 static void max(SourceVectorType& left, SourceVectorType& right, Monostate&) {
42 456960 right = vmaxq(left, right);
43 456960 }
44 16064 static SourceVectorType get_min(SourceVectorType& left,
45 SourceVectorType& right, Monostate&) {
46 16064 return vminq(left, right);
47 }
48 16064 static SourceVectorType get_max(SourceVectorType& left,
49 SourceVectorType& right, Monostate&) {
50 16064 return vmaxq(left, right);
51 }
52 };
53
54 template <typename ScalarType>
55 class ScalarComparator {
56 public:
57 15767992 static void compare_and_swap(ScalarType& left, ScalarType& right,
58 Monostate&) {
59
14/14
✓ Branch 0 taken 1125597 times.
✓ Branch 1 taken 636683 times.
✓ Branch 2 taken 1755194 times.
✓ Branch 3 taken 994482 times.
✓ Branch 4 taken 1680122 times.
✓ Branch 5 taken 968778 times.
✓ Branch 6 taken 1679672 times.
✓ Branch 7 taken 969228 times.
✓ Branch 8 taken 1117913 times.
✓ Branch 9 taken 639447 times.
✓ Branch 10 taken 1115893 times.
✓ Branch 11 taken 641467 times.
✓ Branch 12 taken 1555010 times.
✓ Branch 13 taken 888506 times.
15767992 if (left > right) {
60 5738591 std::swap(left, right);
61 5738591 }
62 15767992 }
63
64 1702384 static void min(ScalarType& left, ScalarType& right, Monostate&) {
65 1702384 left = std::min(left, right);
66 1702384 }
67
68 1648288 static void max(ScalarType& left, ScalarType& right, Monostate&) {
69 1648288 right = std::max(left, right);
70 1648288 }
71 34560 static ScalarType get_min(ScalarType& left, ScalarType& right, Monostate&) {
72 34560 return std::min(left, right);
73 }
74 34560 static ScalarType get_max(ScalarType& left, ScalarType& right, Monostate&) {
75 34560 return std::max(left, right);
76 }
77 };
78
79 // Template for Median Blur 3x3 filters.
80 template <typename ScalarType>
81 class MedianBlurSortingNetwork<ScalarType, 3> {
82 public:
83 using SourceType = ScalarType;
84 using DestinationType = SourceType;
85 using SourceVectorType = typename VecTraits<SourceType>::VectorType;
86 using DestinationVectorType = typename VecTraits<DestinationType>::VectorType;
87
88 template <typename KernelWindowFunctor>
89 1076 void vector_path(KernelWindowFunctor& KernelWindow,
90 DestinationVectorType& output_vec) const {
91 1076 Monostate ctx;
92 1076 sorting_network3x3_single_row<VectorizedComparator<ScalarType>>(
93 1076 KernelWindow, output_vec, ctx);
94 1076 }
95
96 template <typename KernelWindowFunctor>
97 3478 void vector_path_for_dual_row_handling(
98 KernelWindowFunctor& KernelWindow, DestinationVectorType& output_vec_0,
99 DestinationVectorType& output_vec_1) const {
100 3478 Monostate ctx;
101 3478 sorting_network3x3_dual_rows<VectorizedComparator<ScalarType>>(
102 3478 KernelWindow, output_vec_0, output_vec_1, ctx);
103 3478 }
104
105 template <typename KernelWindowFunctor>
106 1168 void scalar_path(KernelWindowFunctor& KernelWindow,
107 DestinationType& output_vec) const {
108 1168 Monostate ctx;
109 1168 sorting_network3x3_single_row<ScalarComparator<ScalarType>>(
110 1168 KernelWindow, output_vec, ctx);
111 1168 }
112
113 template <typename KernelWindowFunctor>
114 8056 void scalar_path_for_dual_row_handling(KernelWindowFunctor& KernelWindow,
115 DestinationType& output_vec0,
116 DestinationType& output_vec1) const {
117 8056 Monostate ctx;
118 8056 sorting_network3x3_dual_rows<ScalarComparator<ScalarType>>(
119 8056 KernelWindow, output_vec0, output_vec1, ctx);
120 8056 }
121 }; // end of class MedianBlurSortingNetwork<ScalarType, 3>
122
123 // Template for Median Blur 5x5 filters.
124 template <typename ScalarType>
125 class MedianBlurSortingNetwork<ScalarType, 5> {
126 public:
127 using SourceType = ScalarType;
128 using DestinationType = SourceType;
129 using SourceVectorType = typename VecTraits<SourceType>::VectorType;
130 using DestinationVectorType = typename VecTraits<DestinationType>::VectorType;
131
132 template <typename KernelWindowFunctor>
133 11308 void vector_path(KernelWindowFunctor& KernelWindow,
134 DestinationVectorType& output_vec) const {
135 11308 Monostate ctx;
136 22616 sorting_network5x5<VectorizedComparator<ScalarType>>(KernelWindow,
137 11308 output_vec, ctx);
138 11308 }
139
140 template <typename KernelWindowFunctor>
141 32136 void scalar_path(KernelWindowFunctor& KernelWindow,
142 DestinationType& dst) const {
143 32136 Monostate ctx;
144 32136 sorting_network5x5<ScalarComparator<ScalarType>>(KernelWindow, dst, ctx);
145 32136 }
146 }; // end of class MedianBlurSortingNetwork<ScalarType, 5>
147
148 // Template for Median Blur 7x7 filters.
149 template <typename ScalarType>
150 class MedianBlurSortingNetwork<ScalarType, 7> {
151 public:
152 using SourceType = ScalarType;
153 using DestinationType = SourceType;
154 using SourceVectorType = typename VecTraits<SourceType>::VectorType;
155 using DestinationVectorType = typename VecTraits<DestinationType>::VectorType;
156
157 template <typename KernelWindowFunctor>
158 13572 void vector_path(KernelWindowFunctor& KernelWindow,
159 DestinationVectorType& dst) const {
160 13572 Monostate ctx;
161 13572 sorting_network7x7<VectorizedComparator<ScalarType>>(KernelWindow, dst,
162 ctx);
163 13572 }
164
165 template <typename KernelWindowFunctor>
166 54096 void scalar_path(KernelWindowFunctor& KernelWindow,
167 DestinationType& dst) const {
168 54096 Monostate ctx;
169 54096 sorting_network7x7<ScalarComparator<ScalarType>>(KernelWindow, dst, ctx);
170 54096 }
171 }; // end of class MedianBlurSortingNetworkSortingNetwork<ScalarType, 7>
172
173 template <typename T>
174 1610 kleidicv_error_t median_blur_sorting_network_stripe(
175 const T* src, size_t src_stride, T* dst, size_t dst_stride, size_t width,
176 size_t height, size_t y_begin, size_t y_end, size_t channels,
177 size_t kernel_width, [[maybe_unused]] size_t kernel_height,
178 FixedBorderType border_type) {
179 1610 Rectangle rect{width, height};
180 1610 Rows<const T> src_rows{src, src_stride, channels};
181 1610 Rows<T> dst_rows{dst, dst_stride, channels};
182
183
14/14
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 130 times.
✓ Branch 2 taken 98 times.
✓ Branch 3 taken 159 times.
✓ Branch 4 taken 98 times.
✓ Branch 5 taken 159 times.
✓ Branch 6 taken 98 times.
✓ Branch 7 taken 159 times.
✓ Branch 8 taken 64 times.
✓ Branch 9 taken 130 times.
✓ Branch 10 taken 64 times.
✓ Branch 11 taken 130 times.
✓ Branch 12 taken 98 times.
✓ Branch 13 taken 159 times.
1610 if (kernel_width == 3) {
184 584 MedianBlurSortingNetwork<T, 3> median_filter;
185 584 Filter2D3x3<MedianBlurSortingNetwork<T, 3>> filter{median_filter};
186 1168 process_filter2d_by_dual_rows(rect, y_begin, y_end, src_rows, dst_rows,
187 584 border_type, filter);
188 584 return KLEIDICV_OK;
189 584 }
190
191
14/14
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 84 times.
✓ Branch 3 taken 75 times.
✓ Branch 4 taken 84 times.
✓ Branch 5 taken 75 times.
✓ Branch 6 taken 84 times.
✓ Branch 7 taken 75 times.
✓ Branch 8 taken 66 times.
✓ Branch 9 taken 64 times.
✓ Branch 10 taken 66 times.
✓ Branch 11 taken 64 times.
✓ Branch 12 taken 84 times.
✓ Branch 13 taken 75 times.
1026 if (kernel_width == 5) {
192 534 MedianBlurSortingNetwork<T, 5> median_filter;
193 534 Filter2D5x5<MedianBlurSortingNetwork<T, 5>> filter{median_filter};
194 1068 process_filter2d(rect, y_begin, y_end, src_rows, dst_rows, border_type,
195 534 filter);
196 534 return KLEIDICV_OK;
197 534 }
198
199 492 MedianBlurSortingNetwork<T, 7> median_filter;
200 492 Filter2D7x7<MedianBlurSortingNetwork<T, 7>> filter{median_filter};
201 984 process_filter2d(rect, y_begin, y_end, src_rows, dst_rows, border_type,
202 492 filter);
203 492 return KLEIDICV_OK;
204 1610 }
205
206 #define KLEIDICV_INSTANTIATE_TEMPLATE(type) \
207 template KLEIDICV_TARGET_FN_ATTRS kleidicv_error_t \
208 median_blur_sorting_network_stripe<type>( \
209 const type* src, size_t src_stride, type* dst, size_t dst_stride, \
210 size_t width, size_t height, size_t y_begin, size_t y_end, \
211 size_t channels, size_t kernel_width, size_t kernel_height, \
212 FixedBorderType border_type)
213
214 KLEIDICV_INSTANTIATE_TEMPLATE(int8_t);
215 KLEIDICV_INSTANTIATE_TEMPLATE(uint8_t);
216 KLEIDICV_INSTANTIATE_TEMPLATE(int16_t);
217 KLEIDICV_INSTANTIATE_TEMPLATE(uint16_t);
218 KLEIDICV_INSTANTIATE_TEMPLATE(int32_t);
219 KLEIDICV_INSTANTIATE_TEMPLATE(uint32_t);
220 KLEIDICV_INSTANTIATE_TEMPLATE(float);
221
222 } // namespace kleidicv::neon
223