]>
Commit | Line | Data |
---|---|---|
97020474 | 1 | /* Measure strncmp functions. |
bfff8b1b | 2 | Copyright (C) 2013-2017 Free Software Foundation, Inc. |
97020474 SP |
3 | This file is part of the GNU C Library. |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public | |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
16 | License along with the GNU C Library; if not, see | |
17 | <http://www.gnu.org/licenses/>. */ | |
18 | ||
19 | #define TEST_MAIN | |
cee82e70 SL |
20 | #ifdef WIDE |
21 | # define TEST_NAME "wcsncmp" | |
22 | #else | |
23 | # define TEST_NAME "strncmp" | |
24 | #endif /* !WIDE */ | |
97020474 SP |
25 | #include "bench-string.h" |
26 | ||
cee82e70 SL |
27 | #ifdef WIDE |
28 | # include <wchar.h> | |
97020474 | 29 | |
cee82e70 SL |
30 | # define L(str) L##str |
31 | # define STRNCMP wcsncmp | |
32 | # define SIMPLE_STRNCMP simple_wcsncmp | |
33 | # define STUPID_STRNCMP stupid_wcsncmp | |
34 | # define CHAR wchar_t | |
35 | # define CHARBYTES 4 | |
97020474 | 36 | |
cee82e70 SL |
37 | /* Wcsncmp uses signed semantics for comparison, not unsigned. |
38 | Avoid using substraction since possible overflow. */ | |
39 | int | |
40 | simple_wcsncmp (const CHAR *s1, const CHAR *s2, size_t n) | |
41 | { | |
42 | wchar_t c1, c2; | |
43 | ||
44 | while (n--) | |
45 | { | |
46 | c1 = *s1++; | |
47 | c2 = *s2++; | |
48 | if (c1 == L ('\0') || c1 != c2) | |
49 | return c1 > c2 ? 1 : (c1 < c2 ? -1 : 0); | |
50 | } | |
51 | return 0; | |
52 | } | |
53 | ||
54 | int | |
55 | stupid_wcsncmp (const CHAR *s1, const CHAR *s2, size_t n) | |
56 | { | |
57 | wchar_t c1, c2; | |
58 | size_t ns1 = wcsnlen (s1, n) + 1, ns2 = wcsnlen (s2, n) + 1; | |
59 | ||
60 | n = ns1 < n ? ns1 : n; | |
61 | n = ns2 < n ? ns2 : n; | |
62 | ||
63 | while (n--) | |
64 | { | |
65 | c1 = *s1++; | |
66 | c2 = *s2++; | |
67 | if (c1 != c2) | |
68 | return c1 > c2 ? 1 : -1; | |
69 | } | |
70 | return 0; | |
71 | } | |
72 | ||
73 | #else | |
74 | # define L(str) str | |
75 | # define STRNCMP strncmp | |
76 | # define SIMPLE_STRNCMP simple_strncmp | |
77 | # define STUPID_STRNCMP stupid_strncmp | |
78 | # define CHAR char | |
79 | # define CHARBYTES 1 | |
80 | ||
81 | /* Strncmp uses unsigned semantics for comparison. */ | |
97020474 SP |
82 | int |
83 | simple_strncmp (const char *s1, const char *s2, size_t n) | |
84 | { | |
85 | int ret = 0; | |
86 | ||
87 | while (n-- && (ret = *(unsigned char *) s1 - * (unsigned char *) s2++) == 0 | |
88 | && *s1++); | |
89 | return ret; | |
90 | } | |
91 | ||
92 | int | |
93 | stupid_strncmp (const char *s1, const char *s2, size_t n) | |
94 | { | |
95 | size_t ns1 = strnlen (s1, n) + 1, ns2 = strnlen (s2, n) + 1; | |
96 | int ret = 0; | |
97 | ||
98 | n = ns1 < n ? ns1 : n; | |
99 | n = ns2 < n ? ns2 : n; | |
cee82e70 | 100 | while (n-- && (ret = *(unsigned char *) s1++ - *(unsigned char *) s2++) == 0); |
97020474 SP |
101 | return ret; |
102 | } | |
103 | ||
cee82e70 SL |
104 | #endif /* !WIDE */ |
105 | ||
106 | typedef int (*proto_t) (const CHAR *, const CHAR *, size_t); | |
107 | ||
108 | IMPL (STUPID_STRNCMP, 0) | |
109 | IMPL (SIMPLE_STRNCMP, 0) | |
110 | IMPL (STRNCMP, 1) | |
111 | ||
112 | ||
97020474 | 113 | static void |
cee82e70 | 114 | do_one_test (impl_t *impl, const CHAR *s1, const CHAR *s2, size_t n, |
97020474 SP |
115 | int exp_result) |
116 | { | |
44558701 WN |
117 | size_t i, iters = INNER_LOOP_ITERS; |
118 | timing_t start, stop, cur; | |
119 | ||
120 | TIMING_NOW (start); | |
121 | for (i = 0; i < iters; ++i) | |
97020474 | 122 | { |
44558701 | 123 | CALL (impl, s1, s2, n); |
97020474 | 124 | } |
44558701 WN |
125 | TIMING_NOW (stop); |
126 | ||
127 | TIMING_DIFF (cur, start, stop); | |
128 | ||
129 | TIMING_PRINT_MEAN ((double) cur, (double) iters); | |
97020474 SP |
130 | } |
131 | ||
132 | static void | |
133 | do_test_limit (size_t align1, size_t align2, size_t len, size_t n, int max_char, | |
134 | int exp_result) | |
135 | { | |
136 | size_t i, align_n; | |
cee82e70 | 137 | CHAR *s1, *s2; |
97020474 SP |
138 | |
139 | if (n == 0) | |
140 | { | |
cee82e70 SL |
141 | s1 = (CHAR *) (buf1 + page_size); |
142 | s2 = (CHAR *) (buf2 + page_size); | |
44558701 | 143 | printf ("Length %4zd/%4zd:", len, n); |
97020474 SP |
144 | |
145 | FOR_EACH_IMPL (impl, 0) | |
146 | do_one_test (impl, s1, s2, n, 0); | |
147 | ||
44558701 | 148 | putchar ('\n'); |
97020474 SP |
149 | |
150 | return; | |
151 | } | |
152 | ||
153 | align1 &= 15; | |
154 | align2 &= 15; | |
cee82e70 | 155 | align_n = (page_size - n * CHARBYTES) & 15; |
97020474 | 156 | |
cee82e70 SL |
157 | s1 = (CHAR *) (buf1 + page_size - n * CHARBYTES); |
158 | s2 = (CHAR *) (buf2 + page_size - n * CHARBYTES); | |
97020474 SP |
159 | |
160 | if (align1 < align_n) | |
cee82e70 | 161 | s1 = (CHAR *) ((char *) s1 - (align_n - align1)); |
97020474 SP |
162 | |
163 | if (align2 < align_n) | |
cee82e70 | 164 | s2 = (CHAR *) ((char *) s2 - (align_n - align2)); |
97020474 SP |
165 | |
166 | for (i = 0; i < n; i++) | |
167 | s1[i] = s2[i] = 1 + 23 * i % max_char; | |
168 | ||
169 | if (len < n) | |
170 | { | |
171 | s1[len] = 0; | |
172 | s2[len] = 0; | |
173 | if (exp_result < 0) | |
174 | s2[len] = 32; | |
175 | else if (exp_result > 0) | |
176 | s1[len] = 64; | |
177 | } | |
178 | ||
44558701 | 179 | printf ("Length %4zd/%4zd, alignment %2zd/%2zd:", len, n, align1, align2); |
97020474 SP |
180 | |
181 | FOR_EACH_IMPL (impl, 0) | |
182 | do_one_test (impl, s1, s2, n, exp_result); | |
183 | ||
44558701 | 184 | putchar ('\n'); |
97020474 SP |
185 | } |
186 | ||
187 | static void | |
188 | do_test (size_t align1, size_t align2, size_t len, size_t n, int max_char, | |
189 | int exp_result) | |
190 | { | |
191 | size_t i; | |
cee82e70 | 192 | CHAR *s1, *s2; |
97020474 SP |
193 | |
194 | if (n == 0) | |
195 | return; | |
196 | ||
cee82e70 SL |
197 | align1 &= 63; |
198 | if (align1 + (n + 1) * CHARBYTES >= page_size) | |
97020474 SP |
199 | return; |
200 | ||
201 | align2 &= 7; | |
cee82e70 | 202 | if (align2 + (n + 1) * CHARBYTES >= page_size) |
97020474 SP |
203 | return; |
204 | ||
cee82e70 SL |
205 | s1 = (CHAR *) (buf1 + align1); |
206 | s2 = (CHAR *) (buf2 + align2); | |
97020474 SP |
207 | |
208 | for (i = 0; i < n; i++) | |
cee82e70 | 209 | s1[i] = s2[i] = 1 + (23 << ((CHARBYTES - 1) * 8)) * i % max_char; |
97020474 SP |
210 | |
211 | s1[n] = 24 + exp_result; | |
212 | s2[n] = 23; | |
213 | s1[len] = 0; | |
214 | s2[len] = 0; | |
215 | if (exp_result < 0) | |
216 | s2[len] = 32; | |
217 | else if (exp_result > 0) | |
218 | s1[len] = 64; | |
219 | if (len >= n) | |
220 | s2[n - 1] -= exp_result; | |
221 | ||
44558701 | 222 | printf ("Length %4zd/%4zd, alignment %2zd/%2zd:", len, n, align1, align2); |
97020474 SP |
223 | |
224 | FOR_EACH_IMPL (impl, 0) | |
cee82e70 | 225 | do_one_test (impl, s1, s2, n, exp_result); |
97020474 | 226 | |
44558701 | 227 | putchar ('\n'); |
97020474 SP |
228 | } |
229 | ||
230 | int | |
231 | test_main (void) | |
232 | { | |
233 | size_t i; | |
234 | ||
235 | test_init (); | |
236 | ||
237 | printf ("%23s", ""); | |
238 | FOR_EACH_IMPL (impl, 0) | |
239 | printf ("\t%s", impl->name); | |
240 | putchar ('\n'); | |
241 | ||
242 | for (i =0; i < 16; ++i) | |
243 | { | |
244 | do_test (0, 0, 8, i, 127, 0); | |
245 | do_test (0, 0, 8, i, 127, -1); | |
246 | do_test (0, 0, 8, i, 127, 1); | |
247 | do_test (i, i, 8, i, 127, 0); | |
248 | do_test (i, i, 8, i, 127, 1); | |
249 | do_test (i, i, 8, i, 127, -1); | |
250 | do_test (i, 2 * i, 8, i, 127, 0); | |
251 | do_test (2 * i, i, 8, i, 127, 1); | |
252 | do_test (i, 3 * i, 8, i, 127, -1); | |
253 | do_test (0, 0, 8, i, 255, 0); | |
254 | do_test (0, 0, 8, i, 255, -1); | |
255 | do_test (0, 0, 8, i, 255, 1); | |
256 | do_test (i, i, 8, i, 255, 0); | |
257 | do_test (i, i, 8, i, 255, 1); | |
258 | do_test (i, i, 8, i, 255, -1); | |
259 | do_test (i, 2 * i, 8, i, 255, 0); | |
260 | do_test (2 * i, i, 8, i, 255, 1); | |
261 | do_test (i, 3 * i, 8, i, 255, -1); | |
262 | } | |
263 | ||
264 | for (i = 1; i < 8; ++i) | |
265 | { | |
266 | do_test (0, 0, 8 << i, 16 << i, 127, 0); | |
267 | do_test (0, 0, 8 << i, 16 << i, 127, 1); | |
268 | do_test (0, 0, 8 << i, 16 << i, 127, -1); | |
269 | do_test (0, 0, 8 << i, 16 << i, 255, 0); | |
270 | do_test (0, 0, 8 << i, 16 << i, 255, 1); | |
271 | do_test (0, 0, 8 << i, 16 << i, 255, -1); | |
272 | do_test (8 - i, 2 * i, 8 << i, 16 << i, 127, 0); | |
273 | do_test (8 - i, 2 * i, 8 << i, 16 << i, 127, 1); | |
274 | do_test (2 * i, i, 8 << i, 16 << i, 255, 0); | |
275 | do_test (2 * i, i, 8 << i, 16 << i, 255, 1); | |
276 | } | |
277 | ||
278 | do_test_limit (0, 0, 0, 0, 127, 0); | |
279 | do_test_limit (4, 0, 21, 20, 127, 0); | |
280 | do_test_limit (0, 4, 21, 20, 127, 0); | |
281 | do_test_limit (8, 0, 25, 24, 127, 0); | |
282 | do_test_limit (0, 8, 25, 24, 127, 0); | |
283 | ||
284 | for (i = 0; i < 8; ++i) | |
285 | { | |
286 | do_test_limit (0, 0, 17 - i, 16 - i, 127, 0); | |
287 | do_test_limit (0, 0, 17 - i, 16 - i, 255, 0); | |
288 | do_test_limit (0, 0, 15 - i, 16 - i, 127, 0); | |
289 | do_test_limit (0, 0, 15 - i, 16 - i, 127, 1); | |
290 | do_test_limit (0, 0, 15 - i, 16 - i, 127, -1); | |
291 | do_test_limit (0, 0, 15 - i, 16 - i, 255, 0); | |
292 | do_test_limit (0, 0, 15 - i, 16 - i, 255, 1); | |
293 | do_test_limit (0, 0, 15 - i, 16 - i, 255, -1); | |
294 | } | |
295 | ||
296 | return ret; | |
297 | } | |
298 | ||
b598e134 | 299 | #include <support/test-driver.c> |