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

刚好我在优化一个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. KMP超强模板贴一份

    )== ) {         );         next[]=; ;         ;i<=n;i++) {             ]!=str[i]) j=next[j];      ...

  2. hdu 2604 矩阵快速幂模板题

    /* 矩阵快速幂: 第n个人如果是m,有f(n-1)种合法结果 第n个人如果是f,对于第n-1和n-2个人有四种ff,fm,mf,mm其中合法的只有fm和mm 对于ffm第n-3个人只能是m那么有f( ...

  3. 1874 Bellman-ford算法 队列优化过的 用于稀疏图,有负权的图

    #include<stdio.h> #include<algorithm> #include<iostream> #include<queue> usi ...

  4. C++ - 一个构造函数调用构造函数的问题

          今天做C++的实验,题目是写一个二维点的类,然后让一个三维点的类继承它然后扩展.题目是一般学面向对象语言的常用例子.       然后遇到一个这样的问题:之前用Java的时候写构造方法的时 ...

  5. Ubuntu 16.04安装Synaptic Package Manager图形化APT管理工具

    安装: sudo apt-get install synaptic 启动:

  6. redis 主从备份自动切换+java代码实现类

    转载:http://blog.csdn.net/qq_23430789/article/details/52185706 目录(?)[-] redis-0sentinel实例之间的通讯端口 maste ...

  7. 移动匿名支付购物方案 A Lightweight Anonymous Mobile Shopping Scheme Based on DAA for Trusted Mobile Platform

  8. Live555研究之中的一个 源码编译

                                                Live555研究之中的一个 源代码编译 Live555 是一个为流媒体提供解决方式的跨平台的C++开源项目,它 ...

  9. AUTOTRACE

    .sqlplus 设置参数 set atuotrace on SET AUTOTRACE OFF --No AUTOTRACE report is generated. This is the def ...

  10. 如何用分布式缓存服务实现Redis内存优化

    Redis是一种支持Key-Value等多种数据结构的存储系统,其数据特性是“ALL IN MEMORY”,因此优化内存十分重要.在对Redis进行内存优化时,先要掌握Redis内存存储的特性比如字符 ...