KleidiCV Coverage Report


Directory: ./
File: kleidicv/src/resize/resize_linear_api.cpp
Date: 2026-03-05 15:57:40
Exec Total Coverage
Lines: 83 83 100.0%
Functions: 13 13 100.0%
Branches: 128 142 90.1%

Line Branch Exec Source
1 // SPDX-FileCopyrightText: 2024 - 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
2 //
3 // SPDX-License-Identifier: Apache-2.0
4
5 #include <cassert>
6
7 #include "kleidicv/dispatch.h"
8 #include "kleidicv/kleidicv.h"
9 #include "kleidicv/resize/resize_linear.h"
10 #include "kleidicv/utils.h"
11
12 #define KLEIDICV_DEFINE_C_API_ALL(name, called_name) \
13 KLEIDICV_MULTIVERSION_C_API( \
14 name, &kleidicv::neon::called_name, \
15 KLEIDICV_SVE2_IMPL_IF(kleidicv::sve2::called_name), \
16 &kleidicv::sme::called_name, &kleidicv::sme2::called_name)
17
18 #define KLEIDICV_DEFINE_C_API_NEON(name, called_name) \
19 KLEIDICV_MULTIVERSION_C_API(name, &kleidicv::neon::called_name, nullptr, \
20 nullptr, nullptr)
21
22
6/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1 times.
10 KLEIDICV_DEFINE_C_API_ALL(kleidicv_resize_2x2_stripe_u8,
23 kleidicv_resize_2x2_stripe_u8);
24
6/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1 times.
10 KLEIDICV_DEFINE_C_API_ALL(kleidicv_resize_4x4_stripe_u8,
25 kleidicv_resize_4x4_stripe_u8);
26
27
10/12
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 1 times.
10 KLEIDICV_MULTIVERSION_C_API_VECLEN(
28 kleidicv_resize_1ch_r2_stripe_u8,
29 (&kleidicv::neon::kleidicv_resize_generic_stripe_u8<2, 1>),
30 (&kleidicv::sve2::kleidicv_resize_generic_stripe_u8<2, 1>),
31 (&kleidicv::sme::kleidicv_resize_generic_stripe_u8<2, 1>),
32 (&kleidicv::sme2::kleidicv_resize_generic_stripe_u8<2, 1>), 16, 64);
33
10/12
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 1 times.
10 KLEIDICV_MULTIVERSION_C_API_VECLEN(
34 kleidicv_resize_1ch_r3_stripe_u8,
35 (&kleidicv::neon::kleidicv_resize_generic_stripe_u8<3, 1>),
36 (&kleidicv::sve2::kleidicv_resize_generic_stripe_u8<3, 1>),
37 (&kleidicv::sme::kleidicv_resize_generic_stripe_u8<3, 1>),
38 (&kleidicv::sme2::kleidicv_resize_generic_stripe_u8<3, 1>), 16, 64);
39
10/12
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 1 times.
10 KLEIDICV_MULTIVERSION_C_API_VECLEN(
40 kleidicv_resize_2ch_r2_stripe_u8,
41 (&kleidicv::neon::kleidicv_resize_generic_stripe_u8<2, 2>),
42 (&kleidicv::sve2::kleidicv_resize_generic_stripe_u8<2, 2>),
43 (&kleidicv::sme::kleidicv_resize_generic_stripe_u8<2, 2>),
44 (&kleidicv::sme2::kleidicv_resize_generic_stripe_u8<2, 2>), 16, 64);
45
10/12
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 1 times.
10 KLEIDICV_MULTIVERSION_C_API_VECLEN(
46 kleidicv_resize_2ch_r3_stripe_u8,
47 (&kleidicv::neon::kleidicv_resize_generic_stripe_u8<3, 2>),
48 (&kleidicv::sve2::kleidicv_resize_generic_stripe_u8<3, 2>),
49 (&kleidicv::sme::kleidicv_resize_generic_stripe_u8<3, 2>),
50 (&kleidicv::sme2::kleidicv_resize_generic_stripe_u8<3, 2>), 16, 64);
51
10/12
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 1 times.
10 KLEIDICV_MULTIVERSION_C_API_VECLEN(
52 kleidicv_resize_3ch_r2_stripe_u8,
53 (&kleidicv::neon::kleidicv_resize_generic_stripe_u8<2, 3>),
54 (&kleidicv::sve2::kleidicv_resize_generic_stripe_u8<2, 3>),
55 (&kleidicv::sme::kleidicv_resize_generic_stripe_u8<2, 3>),
56 (&kleidicv::sme2::kleidicv_resize_generic_stripe_u8<2, 3>), 16, 64);
57
10/12
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 1 times.
10 KLEIDICV_MULTIVERSION_C_API_VECLEN(
58 kleidicv_resize_3ch_r3_stripe_u8,
59 (&kleidicv::neon::kleidicv_resize_generic_stripe_u8<3, 3>),
60 (&kleidicv::sve2::kleidicv_resize_generic_stripe_u8<3, 3>),
61 (&kleidicv::sme::kleidicv_resize_generic_stripe_u8<3, 3>),
62 (&kleidicv::sme2::kleidicv_resize_generic_stripe_u8<3, 3>), 16, 64);
63
64
6/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1 times.
10 KLEIDICV_DEFINE_C_API_ALL(kleidicv_resize_linear_stripe_f32,
65 kleidicv_resize_linear_stripe_f32);
66
67
6/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1 times.
10 KLEIDICV_MULTIVERSION_C_API(
68 kleidicv_resize_to_quarter_u8, &kleidicv::neon::resize_to_quarter_u8,
69 KLEIDICV_SVE2_IMPL_IF(&kleidicv::sve2::resize_to_quarter_u8),
70 &kleidicv::sme::resize_to_quarter_u8,
71 KLEIDICV_SME2_IMPL_IF(&kleidicv::sme2::resize_to_quarter_u8));
72
73 extern "C" {
74
75 1275 kleidicv_error_t kleidicv_resize_linear_u8(const uint8_t *src,
76 size_t src_stride, size_t src_width,
77 size_t src_height, uint8_t *dst,
78 size_t dst_stride, size_t dst_width,
79 size_t dst_height, size_t channels) {
80
2/2
✓ Branch 0 taken 260 times.
✓ Branch 1 taken 1015 times.
1275 if (!kleidicv::resize_linear_u8_is_implemented(
81 1275 src_width, src_height, dst_width, dst_height, channels)) {
82 260 return KLEIDICV_ERROR_NOT_IMPLEMENTED;
83 }
84
85 // For upsampling, process by src rows
86 // For resize_generic, process by dst rows
87
2/2
✓ Branch 0 taken 350 times.
✓ Branch 1 taken 665 times.
1015 size_t y_end = (src_width < dst_width) ? src_height : dst_height;
88
89 2030 return kleidicv_resize_linear_stripe_u8(src, src_stride, src_width,
90 1015 src_height, 0, y_end, dst, dst_stride,
91 1015 dst_width, dst_height, channels);
92 1275 }
93
94 // This function is too complex, but disable the warning for now.
95 // NOLINTBEGIN(readability-function-cognitive-complexity)
96 2025 kleidicv_error_t kleidicv_resize_linear_stripe_u8(
97 const uint8_t *src, size_t src_stride, size_t src_width, size_t src_height,
98 size_t y_begin, size_t y_end, uint8_t *dst, size_t dst_stride,
99 size_t dst_width, size_t dst_height, size_t channels) {
100
4/4
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 2005 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 2005 times.
2025 CHECK_POINTER_AND_STRIDE(src, src_stride, src_height);
101
4/4
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 1985 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 1985 times.
2005 CHECK_POINTER_AND_STRIDE(dst, dst_stride, dst_height);
102
103
4/4
✓ Branch 0 taken 1980 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 1975 times.
1985 if (src_width == 0 || src_height == 0) {
104 10 return KLEIDICV_OK;
105 }
106
107
2/2
✓ Branch 0 taken 1455 times.
✓ Branch 1 taken 520 times.
1975 if (channels == 1) {
108
4/4
✓ Branch 0 taken 1010 times.
✓ Branch 1 taken 445 times.
✓ Branch 2 taken 80 times.
✓ Branch 3 taken 930 times.
1580 if ((src_width / 2 == dst_width || (src_width + 1) / 2 == dst_width) &&
109
2/2
✓ Branch 0 taken 125 times.
✓ Branch 1 taken 400 times.
525 (src_height / 2 == dst_height || (src_height + 1) / 2 == dst_height)) {
110 525 size_t src_begin = y_begin * 2;
111 525 size_t src_end = std::min<size_t>(src_height, y_end * 2);
112 525 size_t dst_begin = y_begin;
113 525 size_t dst_end = std::min<size_t>(dst_height, y_end);
114
115
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 495 times.
525 if (dst_begin == dst_end) {
116 30 return KLEIDICV_OK;
117 }
118
119 990 return kleidicv_resize_to_quarter_u8(
120 495 src + src_begin * src_stride, src_stride, src_width,
121 495 src_end - src_begin, dst + dst_begin * dst_stride, dst_stride,
122 495 dst_width, dst_end - dst_begin);
123 525 }
124
3/4
✓ Branch 0 taken 390 times.
✓ Branch 1 taken 540 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 390 times.
930 if (src_width * 2 == dst_width && src_height * 2 == dst_height) {
125 780 return kleidicv_resize_2x2_stripe_u8(src, src_stride, src_width,
126 390 src_height, y_begin, y_end, dst,
127 390 dst_stride);
128 }
129
3/4
✓ Branch 0 taken 290 times.
✓ Branch 1 taken 250 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 290 times.
540 if (src_width * 4 == dst_width && src_height * 4 == dst_height) {
130 580 return kleidicv_resize_4x4_stripe_u8(src, src_stride, src_width,
131 290 src_height, y_begin, y_end, dst,
132 290 dst_stride);
133 }
134
135
2/2
✓ Branch 0 taken 125 times.
✓ Branch 1 taken 125 times.
250 if (dst_width * 2 >= src_width) {
136 250 return kleidicv_resize_1ch_r2_stripe_u8(
137 125 src, src_stride, src_width, src_height, y_begin, y_end, dst,
138 125 dst_stride, dst_width, dst_height);
139 }
140 250 return kleidicv_resize_1ch_r3_stripe_u8(src, src_stride, src_width,
141 125 src_height, y_begin, y_end, dst,
142 125 dst_stride, dst_width, dst_height);
143 }
144
145
2/2
✓ Branch 0 taken 280 times.
✓ Branch 1 taken 240 times.
520 if (channels == 2) {
146
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 140 times.
280 if (dst_width * 2 >= src_width) {
147 280 return kleidicv_resize_2ch_r2_stripe_u8(
148 140 src, src_stride, src_width, src_height, y_begin, y_end, dst,
149 140 dst_stride, dst_width, dst_height);
150 }
151 280 return kleidicv_resize_2ch_r3_stripe_u8(src, src_stride, src_width,
152 140 src_height, y_begin, y_end, dst,
153 140 dst_stride, dst_width, dst_height);
154 }
155
156 assert(channels == 3);
157 480 double inverz_scale =
158 240 static_cast<double>(src_width) / static_cast<double>(dst_width);
159 // SVE variant does not handle the rightmost lanes of b and d vectors for 3
160 // channel images, so use the r3 and use the Neon variant only over 2.8
161
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 128 times.
240 if (inverz_scale < 1.8) {
162 224 return kleidicv_resize_3ch_r2_stripe_u8(src, src_stride, src_width,
163 112 src_height, y_begin, y_end, dst,
164 112 dst_stride, dst_width, dst_height);
165 }
166
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 8 times.
128 if (inverz_scale < 2.8) {
167 240 return kleidicv_resize_3ch_r3_stripe_u8(src, src_stride, src_width,
168 120 src_height, y_begin, y_end, dst,
169 120 dst_stride, dst_width, dst_height);
170 }
171 8 return kleidicv::neon::kleidicv_resize_generic_stripe_u8<3, 3>(
172 8 src, src_stride, src_width, src_height, y_begin, y_end, dst, dst_stride,
173 8 dst_width, dst_height);
174 2025 }
175 // NOLINTEND(readability-function-cognitive-complexity)
176
177 565 kleidicv_error_t kleidicv_resize_linear_f32(const float *src, size_t src_stride,
178 size_t src_width, size_t src_height,
179 float *dst, size_t dst_stride,
180 size_t dst_width, size_t dst_height,
181 size_t channels) {
182
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 485 times.
565 if (!kleidicv::resize_linear_f32_is_implemented(
183 565 src_width, src_height, dst_width, dst_height, channels)) {
184 80 return KLEIDICV_ERROR_NOT_IMPLEMENTED;
185 }
186 970 return kleidicv_resize_linear_stripe_f32(src, src_stride, src_width,
187 485 src_height, 0, src_height, dst,
188 485 dst_stride, dst_width, dst_height);
189 565 }
190
191 } // extern "C"
192