1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright © 2020 Keith Packard
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above
14  *    copyright notice, this list of conditions and the following
15  *    disclaimer in the documentation and/or other materials provided
16  *    with the distribution.
17  *
18  * 3. Neither the name of the copyright holder nor the names of its
19  *    contributors may be used to endorse or promote products derived
20  *    from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33  * OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #define _DEFAULT_SOURCE
37 #include <strings.h>
38 #include <string.h>
39 #include <stdlib.h>
40 #include <stdio.h>
41 
42 long long int
rand_long_long(void)43 rand_long_long(void)
44 {
45 	unsigned long long int r = 0;
46 	size_t x;
47 
48 	for (x = 0; x < sizeof(r) / 4; x++)
49 		r = (r << 32) | (lrand48() & 0xffffffffL);
50 	return r;
51 }
52 
53 int
slow_ffs(int i)54 slow_ffs(int i)
55 {
56 	int p;
57 	if (!i)
58 		return 0;
59 	for (p = 1; (i & (1 << (p - 1))) == 0; p++)
60 		;
61 	return p;
62 }
63 
64 int
slow_ffsl(long int i)65 slow_ffsl(long int i)
66 {
67 	int p;
68 	if (!i)
69 		return 0;
70 	for (p = 1; (i & (1L << (p - 1))) == 0; p++)
71 		;
72 	return p;
73 }
74 
75 int
slow_ffsll(long long int i)76 slow_ffsll(long long int i)
77 {
78 	int p;
79 	if (!i)
80 		return 0;
81 	for (p = 1; (i & (1LL << (p - 1))) == 0; p++)
82 		;
83 	return p;
84 }
85 
86 static int
check(long long int x,int got,int expect,char * which)87 check(long long int x, int got, int expect, char *which)
88 {
89 	long int low = x & 0xffffffffl;
90 	long int high = ((x >> 16) >> 16) & 0xffffffffl;
91 	if (got != expect) {
92 		printf("failed %s(%08lx%08lx): got %d expect %d\n", which, high, low, got, expect);
93 		return 1;
94 	}
95 	return 0;
96 }
97 
98 int
main(void)99 main(void)
100 {
101 	size_t i;
102 	int ret = 0;
103 
104 	/* Test zero */
105 	ret += check(0, ffs(0), slow_ffs(0), "ffs");
106 	ret += check(0, ffsl(0), slow_ffsl(0), "ffsl");
107 	ret += check(0, ffsll(0), slow_ffsll(0), "ffsll");
108 
109 	/* Test every bit position in a long long */
110 	for (i = 0; i < sizeof(long long) * 8; i++) {
111 		long long int xll = 1LL << i;
112 		long xl = (long) xll;
113 		int x = (int) xll;
114 
115 		ret += check(x, ffs(x), slow_ffs(x), "ffs");
116 		ret += check(xl, ffsl(xl), slow_ffsl(xl), "ffsl");
117 		ret += check(xll, ffsll(xll), slow_ffsll(xll), "ffsll");
118 	}
119 
120 	/* Test another few random values */
121 #define N 100000
122 	for (i = 0; i < N; i++) {
123 		long long int xll = rand_long_long();
124 		long xl = (long) xll;
125 		int x = (int) xll;
126 
127 		ret += check(x, ffs(x), slow_ffs(x), "ffs");
128 		ret += check(xl, ffsl(xl), slow_ffsl(xl), "ffsl");
129 		ret += check(xll, ffsll(xll), slow_ffsll(xll), "ffsll");
130 	}
131 	return ret;
132 }
133