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 })