vpp代码中有一个clib.h,其中封装了很一些很经典的位运算:
1 //计算以2为底的对数,log2(x)
2 //也就是计算2的N次方为x。x为uint32类型
3 #if defined (count_leading_zeros)
4 always_inline uword
5 min_log2 (uword x)
6 {
7 uword n;
8 n = count_leading_zeros (x);
9 return BITS (uword) - n - 1;
10 }
11 #else
12 always_inline uword
13 min_log2 (uword x)
14 {
15 uword a = x, b = BITS (uword) / 2, c = 0, r = 0;
16
17 /* Reduce x to 4 bit result. */
18 #define _ \
19 { \
20 c = a >> b; \
21 if (c) a = c; \
22 if (c) r += b; \
23 b /= 2; \
24 }
25
26 if (BITS (uword) > 32)
27 _;
28 _;
29 _;
30 _;
31 #undef _
32
33 /* Do table lookup on 4 bit partial. */
34 if (BITS (uword) > 32)
35 {
36 const u64 table = 0x3333333322221104LL;
37 uword t = (table >> (4 * a)) & 0xf;
38 r = t < 4 ? r + t : ~0;
39 }
40 else
41 {
42 const u32 table = 0x22221104;
43 uword t = (a & 8) ? 3 : ((table >> (4 * a)) & 0xf);
44 r = t < 4 ? r + t : ~0;
45 }
46
47 return r;
48 }
49 #endif
50
51 //计算以2为底的对数(有余数的话+1),log2(x)
52 //也就是计算2的N次方为x。2的N次方大于x
53 always_inline uword
54 max_log2 (uword x)
55 {
56 uword l = min_log2 (x);
57 if (x > ((uword) 1 << l))
58 l++;
59 return l;
60 }
61
62 //计算以2为底的对数,log2(x)
63 //也就是计算2的N次方为x。x为u64类型
64 always_inline u64
65 min_log2_u64 (u64 x)
66 {
67 if (BITS (uword) == 64)
68 return min_log2 (x);
69 else
70 {
71 uword l, y;
72 y = x;
73 l = 0;
74 if (y == 0)
75 {
76 l += 32;
77 x >>= 32;
78 }
79 l += min_log2 (x);
80 return l;
81 }
82 }
83
84 //计算基数2的x次幂的值对应的掩码
85 //比如2的4次幂为16,对应的掩码为15
86 always_inline uword
87 pow2_mask (uword x)
88 {
89 return ((uword) 1 << x) - (uword) 1;
90 }
91
92 //计算数字x对应的,以基数2的n次幂的值。x小于等于n
93 //比如x=15,则得出的数字为16.2的3次幂小于x,2的4次幂大于x。
94 always_inline uword
95 max_pow2 (uword x)
96 {
97 word y = (word) 1 << min_log2 (x);
98 if (x > y)
99 y *= 2;
100 return y;
101 }
102
103 //计算x是否可等于基数2的n次幂
104 //比如x=16,返回1.x=15,返回0
105 always_inline uword
106 is_pow2 (uword x)
107 {
108 return 0 == (x & (x - 1));
109 }
110
111 //计算x以pow2对齐的长度。pow2应该为2的n次方。
112 //如x=15,pow2=4,则返回16。
113 always_inline uword
114 round_pow2 (uword x, uword pow2)
115 {
116 return (x + pow2 - 1) & ~(pow2 - 1);
117 }
118
119 //计算x以pow2对齐的长度。pow2应该为2的n次方。
120 //如x=15,pow2=4,则返回16。
121 always_inline u64
122 round_pow2_u64 (u64 x, u64 pow2)
123 {
124 return (x + pow2 - 1) & ~(pow2 - 1);
125 }
126
127 //保留二进制下最后出现的1的位置,其余位置置0(即一个数中最大的2的n次幂的因数
128 //当一个偶数与它的负值向与时,结果是能被这个偶数整除的最大的2的n次幂
129 //当一个奇数与它的负值向与时结果一定是1
130 always_inline uword
131 first_set (uword x)
132 {
133 return x & -x;
134 }
135
136 //先将x用first_set计算结果,
137 //然后以2为底做对数运算
138 always_inline uword
139 log2_first_set (uword x)
140 {
141 uword result;
142 #ifdef count_trailing_zeros
143 result = count_trailing_zeros (x);
144 #else
145 result = min_log2 (first_set (x));
146 #endif
147 return result;
148 }
149
150 //将浮点数强转为整型(小数部分舍去)
151 always_inline f64
152 flt_round_down (f64 x)
153 {
154 return (int) x;
155 }
156
157 //将浮点数强转为整型(小数部分四舍五入)
158 always_inline word
159 flt_round_nearest (f64 x)
160 {
161 return (word) (x + .5);
162 }
163
164 //若x大于f的一半,则返回f,否则返回0
165 always_inline f64
166 flt_round_to_multiple (f64 x, f64 f)
167 {
168 return f * flt_round_nearest (x / f);
169 }
170
171 //计算x右移start位后,再截取count位有效数字是多少
172 always_inline uword
173 extract_bits (uword x, int start, int count)
174 {
175 #ifdef __BMI__
176 return _bextr_u64 (x, start, count);
177 #endif
178 return (x >> start) & pow2_mask (count);
179 }
180
181 //取x和y两个数中大的数
182 #define clib_max(x,y) \
183 ({ \
184 __typeof__ (x) _x = (x); \
185 __typeof__ (y) _y = (y); \
186 _x > _y ? _x : _y; \
187 })
188
189 //取x和y两个数中较小的数
190 #define clib_min(x,y) \
191 ({ \
192 __typeof__ (x) _x = (x); \
193 __typeof__ (y) _y = (y); \
194 _x < _y ? _x : _y; \
195 })
196
197 //取x和y两个数中较大的数
198 #define clib_max(x,y) \
199 ({ \
200 __typeof__ (x) _x = (x); \
201 __typeof__ (y) _y = (y); \
202 _x > _y ? _x : _y; \
203 })
204
205
206 //取x的绝对值
207 //定义类型与x相同的临时变量_x,并将x的值赋予_x
208 //取绝对值
209 #define clib_abs(x) \
210 ({ \
211 __typeof__ (x) _x = (x); \
212 _x < 0 ? -_x : _x; \
213 })