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 ...
随机推荐
- elasticsearch unassigned shards 导致RED解决
先通过命令查看节点的shard分配整体情况 curl -X GET "ip:9200/_cat/allocation?v" 说明:有16个索引未分片 2.查看未分片的索引 curl ...
- 记录一次Flink作业异常的排查过程
最近2周开始接手apache flink全链路监控数据的作业,包括指标统计,业务规则匹配等逻辑,计算结果实时写入elasticsearch. 昨天遇到生产环境有作业无法正常重启的问题,我负责对这个问题 ...
- AWS 错误标记3
1. What is the average queue length recommended by AWS to achieve a lower latency for the 200 PIOPS ...
- JavaWeb网上图书商城完整项目--day02-7.提交注册表单功能之流程分析
1.点击注册之后将提交的信息传递到UserServlet的public String regist方法进行处理,然后将东西通过service进行处理 业务流程:
- 分词搜索 sphinx+php+mysql
sphinx3.1.1的安装与使用 下载sphinx3.1.1 wget http://sphinxsearch.com/files/sphinx-3.1.1-612d99f-linux-amd64. ...
- Spring IoC BeanDefinition 的加载和注册
前言 本系列全部基于 Spring 5.2.2.BUILD-SNAPSHOT 版本.因为 Spring 整个体系太过于庞大,所以只会进行关键部分的源码解析. 本篇文章主要介绍 Spring IoC 容 ...
- 使用迭代器模式批量获得数据(C#实现)
先说一下项目的背景,以前曾经做过一个项目,根据Excel中的数据批量的到网页上抓取数据,将抓取到的数据批量的回填到Excel中.这个Excel中有很多行的记录(多的时候会有好几千行),每一行数据存储能 ...
- 多图解释Redis的整数集合intset升级过程
redis源码分析系列文章 [Redis源码系列]在Liunx安装和常见API 为什么要从Redis源码分析 String底层实现——动态字符串SDS 双向链表都不懂,还说懂Redis? 面试官:说说 ...
- 如何将Oracle中同一列的多行记录拼接成一个字符串
需要用wm_concat函数来实现. 如目前在emp表中查询数据如下: 要按照deptno相同的将ename以字符串形式合并,可用如下语句: 1 select deptno,wm_concat(ena ...
- 拿2k的前端开发都会做些什么?
坐标珠海,前端程序媛一枚 实习时候做的是测试,2.5k+600餐补: 后来觉得对前端更有兴趣所以重新找工作,但是苦于没有经验,毕业第一年在一个传统行业的公司找到了一个前端岗位,薪酬4k,公司主要是接政 ...