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

刚好我在优化一个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. [luoguP1922] 女仆咖啡厅桌游吧(奇奇怪怪的树形DP)

    传送门 什么鬼的题? 代码 #include <cstdio> #include <cstring> #include <iostream> #define N 1 ...

  2. 免XML的SpringMVC配置

    Servlet 3.0以后,新增了一些注解,使得web.xml可以省略掉.这样配合Spring的JavaConfig就可以实现免xml的项目配置,这里简单搭建一个免XML的SpringMVC.Spri ...

  3. HDU1914(稳定婚姻)

    http://acm.hdu.edu.cn/showproblem.php?pid=1914 思路:Gale-Shapley算法.算法过程是男士不停地求婚,女士不停地拒绝.在每一轮中,每个尚未订婚的男 ...

  4. 夜话JAVA设计模式之策略模式

    策略模式     定义了算法簇,分别封装起来,让他们之间可以互相替换,让算法簇的变化独立于使用算法的客户.设计原则1     找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混在 ...

  5. Android GIS开发系列-- 入门季(3) GraphicsLayer添加点、线、面

    GraphicsLayer是图形图层,可以自定义图形添加到地图上.调用GraphicsLayer的addGraphic方法就能添加图形,此方法要一个Graphic对象,此对象的构造方法是Graphic ...

  6. Redis: Useful commands

    SELECT X - Select database (the X must be int) CONFIG GET databases - Get databases number INFO keys ...

  7. [Algorithm] Determine if two strings are an anagram

    The anagram test is commonly used to demonstrate how an naive implementation can perform significant ...

  8. Linux下Shell编程

    Linux的shell编程 1.什么是shell? 当一个用户登录Linux系统之后,系统初始化程序init就为每个用户执行一个称为shell(外壳)的程序. shell就是一个命令行解释器,它为用户 ...

  9. Python3基础(九) 错误和异常

    本文主要介绍Python中的错误和异常,涉及到简单的异常处理.抛出异常以及清理动作.至于自定义异常类,将在介绍类与继承的时候讲到. 一.定义 常见的两种错误:语法错误 和 异常. 1.语法错误(Syn ...

  10. tomcat连接mysql的3个问题解决

    转载请标明出处: 本文出自:[ouyida3的博客] 1.BasicDataSourceFactory Caused by: java.lang.ClassNotFoundException: org ...