1. 程式人生 > 實用技巧 >vpp之clib.h分析

vpp之clib.h分析

vpp程式碼中有一個clib.h,其中封裝了很一些很經典的位運算:

 //計算以2為底的對數,log2(x)
//也就是計算2的N次方為x。x為uint32型別
#if defined (count_leading_zeros)
always_inline uword
min_log2 (uword x)
{
uword n;
n = count_leading_zeros (x);
return BITS (uword) - n - ;
}
#else
always_inline uword
min_log2 (uword x)
{
uword a = x, b = BITS (uword) / , c = , r = ; /* Reduce x to 4 bit result. */
#define _ \
{ \
c = a >> b; \
if (c) a = c; \
if (c) r += b; \
b /= ; \
} if (BITS (uword) > )
_;
_;
_;
_;
#undef _ /* Do table lookup on 4 bit partial. */
if (BITS (uword) > )
{
const u64 table = 0x3333333322221104LL;
uword t = (table >> ( * a)) & 0xf;
r = t < ? r + t : ~;
}
else
{
const u32 table = 0x22221104;
uword t = (a & ) ? : ((table >> ( * a)) & 0xf);
r = t < ? r + t : ~;
} return r;
}
#endif //計算以2為底的對數(有餘數的話+1),log2(x)
//也就是計算2的N次方為x。2的N次方大於x
always_inline uword
max_log2 (uword x)
{
uword l = min_log2 (x);
if (x > ((uword) << l))
l++;
return l;
} //計算以2為底的對數,log2(x)
//也就是計算2的N次方為x。x為u64型別
always_inline u64
min_log2_u64 (u64 x)
{
if (BITS (uword) == )
return min_log2 (x);
else
{
uword l, y;
y = x;
l = ;
if (y == )
{
l += ;
x >>= ;
}
l += min_log2 (x);
return l;
}
} //計算基數2的x次冪的值對應的掩碼
//比如2的4次冪為16,對應的掩碼為15
always_inline uword
pow2_mask (uword x)
{
return ((uword) << x) - (uword) ;
} //計算數字x對應的,以基數2的n次冪的值。x小於等於n
//比如x=15,則得出的數字為16.2的3次冪小於x,2的4次冪大於x。
always_inline uword
max_pow2 (uword x)
{
word y = (word) << min_log2 (x);
if (x > y)
y *= ;
return y;
} //計算x是否可等於基數2的n次冪
//比如x=16,返回1.x=15,返回0
always_inline uword
is_pow2 (uword x)
{
return == (x & (x - ));
} //計算x以pow2對齊的長度。pow2應該為2的n次方。
//如x=15,pow2=4,則返回16。
always_inline uword
round_pow2 (uword x, uword pow2)
{
return (x + pow2 - ) & ~(pow2 - );
} //計算x以pow2對齊的長度。pow2應該為2的n次方。
//如x=15,pow2=4,則返回16。
always_inline u64
round_pow2_u64 (u64 x, u64 pow2)
{
return (x + pow2 - ) & ~(pow2 - );
} //保留二進位制下最後出現的1的位置,其餘位置置0(即一個數中最大的2的n次冪的因數
//當一個偶數與它的負值向與時,結果是能被這個偶數整除的最大的2的n次冪
//當一個奇數與它的負值向與時結果一定是1
always_inline uword
first_set (uword x)
{
return x & -x;
} //先將x用first_set計算結果,
//然後以2為底做對數運算
always_inline uword
log2_first_set (uword x)
{
uword result;
#ifdef count_trailing_zeros
result = count_trailing_zeros (x);
#else
result = min_log2 (first_set (x));
#endif
return result;
} //將浮點數強轉為整型(小數部分捨去)
always_inline f64
flt_round_down (f64 x)
{
return (int) x;
} //將浮點數強轉為整型(小數部分四捨五入)
always_inline word
flt_round_nearest (f64 x)
{
return (word) (x + .);
} //若x大於f的一半,則返回f,否則返回0
always_inline f64
flt_round_to_multiple (f64 x, f64 f)
{
return f * flt_round_nearest (x / f);
} //計算x右移start位後,再擷取count位有效數字是多少
always_inline uword
extract_bits (uword x, int start, int count)
{
#ifdef __BMI__
return _bextr_u64 (x, start, count);
#endif
return (x >> start) & pow2_mask (count);
} //取x和y兩個數中大的數
#define clib_max(x,y) \
({ \
__typeof__ (x) _x = (x); \
__typeof__ (y) _y = (y); \
_x > _y ? _x : _y; \
}) //取x和y兩個數中較小的數
#define clib_min(x,y) \
({ \
__typeof__ (x) _x = (x); \
__typeof__ (y) _y = (y); \
_x < _y ? _x : _y; \
}) //取x和y兩個數中較大的數
#define clib_max(x,y) \
({ \
__typeof__ (x) _x = (x); \
__typeof__ (y) _y = (y); \
_x > _y ? _x : _y; \
}) //取x的絕對值
//定義型別與x相同的臨時變數_x,並將x的值賦予_x
//取絕對值
#define clib_abs(x) \
({ \
__typeof__ (x) _x = (x); \
_x < ? -_x : _x; \
})