2 * Copyright (c) 2011, 2012 Nicira, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
24 #include "byte-order.h"
25 #include "command-line.h"
33 check_log_2_floor(uint32_t x
, int n
)
35 if (log_2_floor(x
) != n
) {
36 fprintf(stderr
, "log_2_floor(%"PRIu32
") is %d but should be %d\n",
37 x
, log_2_floor(x
), n
);
43 test_log_2_floor(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
47 for (n
= 0; n
< 32; n
++) {
48 /* Check minimum x such that f(x) == n. */
49 check_log_2_floor(1 << n
, n
);
51 /* Check maximum x such that f(x) == n. */
52 check_log_2_floor((1 << n
) | ((1 << n
) - 1), n
);
54 /* Check a random value in the middle. */
55 check_log_2_floor((random_uint32() & ((1 << n
) - 1)) | (1 << n
), n
);
58 /* log_2_floor(0) is undefined, so don't check it. */
62 check_ctz(uint32_t x
, int n
)
65 fprintf(stderr
, "ctz(%"PRIu32
") is %d but should be %d\n",
72 test_ctz(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
76 for (n
= 0; n
< 32; n
++) {
77 /* Check minimum x such that f(x) == n. */
80 /* Check maximum x such that f(x) == n. */
81 check_ctz(UINT32_MAX
<< n
, n
);
83 /* Check a random value in the middle. */
84 check_ctz((random_uint32() | 1) << n
, n
);
92 shuffle(unsigned int *p
, size_t n
)
94 for (; n
> 1; n
--, p
++) {
95 unsigned int *q
= &p
[rand() % n
];
96 unsigned int tmp
= *p
;
103 check_popcount(uint32_t x
, int n
)
105 if (popcount(x
) != n
) {
106 fprintf(stderr
, "popcount(%#"PRIx32
") is %d but should be %d\n",
113 test_popcount(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
115 unsigned int bits
[32];
118 for (i
= 0; i
< ARRAY_SIZE(bits
); i
++) {
122 check_popcount(0, 0);
124 for (i
= 0; i
< 1000; i
++) {
128 shuffle(bits
, ARRAY_SIZE(bits
));
129 for (j
= 0; j
< 32; j
++) {
131 check_popcount(x
, j
+ 1);
133 assert(x
== UINT32_MAX
);
135 shuffle(bits
, ARRAY_SIZE(bits
));
136 for (j
= 31; j
>= 0; j
--) {
138 check_popcount(x
, j
);
144 /* Returns the sum of the squares of the first 'n' positive integers. */
146 sum_of_squares(int n
)
148 return n
* (n
+ 1) * (2 * n
+ 1) / 6;
152 test_bitwise_copy(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
154 unsigned int n_loops
;
160 for (n_bits
= 0; n_bits
<= 64; n_bits
++) {
161 for (src_ofs
= 0; src_ofs
< 64 - n_bits
; src_ofs
++) {
162 for (dst_ofs
= 0; dst_ofs
< 64 - n_bits
; dst_ofs
++) {
163 ovs_be64 src
= htonll(random_uint64());
164 ovs_be64 dst
= htonll(random_uint64());
165 ovs_be64 orig_dst
= dst
;
171 uint64_t mask
= (UINT64_C(1) << n_bits
) - 1;
172 expect
= orig_dst
& ~htonll(mask
<< dst_ofs
);
173 expect
|= htonll(((ntohll(src
) >> src_ofs
) & mask
)
177 bitwise_copy(&src
, sizeof src
, src_ofs
,
178 &dst
, sizeof dst
, dst_ofs
,
181 fprintf(stderr
,"copy_bits(0x%016"PRIx64
",8,%d, "
182 "0x%016"PRIx64
",8,%d, %d) yielded 0x%016"PRIx64
" "
183 "instead of the expected 0x%016"PRIx64
"\n",
184 ntohll(src
), src_ofs
,
185 ntohll(orig_dst
), dst_ofs
,
187 ntohll(dst
), ntohll(expect
));
196 if (n_loops
!= sum_of_squares(64)) {
202 test_bitwise_zero(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
204 unsigned int n_loops
;
209 for (n_bits
= 0; n_bits
<= 64; n_bits
++) {
210 for (dst_ofs
= 0; dst_ofs
< 64 - n_bits
; dst_ofs
++) {
211 ovs_be64 dst
= htonll(random_uint64());
212 ovs_be64 orig_dst
= dst
;
218 uint64_t mask
= (UINT64_C(1) << n_bits
) - 1;
219 expect
= orig_dst
& ~htonll(mask
<< dst_ofs
);
222 bitwise_zero(&dst
, sizeof dst
, dst_ofs
, n_bits
);
224 fprintf(stderr
,"bitwise_zero(0x%016"PRIx64
",8,%d, %d) "
225 "yielded 0x%016"PRIx64
" "
226 "instead of the expected 0x%016"PRIx64
"\n",
227 ntohll(orig_dst
), dst_ofs
,
229 ntohll(dst
), ntohll(expect
));
237 if (n_loops
!= 64 * (64 + 1) / 2) {
243 test_bitwise_one(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
245 unsigned int n_loops
;
250 for (n_bits
= 0; n_bits
<= 64; n_bits
++) {
251 for (dst_ofs
= 0; dst_ofs
< 64 - n_bits
; dst_ofs
++) {
252 ovs_be64 dst
= htonll(random_uint64());
253 ovs_be64 orig_dst
= dst
;
257 expect
= htonll(UINT64_MAX
);
259 uint64_t mask
= (UINT64_C(1) << n_bits
) - 1;
260 expect
= orig_dst
| htonll(mask
<< dst_ofs
);
263 bitwise_one(&dst
, sizeof dst
, dst_ofs
, n_bits
);
265 fprintf(stderr
,"bitwise_one(0x%016"PRIx64
",8,%d, %d) "
266 "yielded 0x%016"PRIx64
" "
267 "instead of the expected 0x%016"PRIx64
"\n",
268 ntohll(orig_dst
), dst_ofs
,
270 ntohll(dst
), ntohll(expect
));
278 if (n_loops
!= 64 * (64 + 1) / 2) {
284 test_bitwise_is_all_zeros(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
288 for (n_loops
= 0; n_loops
< 100; n_loops
++) {
289 ovs_be64 x
= htonll(0);
292 for (i
= 0; i
< 64; i
++) {
296 /* Change a random 0-bit into a 1-bit. */
298 bit
= htonll(UINT64_C(1) << (random_uint32() % 64));
302 for (ofs
= 0; ofs
< 64; ofs
++) {
303 for (n
= 0; n
<= 64 - ofs
; n
++) {
309 : !(x
& htonll(((UINT64_C(1) << n
) - 1)
311 answer
= bitwise_is_all_zeros(&x
, sizeof x
, ofs
, n
);
312 if (expect
!= answer
) {
314 "bitwise_is_all_zeros(0x%016"PRIx64
",8,%d,%d "
315 "returned %s instead of %s\n",
317 answer
? "true" : "false",
318 expect
? "true" : "false");
328 test_follow_symlinks(int argc
, char *argv
[])
332 for (i
= 1; i
< argc
; i
++) {
333 char *target
= follow_symlinks(argv
[i
]);
339 static const struct command commands
[] = {
340 {"ctz", 0, 0, test_ctz
},
341 {"popcount", 0, 0, test_popcount
},
342 {"log_2_floor", 0, 0, test_log_2_floor
},
343 {"bitwise_copy", 0, 0, test_bitwise_copy
},
344 {"bitwise_zero", 0, 0, test_bitwise_zero
},
345 {"bitwise_one", 0, 0, test_bitwise_one
},
346 {"bitwise_is_all_zeros", 0, 0, test_bitwise_is_all_zeros
},
347 {"follow-symlinks", 1, INT_MAX
, test_follow_symlinks
},
352 main(int argc
, char *argv
[])
354 set_program_name(argv
[0]);
355 run_command(argc
- 1, argv
+ 1, commands
);