经典位操作
2015-06-18 09:45
295 查看
最近看了一篇文章<<Bit Twiddling Hacks>>感觉不错,适当的做一下笔记。
原文地址:http://graphics.stanford.edu/~seander/bithacks.html#OperationCounting
1、Compute the sign of an integer
2、Detect if two integers have opposite signs
3、Compute the integer absolute value (abs) without branching
4、Compute the minimum (min) or maximum(max) of two integers without branching
5、Determining if an integer is a power of 2
6、Sign entending from a constant bit-width
In C, sign extension from a constant bit-width is trival, since bit fields may be specified in structs or unions. For example, to convert from 5 bits to an full integer.
7、 Counting bits set
8、Counting bits set, Brian Kernighan's way
Counting bits set in 14, 24, or 32-bit words using 64-bit instructions
Counting bits set, in parallel
Count bits set (rank) from the most-significant bit upto a given position
Select the bit position(from the most-significant bit) with the given count(rank)
上面这些看上去很复杂的样子,头大了,先跳过吧。
9、 Computing parity the naive way
10、 Compute parity by lookup table
11、Compute parity of a byte using 64-bit multiply and modulus division
12、Compute parity of word with a multiply
The following method computers the parity of the 32-bit value in only 8 operations using a multiply.
Also for 64-bits, 8 operators are still enough.
13、 Compute parity in parallel
14、 Swapping values with subtraction and addition
15、Swapping values with XOR
16、 Swapping individual bits with XOR
(expressed in binary) and we want to swap the n = 3 consecutive bits starting at i = 1 (the second bit from the right) with the 3 consecutive bits starting at j = 5; the result would be r = 11100011
(binary).
This method of swapping is similar to the general purpose XOR swap trick, but intended for operating on individual bits. The variable x stores the result of XORing the pairs of bit values we want to
swap, and then the bits are set to the result of themselves XORed with x.
Of course, the result is undefined if the sequences overlap.
17、Reverse bits the obvious way
18、 Reverse bits in word by lookup table
直接贴作者的代码了...
19、Compute modulus division by 1 << s without a division operator
20、 Compute modulus division by (1 << s) - 1 without a division operator
21、Find the log base 2 of an integer with the MSB N set in O(N) operations (the obvious way)
22、 Count the consecutive zero bits (trailing) on the right linearly
23、 Count the consecutive zero bits (trailing) on the right by binary search
24、 Interleave bits the obvious way
that a number is usually close to another if their x and y values are close.
25、 Compute the lexicographically next bit permutation
Suppose we have a pattern of N bits set to 1 in an integer and we want the next permutation of N 1 bits in a lexicographical sense. For example, if N is 3 and the bit pattern is 00010011, the
next patterns would be 00010101, 00010110, 00011001,00011010, 00011100, 00100011, and so forth. The following is a fast way to compute the next permutation.
returns the number of trailing zeros. If you are using Microsoft compilers for x86, the intrinsic is _BitScanForward. These both emit a bsf instruction, but equivalents may be available for other architectures. If not, then
consider using one of the methods for counting the consecutive zero bits mentioned earlier.
更多内容参照原文,我只是把我能理解的代码摘了下来,更多神奇的代码请看原文。
原文地址:http://graphics.stanford.edu/~seander/bithacks.html#OperationCounting
1、Compute the sign of an integer
// we want to find the sign of v int v; // the result goes here int sign; // CHAR_BIT is the number of bits per byte (normally 8). // if v < 0 then -1, else 0. sign = -(v < 0); // or, to avoid branching on CPUs with flag registers (IA32): sign = -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1)); // or, for one less instruction (but not portable): sign = v >> (sizeof(int) * CHAR_BIT - 1); // if v < 0 then -1, else +1 sign = +1 | (v >> (sizeof(int) * CHAR_BIT - 1)); // if v < 0 then -1, else if v > 0 then 1, else 0 sign = (v != 0) | -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1)); // Or, for more speed but less portability: sign = (v != 0) | (v >> (sizeof(int) * CHAR_BIT - 1)); // Or, for portability, brevity, and (perhaps) speed: sign = (v > 0) - (v < 0); // if v >= 0 then 1, else 0 sign = 1 ^ ((unsigned int)v >> (sizeof(int) * CHAR_BIT - 1));
2、Detect if two integers have opposite signs
// input values to compare signs int x, y; // true if x and y have opposite signs bool f = ((x ^ y) < 0);
3、Compute the integer absolute value (abs) without branching
// we want to find the absolute value of v int v; // the result goes here unsigned int r; // if v >= 0 then 0, else -1 const int mask = v >> (sizeof(int) * CHAR_BIT - 1); // general method r = (v < 0) ? -(unsigned int)v : v; // if v >= 0 then r = (v + 0) ^ 0 // if v < 0 then r = (v + (-1)) ^ (-1) r = (v + mask) ^ mask; // patented variation // if v < 0 then r = (v ^ (-1)) + 1 r = (v ^ mask) - mask;
4、Compute the minimum (min) or maximum(max) of two integers without branching
// we want to find the minimum of x and y int x; int y; // the result goes here int r; // min(x, y) r = y ^ ((x ^ y) & -(x < y)); // max(x, y) r = x ^ ((x ^ y) & -(x < y)); // quick and dirty versions // if INT_MIN <= x - y <= INT_MAX // min(x, y) r = y + ((x - y) & ((x - y) >> (sizeof(int) * CHAR_BIT - 1))); // max(x, y) r = x - ((x - y) & ((x - y) >> (sizeof(int) * CHAR_BIT - 1)));
5、Determining if an integer is a power of 2
// we want to see if v is a power of 2 unsigned int v ; // the result goes here bool f; // include 0, but 0 is incorrect f = (v & (v - 1)) == 0; // not include 0 f = v && !(v & (v - 1));
6、Sign entending from a constant bit-width
In C, sign extension from a constant bit-width is trival, since bit fields may be specified in structs or unions. For example, to convert from 5 bits to an full integer.
int x; int r; struct { signed int x:5; } s; r = s.x = x;
template<typename T, unsigned B> inline T signextend(const T x) { struct { signed int x:B; } s; return s.x = x; } int r = signextend<signed int, 5>(x);
7、 Counting bits set
unsigned int v; // count the number of bits set in v unsigned int c; // c accumulates the total bits set in v for (c = 0; v; v >>= 1) { c += v & 1; }
8、Counting bits set, Brian Kernighan's way
unsigned int v; // count the number of bits set in v unsigned int c; // c accumulates the total bits set in v for (c = 0; v; c++) { v &= v - 1; // clear the least significant bit set }
Counting bits set in 14, 24, or 32-bit words using 64-bit instructions
Counting bits set, in parallel
Count bits set (rank) from the most-significant bit upto a given position
Select the bit position(from the most-significant bit) with the given count(rank)
上面这些看上去很复杂的样子,头大了,先跳过吧。
9、 Computing parity the naive way
unsigned int v; // word value to compute the parity of bool parity = false; // parity will be the parity of v while (v) { parity = !parity; v = v & (v - 1); }
10、 Compute parity by lookup table
static const bool ParityTable256[256] = { # define P2(n) n, n^1, n^1, n # define P4(n) P2(n), P2(n^1), P2(n^1), P2(n) # define P6(n) P4(n), P4(n^1), P4(n^1), P4(n) P6(0), P6(1), P6(1), P6(0) }; unsigned char b; // byte value to compute the parity of bool parity = ParityTable256[b]; // OR, for 32-bit words: unsigned int v; v ^= v >> 16; v ^= v >> 8; bool parity = ParityTable256[v & 0xff]; // Variation: unsigned char * p = (unsigned char *) &v; parity = ParityTable256[p[0] ^ p[1] ^ p[2] ^ p[3]];
11、Compute parity of a byte using 64-bit multiply and modulus division
unsigned char b; // byte value to compute the parity of bool parity = (((b * 0x0101010101010101ULL) & 0x8040201008040201ULL) % 0x1FF) & 1;
12、Compute parity of word with a multiply
The following method computers the parity of the 32-bit value in only 8 operations using a multiply.
unsigned int v; // 32-bit word v ^= v >> 1; v ^= v >> 2; v = (v & 0x11111111U) * 0x11111111U; return (v >> 28) & 1;
Also for 64-bits, 8 operators are still enough.
unsigned long long v; // 64-bit word v ^= v >> 1; v ^= v >> 2; v = (v & 0x1111111111111111UL) * 0x1111111111111111UL; return (v >> 60) & 1;
13、 Compute parity in parallel
unsigned int v; // word value to compute the parity of v ^= v >> 16; v ^= v >> 8; v ^= v >> 4; v &= 0xf; return (0x6996 >> v) & 1;
14、 Swapping values with subtraction and addition
#define SWAP(a, b) ((&(a) == &(b)) || \ (((a) -= (b)), ((b) += (a)), ((a) = (b) - (a))))
15、Swapping values with XOR
#define SWAP(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b)))
16、 Swapping individual bits with XOR
// positions of bit sequences to swap unsigned int i, j; // number of consecutive bits in each sequence unsigned int n; // bits to swap reside in b unsigned int b; // bit-swapped result goes here unsigned int r; // XOR temporary unsigned int x = ((b >> i) ^ (b >> j)) & ((1U << n) - 1); r = b ^ ((x << i) | (x << j));As an example of swapping ranges of bits suppose we have have b = 00101111
(expressed in binary) and we want to swap the n = 3 consecutive bits starting at i = 1 (the second bit from the right) with the 3 consecutive bits starting at j = 5; the result would be r = 11100011
(binary).
This method of swapping is similar to the general purpose XOR swap trick, but intended for operating on individual bits. The variable x stores the result of XORing the pairs of bit values we want to
swap, and then the bits are set to the result of themselves XORed with x.
Of course, the result is undefined if the sequences overlap.
17、Reverse bits the obvious way
unsigned int v; // get the last bit of v unsigned int r = v; int s = sizeof(v) * CHAR_BIT - 1; for(v >>= 1; v; v >>= 1) { r <<= 1; r |= (v&1); s--; } // the lead zero r <<= s;
unsigned int v; // the inital val of f is 0 unsigned int r = 0; // the total bits of v int s = sizeof(v) * CHAR_BIT; for( ; v; v >>= 1) { r <<= 1; r |= (v & 1); s--; } // the lead zero r <<= s;
18、 Reverse bits in word by lookup table
直接贴作者的代码了...
static const unsigned char BitReverseTable256[256] = { # define R2(n) n, n + 2*64, n + 1*64, n + 3*64 # define R4(n) R2(n), R2(n + 2*16), R2(n + 1*16), R2(n + 3*16) # define R6(n) R4(n), R4(n + 2*4 ), R4(n + 1*4 ), R4(n + 3*4 ) R6(0), R6(2), R6(1), R6(3) }; unsigned int v; // reverse 32-bit value, 8 bits at time unsigned int c; // c will get v reversed // Option 1: c = (BitReverseTable256[v & 0xff] << 24) | (BitReverseTable256[(v >> 8) & 0xff] << 16) | (BitReverseTable256[(v >> 16) & 0xff] << 8) | (BitReverseTable256[(v >> 24) & 0xff]); // Option 2: unsigned char * p = (unsigned char *) &v; unsigned char * q = (unsigned char *) &c; q[3] = BitReverseTable256[p[0]]; q[2] = BitReverseTable256[p[1]]; q[1] = BitReverseTable256[p[2]]; q[0] = BitReverseTable256[p[3]];
19、Compute modulus division by 1 << s without a division operator
const unsigned int n; // numerator const unsigned int s; const unsigned int d = 1U << s; // So d will be one of: 1, 2, 4, 8, 16, 32, ... unsigned int m; // m will be n % d m = n & (d - 1);
20、 Compute modulus division by (1 << s) - 1 without a division operator
unsigned int n; // numerator const unsigned int s; // s > 0 const unsigned int d = (1 << s) - 1;// so d is either 1, 3, 7, 15, 31, .... unsigned int m; // n % d goes here for(m = n; n > d; n = m) { for(m = 0; n; n >>= s) { m += n & d; } } // Now m is a value from 0 to d, but since with modulus division // we want m to be 0 when it is d m = m == d ? 0 : m;
21、Find the log base 2 of an integer with the MSB N set in O(N) operations (the obvious way)
// 32-bit word to find the log base 2 of unsigned int v; // r will be lg(v) unsigned int r = 0; while(v >>= 1) { ++r; }
22、 Count the consecutive zero bits (trailing) on the right linearly
// input to count trailing zero bits unsigned int v; // output: c will count v's trailing zero bits // so if v is 1101000(base 2), then c will be 3 int c; if(v) { v = (v ^ (v - 1)) >> 1; for(c = 0; v; v >>= 1, ++c); /* for(c = 0; v; ++c) { v >>= 1; } */ } else { c = sizeof(v) * CHAR_BIT; }
23、 Count the consecutive zero bits (trailing) on the right by binary search
// 32-bit word input to count zero bits on right unsigned int v; // c will be the number of zero bits on the right // so if v is 1101000(base 2), then c will be 3 unsigned int c; // NOTE : if 0 == v, then c = 31 if(v & 0x1) { // special case for odd v (assumed to happen half of the time) c = 0; } else { c = 1; if((v & 0xffff) == 0) { v >>= 16; c += 16; } if((v & 0xff) == 0) { v >>= 8; c += 8; } if((v & 0xf) == 0) { v >>= 4; c += 4; } if((v & 0x3) == 0) { v >>= 2; c += 2; } c -= v & 0x1; }
24、 Interleave bits the obvious way
unsigned short x; // Interleave bits of x and y, so that all of the unsigned short y; // bits of x are in the even positions and y in the odd; unsigned int z = 0; // z gets the resulting Morton Number. for (int i = 0; i < sizeof(x) * CHAR_BIT; i++) // unroll for more speed... { z |= (x & 1U << i) << i | (y & 1U << i) << (i + 1); }Interleaved bits (aka Morton numbers) are useful for linearizing 2D integer coordinates, so x and y are combined into a single number that can be compared easily and has the property
that a number is usually close to another if their x and y values are close.
25、 Compute the lexicographically next bit permutation
Suppose we have a pattern of N bits set to 1 in an integer and we want the next permutation of N 1 bits in a lexicographical sense. For example, if N is 3 and the bit pattern is 00010011, the
next patterns would be 00010101, 00010110, 00011001,00011010, 00011100, 00100011, and so forth. The following is a fast way to compute the next permutation.
unsigned int v; // current permutation of bits unsigned int w; // next permutation of bits unsigned int t = v | (v - 1); // t gets v's least significant 0 bits set to 1 // Next set to 1 the most significant bit to change, // set to 0 the least significant ones, and add the necessary 1 bits. w = (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(v) + 1));The __builtin_ctz(v) GNU C compiler intrinsic for x86 CPUs
returns the number of trailing zeros. If you are using Microsoft compilers for x86, the intrinsic is _BitScanForward. These both emit a bsf instruction, but equivalents may be available for other architectures. If not, then
consider using one of the methods for counting the consecutive zero bits mentioned earlier.
更多内容参照原文,我只是把我能理解的代码摘了下来,更多神奇的代码请看原文。
相关文章推荐
- batch批处理基础
- bootstrap(2)
- win32: 静态控件(Static) - SS_NOTIFY - 响应事件
- Android开发第二阶段(1)
- 读良葛格"初心者之路"有感
- C#基础语法:可空类型详解
- 通过事件调用窗体间的方法
- vc 不能将参数 1 从const char [*]转换为LPCWSTR
- IT相关找工作时间表
- sql server 语法
- malloc() 和 calloc()有啥区别
- Android(java)学习笔记111:成员位置的内部类的介绍
- [Fiddler]如何让Fiddler可以抓取https的请求
- Linux下查看隐藏文件的命令
- 举例详解Python中threading模块的几个常用方法
- chapter13test4
- 在Firefox中关闭缓存
- windows查看硬盘序列号
- Xamarin.Android打包apk
- Access restriction: The type FtpClient is not accessible due to restriction on required library