我在网上看到了一点神奇的代码,用来计算一个数字末尾连续零的个数。

刚好我在优化一个I2C读写函数(只写入I2C特定bit),觉得这个很有用。经过尝试,确实没问题。

下面我隆重介绍一下:

Count the consecutive zero bits (trailing) on the right with multiply and lookup

unsigned int v;  // find the number of trailing zeros in 32-bit v
int r; // result goes here
static const int MultiplyDeBruijnBitPosition[32] =
{
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};
r = MultiplyDeBruijnBitPosition[((uint32_t)((v & -v) * 0x077CB531U)) >> 27];

Converting bit vectors to indices of set bits is an example use for this. It requires one more operation than the earlier one involving modulus division, but the multiply may be faster. The expression (v & -v) extracts the least significant 1 bit from v. The constant 0x077CB531UL is a de Bruijn sequence, which produces a unique pattern of bits into the high 5 bits for each possible bit position that it is multiplied against. When there are no bits set, it returns 0. More information can be found by reading the paper Using de Bruijn Sequences to Index 1 in a Computer Word by Charles E. Leiserson, Harald Prokof, and Keith H. Randall.

On October 8, 2005 Andrew Shapira suggested I add this. Dustin Spicuzza asked me on April 14, 2009 to cast the result of the multiply to a 32-bit type so it would work when compiled with 64-bit ints.

以上内容转自http://graphics.stanford.edu/~seander/bithacks.html

++++++++++++++++++++++++++++++++我是分割线++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

然后根据此方案,我们来做一个8bit的末尾连续0的计算。

主要用途是I2C读写时,mask 的计算。如果要读写某Byte的某几个bit,可以只传入寄存器地址和Mask位就可以了。

创建文件test.c

 #include <stdio.h>
#include <stdlib.h> void main(int argc, **argv)
{
int r;
unsigned char v;
static const unsigned char MultiplyDeBruijnBitPosition[] = {, , , , , , , }; v = (unsigned char)stroul(argv[],NULL, );
r = MultiplyDeBruijnBitPosition[((unsigned char)((v & -v) * 0x1DU)) >> ]; printf("The calculated = %d\n", r);
}

在Linux下调试验证:

gcc -o test test.c

./test xxx

应用实例:

mask的计算方法

 #define BIT(nr) (1<<(nr))
#define _PM_MASK(BITS, POS) \
((unsigned char)((( << (BITS)) - ) << (POS)))
#define PM_MASK(LEFT, RIGHT) \
_PM_MASK((LEFT) - (RIGHT) + , RIGHT)

下面是带mask的I2C写操作。

static status_t i2c_write_mask(uint8_t reg, uint8_t mask, uint8_t data)
{
status_t status;
uint8_t shift = ;
uint8_t tmp; status = i2c_read_byte(reg, &tmp);
if (status != kStatus_Success) {
PRINTF("Failed: status=%ld, reg=%d\n", status, reg);
goto out;
} tmp &= ~mask;
/* 0x1D is calculated from the de Bruun sequence */
shift = MultiplyDeBruijnBitPosition[((uint8_t)((mask & -mask) * 0x1DU)) >> ];
data <<= shift;
tmp |= data & mask; status = i2c_write_byte(reg, tmp);
if (status != kStatus_Success) {
PRINTF("Failed: reg=%02X, status=%ld\n", reg, status);
} out:
return status;
}

至于像 0x1DU 及类似的代码中的 0x077CB531,0x5F3759DF和数组

{
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
}; {0, 1, 6, 2, 7, 5, 4, 3};

的由来问题,就参考:http://www.cnblogs.com/shangdawei/p/3967505.html 好了,非常感谢此作者的工作,让我很快明白了De Bruijin序列的计算方法。

Count the consecutive zero bits (trailing) on the right with multiply and lookup的更多相关文章

  1. BitHacks

    备份文件时看到的.我以前居然下过这东西. 2016-12-4 12:05:52更新 纯文本格式真棒.假如使用word写的我能拷过来格式还不乱?? Markdown真好. Bit Hacks By Se ...

  2. Bit Twiddling Hacks

    http://graphics.stanford.edu/~seander/bithacks.html Bit Twiddling Hacks By Sean Eron Andersonseander ...

  3. upc组队赛17 Bits Reverse【暴力枚举】

    Bits Reverse 题目链接 题目描述 Now given two integers x and y, you can reverse every consecutive three bits ...

  4. CCPC2018 桂林 D "Bits Reverse"

    传送门 题目描述 Now given two integers x and y, you can reverse every consecutive three bits ,,) means chan ...

  5. RFID 基础/分类/编码/调制/传输

    不同频段的RFID产品会有不同的特性,本文详细介绍了无源的感应器在不同工作频率产品的特性以及主要的应用. 目前定义RFID产品的工作频率有低频.高频和甚高频的频率范围内的符合不同标准的不同的产品,而且 ...

  6. 二维码详解(QR Code)

    作者:王子旭链接:https://zhuanlan.zhihu.com/p/21463650来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 2016.7.5 更新:长文 ...

  7. LUXURY15

    A - Guess Your Way Out! Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & ...

  8. RFID Exploration and Spoofer a bipolar transistor, a pair of FETs, and a rectifying full-bridge followed by a loading FET

    RFID Exploration Louis Yi, Mary Ruthven, Kevin O'Toole, & Jay Patterson What did you do? We made ...

  9. 算术编码JM实现

    h.264标准中,CABAC的算术编码部分(9.3.4)只是一个参考,实际编码器中并不一定会按照它来实现,像JM中就有自己的算术编码实现方案. 在上篇文章CABAC中有详细的算术编码描述,在了解算术编 ...

随机推荐

  1. mongodb local数据库的空间初始化好大啊!

    新建立了一个replicat set,登录到primary里,show dbs一看吓一跳 local数据库竟然占用了80多G的空间 [root@wxlab31 bin]# ./mongo --host ...

  2. [codeVS1404] 字符串匹配

    时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master         题目描述 Description 给你两个串A,B,可以得到从A的任意位开始的子串和B匹配的长度. ...

  3. 一份关于jvm内存调优及原理的学习笔记(转)

    JVM 一.虚拟机的基本结构 1.jvm整体架构 类加载子系统:负责从文件系统或者网络中加载class信息,存入方法区中. 方法区(Perm):存放加载后的class信息,包括静态方法,jdk1.6以 ...

  4. 3.3-ISDN

    3.3-ISDN     综合业务数字网ISDN(Integrated Services Digital Network):     ISDN主要有两种接口类型:分为BRI(2B+D=2×64+16K ...

  5. POJ 1861 Network (Kruskal求MST模板题)

    Network Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 14103   Accepted: 5528   Specia ...

  6. 还在自建Redis缓存?那你就out了

    Redis 是什么?简单来说,Redis是一个开源的内存数据库,支持Key-Value等多种数据结构,可用于缓存.事件发布或订阅.高速队列等场景.Redis使用ANSIC语言编写,支持网络,提供字符串 ...

  7. 【网易云音乐 for linux】 踩过的坑

    1.从官网下载的包,却怎么也安装不上. 提示依赖,网上全是什么 sudo apt-get -f install ,结果提示有没有完成安装的包,让我卸载. 于是按下Y卸载了网易云. 尝试一个个修复以来, ...

  8. vs2010 下使用C#开发activeX控件

    1.创建一个类库 2.项目属性-应用程序-程序集信息-"使程序集COM可见"勾上; 3.项目属性-生成-"为COM互操作注册"勾上.(这个折腾一天,否则注册事件 ...

  9. json Date对象在js中的处理办法

    我们在程序用往往通过ajax方式返回json数据,json中包含Date对象时,在js中是Object对象.可以方式获取: 1.new Date(yourJsonDate.time); //你用你的返 ...

  10. java—容器学习笔记

    一:迭代器 刚开始学容器,做了个简单的练习题.. import java.util.ArrayList; import java.util.Collection; import java.util.I ...