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 <stdint.h>
40 #include <stdlib.h>
41 #include <stdio.h>
42
43 long long int
rand_long_long(void)44 rand_long_long(void)
45 {
46 unsigned long long int r = 0;
47 size_t x;
48
49 for (x = 0; x < sizeof(r) / 4; x++)
50 r = (r << 32) | (lrand48() & 0xffffffffL);
51 return r;
52 }
53
54 int
slow_ffs(int i)55 slow_ffs(int i)
56 {
57 int p;
58 if (!i)
59 return 0;
60 for (p = 1; (i & (1 << (p - 1))) == 0; p++)
61 ;
62 return p;
63 }
64
65 int
slow_ffsl(long int i)66 slow_ffsl(long int i)
67 {
68 int p;
69 if (!i)
70 return 0;
71 for (p = 1; (i & (1L << (p - 1))) == 0; p++)
72 ;
73 return p;
74 }
75
76 int
slow_ffsll(long long int i)77 slow_ffsll(long long int i)
78 {
79 int p;
80 if (!i)
81 return 0;
82 for (p = 1; (i & (1LL << (p - 1))) == 0; p++)
83 ;
84 return p;
85 }
86
87 static int
check(long long int x,int got,int expect,char * which)88 check(long long int x, int got, int expect, char *which)
89 {
90 long int low = x & 0xffffffffl;
91 long int high = ((x >> 16) >> 16) & 0xffffffffl;
92 if (got != expect) {
93 printf("failed %s(%08lx%08lx): got %d expect %d\n", which, high, low, got, expect);
94 return 1;
95 }
96 return 0;
97 }
98
99 int
main(void)100 main(void)
101 {
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 (size_t 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 (int32_t 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