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; \
})
vpp之clib.h分析的更多相关文章
- ioctl.h 分析
ioctl.h 分析 我自己画了个解析图...不要嫌弃丑啊.. . 哈哈 type The magic number. Just choose one number (after consulting ...
- SGI STL源码stl_vector.h分析
前言 vector 是最常用的 C++ 容器,其动态扩容的特性是普通数组不具备的,这大大增加了编程的灵活性.虽然平时用 vector 很多,也能基本理解其原理,但无法从深层次理解.直到研读了 vect ...
- ios的xxxAppDelegate.h分析
#import "BIDAppDelegate.h" #import "BIDViewController.h" @implementation BIDAppD ...
- SGI STL源码stl_bvector.h分析
前言 上篇文章讲了 STL vector 泛化版本的实现,其采用普通指针作为迭代器,可以接受任何类型的元素.但如果用来存储 bool 类型的数据,可以实现功能,但每一个 bool 占一个字节(byte ...
- String源码分析
前言:String类在日常开发过程中使用频率非常高,平时大家可能看过String的源码,但是真的认真了解过它么,笔者在一次笔试过程中要求写出String的equals方法,瞬间有点懵逼,凭着大致的理解 ...
- hashCode()方法源码分析
执行代码 public class Demo06 { public static void main(String[] args) { String s="hello"; Syst ...
- Linux Linux程序练习十五(进程间的通信共享内存版)
/* * 题目: * 编写程序,要去实现如下功能: 父进程创建子进程1和子进程2.子进程1向子进程2发送可靠信号,并传送额外数据为子进程1的pid*2; 子进程2接受可靠信号的值,并发送给父进程,父进 ...
- C语言 百炼成钢3
//题目7:用*号输出空心菱形图案 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> # ...
- C语言 百炼成钢2
//题目4:输入某年某月某日,判断这一天是这一年的第几天? #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<st ...
随机推荐
- MFC vc++严重性 代码 说明 项目 文件 行 禁止显示状态 错误 C3646 “m_SockClient”: 未知重写说明符
严重性 代码 说明 项目 文件 行 禁止显示状态错误 C3646 “m_SockClient”: 未知重写说明符 MFC_TCP_CSocket_Client c:\users\tt2018\docu ...
- 什么了解suite集合实现
Testsuite继承BaseTestSuite其实内部的东西不是太多--生成suite集合的逻辑主要如下-我这里没有扒源码-因为他最终生成的TestsSuite关联的模块比较多--如果贴源码出来-- ...
- Python Selenium百度搜索翻页查找文字
#!/usr/bin/python # -*- coding: utf- -*- from selenium import webdriver import time # browser = webd ...
- AOF文件的写入与同步
在 Redis 中客户端向服务器发送相关写命令请求,这时服务器中有个用于处理这些命令的事件循环进程,对这些命令进行处理,并将相关信息处理的结果反馈给客户端,如:"OK",等.同时, ...
- Vue基础篇 (1) —— Vue-Router的使用
Vue-Cli中Vue-Router的使用 一.创建vue-cli的项目 npm create myproject vue create 为vue.js 3.0构建项目的命令,2.0版本可以通过vue ...
- HashMap的基本使用
常用方法 首先,我们应该知道HashMap类实现了Map接口,所以实现了Map常用的一些方法. (1) 插入键值对数据 public V put(K key, V value) (2)根据键值获取键值 ...
- python黑帽子之tcp客户端
在渗透测试过程中,我们经常会需要创建一个tcp客户端来连接服务,发送垃圾数据,进行模糊测试等任务,所以我们来用python创建一个简单的tcp客户端. import sockettarget_host ...
- nova api报错network问题
安装openstack Rocky版本的时候,在未安装网络服务前,创建虚拟机,报以下错误 [root@controller2 nova]# openstack server create --flav ...
- Python实用笔记 (10)高级特性——生成器
通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素 ...
- dart快速入门教程 (2)
2.变量和数据类型 2.1.变量和常量 变量通俗的说就是可以变化的量,作用就是用来存储数据,你可以把一个变量看作是一个水果篮,里面可以装苹果.梨.香蕉等,常量就是一个固定的值,和变量是相对的,变量可以 ...