Bit manipulation tips

Source: Internet
Author: User
Tags array length versions intel core 2 duo

Written by: This article was originally intended to write a bit twiddling hacks of a translation, but because the original bit bit operation skill also spent a lot of ink records the discovery and revision, this article does not contain the above content, only pay attention to bit-related operation skills, interested in these code authors please watch.
Preface

When the total operand is counted, any one of the C statements is considered an operation. An indirect assignment statement considers 0 operands because it does not write to memory. Of course, the total number of operations is approximate to the actual number of computer instructions and operating time. This article assumes that all operations take the same amount of time, although it is virtually impossible, but the gap is already very small in today's fast-growing CPUs speed. The execution time of a sample code is also related to the system's cache size, memory bandwidth, instruction set, and so on. The actual test is the final measure of the efficiency of a piece of code, the following code execution results are based on your actual test results. to find the symbol of an integral type

int V;      input, the symbol int sign of the integral type is obtained
;   Integer symbols (-1 for negative numbers, 0 for positive or 0) 

//Char_bit for bits per byte (typically 8).
Sign =-(v < 0);  If v < 0 then-1, else 0. 
Alternatively, the method of avoiding branching judgment is as follows: sign
=-(int) ((unsigned int) ((int) v) >> (sizeof (int) * char_bit-1));
Or, fewer operands but a less portable line method:

The last expression of the preceding code calculates a 32-bit integer symbol with sign = v >> 31. This will be faster than the intuitive sign =-(v < 0). The way this method works is because, when the symbol integral is moved right, the leftmost sign bit is padded to the right. The leftmost symbol for the negative integer is 1, 0 and the positive integer symbol is 0, and all bits are 1-1 (complement notation). Unfortunately, the method is only applicable with a specific schema.

Alternatively, you may want the result to be expressed as-1 or + 1, then you can use:

Sign = +1 | (v >> (sizeof (int) * char_bit-1));  If v < 0 then-1, else +1

Or, you want the result to be 1, 0, or 1, then use:

Sign = (v! = 0) | -(int) ((unsigned int) ((int) v) >> (sizeof (int) * char_bit-1));
Or, faster but less portable versions: Sign
= (v! = 0) | (v >> (sizeof (int) * char_bit-1));  -1, 0, or +1
//or, shorter, more intuitive and portable, better versions: sign
= (V > 0)-(v < 0);//-1, 0, or +1

If you want to know if a number is non-negative, use +1 for non-negative, 0 for negative, you can use:

Sign = 1 ^ ((unsigned int) v >> (sizeof (int) * char_bit-1)); If v < 0 then 0, else 1

Warning: 1989 ANSI C Specification no longer defines the result of the right-shift operation of the symbol, which may not be valid on some systems that involve a right-shift operation. determine if two integers are the opposite of the symbol

int x, y;               Enter, judging whether these two-digit symbols are opposite

bool F = ((x ^ y) < 0);//True if the X, y symbol is opposite
absolute value of the integral type (ABS, no branch judgment)
int V;           Input integral type
unsigned int r;  The absolute value of 
int const MASK = v >> sizeof (int) * CHAR_BIT-1;

R = (v + mask) ^ mask;
Variable of the same effect:
r = (v ^ mask)-mask;

Some CPUs do not have an integer absolute value directive (or the compiler does not use it). Branching judgment on some machines can be expensive, and the above expression is simpler than the simple method r = (v < 0)? -(unsigned) v:v to be fast, even if their operands are the same. maximum minimum value of two integers (no branch judgment)

int x;  For x, y, the minimum value
int y;   
int R;  Result

r = y ^ ((x ^ y) &-(x < y));//min (x, y)

On some machines branching judgment operations may be more expensive than the simple method of R = (x < y)? The x:y is fast, even though the 2 operation is more than one. (Of course, it is generally best to use simple methods that are easy to understand.) The principle of the formula is: if X<y, then-(x-y) is all 1, so r = y ^ (x ^ y) & ~0 = y ^ x ^ y = x. Also, if x>=y, then-(x<y) is all 0, so r = y ^ ((x ^ y) & 0) = Y. On some machines, the x<y may require a branch judgment instruction, which will be worse than the simple method.

Maximum value:

R = x ^ ((x ^ y) &-(x < y)); Max (x, y)

determines whether an integral type is a power of 2

unsigned int v; Input
bool F;         If V is a emerges of 2, F is true

F = (V & (V-1)) = = 0;

The above incorrectly considers 0 to be a power of 2, and in order to fix this, use:

f = v &&! (V & (V-1));
fixed length symbol extension

For the built-in type (chars ints) symbol extension is done automatically, but suppose you have a sign using the B-complement representation of the number x and want to turn it into an int. If x is positive, a simple copy is possible, but if it is negative, the sign bit must be adjusted to the highest level. For example, we use a 4-bit representation-3 is 1101. If the 8-bit representation-3 is 11111101. You can see that the extra 4 bits on the left use the sign bit fill, which is the symbol extension. In C, symbolic expansion of the fixed-length type is straightforward. The following equation expands a 5bits into an integral type:

int x; input, the int uses only the lowest 5 bits
int r;//The result of the symbol extension
struct {signed int x:5;} s;
r = s.x = x;

The following C + + template functions convert B bits to type T using the same method.

Template 
inline T signextend (const T x)
{
  struct {T x:b;} s;
  return s.x = x;
}

int r = signextend (x);  To extend the 5 bits symbol to an integral type R
conditional Position
bool F;         Flag
unsigned int m;//mask
unsigned int w;//The Word to be placed:  if (f) W |= m; else W &= ~m; 

W ^= (-f ^ w) & M;

Or, for superscalar CPUs
w = (W & ~m) | (-F & M);

For some schemas, a version without branching can compensate for the extra operand. In the informal speed test, the AMD Athlon™xp 2100+ on the fast-5-10%. The second formula is 16% faster than the first formula in Intel Core 2 Duo superscalar version. condition take negative

If you want to reverse a number only if a flag is false, you can avoid branching judgment by using the following methods:

BOOL Fdontnegate; 
int V;             Input, if Fdontnegate is false,v to take the inverse
int r;             r = fdontnegate? V:-V;

r = (fdontnegate ^ (fDontNegate-1)) * V;

If you want to reverse only if flag is true, use:

BOOL Fnegate;  
int V;         Input, if Fdontnegate is true,v to take the inverse
int r;         result = Fnegate? -v:v;

R = (v ^-fnegate) + fnegate;
based on the mask and the bitwise
unsigned int A;    
unsigned int b;    
unsigned int mask; The mask, if a bit is 0, is taken from a value, otherwise from B takes
unsigned int r;    R = (A & ~mask) | (B & Mask)

The upper style has one less action than the simple method in the annotation, but if mask is a constant, the upper style will have no advantage. Statistics Bits count (simple method)

unsigned int v; Count 1 in v
unsigned int c;//result for

(c = 0; v; v >>= 1)
{
  c + = v & 1;
}

The simple method loops once for each bit, and for the 32-bit word with the highest bit of 1, it loops 32 times. Statistics bits count (table method)

static const unsigned char bitssettable256[256] = {# define B2 (n) n, n+1, n+1, n+2 # define B4 (n) B2 (n)

, B2 (n+1), B2 (n+1), B2 (n+2) # define B6 (n) B4 (n), B4 (n+1), B4 (n+1), B4 (n+2) B6 (0), B6 (1), B6 (1), B6 (2)}; unsigned int v; Count 1 in v unsigned int c; Results//Method 1:C = bitssettable256[v & 0xFF] + bitssettable256[(v >> 8) & 0xFF] + BitsSetTable256 

[(v >>) & 0xFF] + bitssettable256[v >> 24];
Method 2:unsigned char * p = (unsigned char *) &v;


c = bitssettable256[p[0]] + bitssettable256[p[1]] + bitssettable256[p[2] [+ bitssettable256[p[3]];
Or use the statement to initialize the query table: bitssettable256[0] = 0; for (int i = 0; i < i++) {Bitssettable256[i] = (I & 1) + BITSSETTABLE256[I/2];} 
count Bits (Brian Kernighan method)
unsigned int v; Count 1 in v
unsigned int c;//result
for (c = 0; v; c + +)
{
  v &= V-1;//clear lowest bit 1
}

Brian Kernighan Loops The same number of bits, and it only needs to loop once for the 32-bit word with the highest bit 1. This method first appeared in the 1988 "C Programming Language" Second edition of Exercise 2-9. (Author is Brian W. Kernighan and Dennis M. Ritchie) count bits (parallel method)

unsigned int v; Count the number of 1 in v
unsigned int c;//result
static const int s[] = {1, 2, 4, 8, 16};//Magic 2 binary number
static const int b[] = { 0x55555555, 0x33333333, 0x0f0f0f0f, 0x00ff00ff, 0x0000ffff};

c = v-((v >> 1) & B[0]);
c = ((c >> s[1]) & B[1]) + (C & b[1]);
c = ((c >> s[2]) + C) & B[2];
c = ((c >> s[3]) + C) & B[3];
c = ((c >> s[4]) + C) & B[4];

The numbers in array B are represented by the 2 binary:

B[0] = 0x55555555 = 01010101 01010101 01010101 01010101
b[1] = 0x33333333 = 00110011 00110011 00110011 00110011
B[  2] = 0x0f0f0f0f = 00001111 00001111 00001111 00001111
b[3] = 0x00ff00ff = 00000000 11111111 00000000 11111111
B[4] = 0X0000FFFF = 00000000 00000000 11111111 11111111

For larger integers, we only need to expand the arrays of B and S. For the K bits,s array and the B array length is ceil (LG (k)). (here LG is the base 2 logarithm function, the same as the writer note)

The best way to count the number of bits 32-bit is the following formula:

v = v-((v >> 1) & 0x55555555);                    00->00, 01->01, 10->01, 11->10
v = (V & 0x33333333) + ((v >> 2) & 0x33333333);     Temp variable
c = ((v + (v >> 4) & 0xf0f0f0f) * 0x1010101) >> 24;//Results

The above method can be parameterized according to type T (for both 128 and length types):

v = v-((v >> 1) & (t) ~ (t) 0/3);                           
v = (V & (t) ~ (t) 0/15*3) + ((v >> 2) & (T) ~ (t) 0/15*3);      
v = (v + (v >> 4)) & (T) ~ (t) 0/255*15;                      
c = (t) (V * ((t) ~ (t) 0/255) >> (sizeof (t)-1) * CHAR_BIT; Results

The above is the best way to count bits, with the same operand and look-up method, but without additional memory overhead. See Ian Ashdown's nice newsgroup post for more details, also known as sideways addition. finding the parity of the total bits number

unsigned int v;       Input, find the parity of the total bits number
bool parity = false;  As a result, an odd number is expressed as true (1), and False (0) indicates an even while

(v)
{
  parity =!parity;
  v = v & (V-1);
}

Similar to the Brian Kernigan method, the sum of bits is counted, and the number of cycles is equal to the total bits. Find the parity of the total bits number (table method)

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;  Input, find the parity of the total bits number
bool parity = paritytable256[b];

For 32-bit Word:
unsigned int v;
V ^= v >>;
V ^= v >> 8;
BOOL parity = paritytable256[v & 0xFF];

Variable:
unsigned char * p = (unsigned char *) &v;
parity = paritytable256[p[0] ^ p[1] ^ p[2] ^ p[3]];
find the parity of the total bits number (take the remainder method)
unsigned char b;  Input, to find the parity of the total bits number of
bool parity = ((( 
  (b * 0x0101010101010101ull) & 0x8040201008040201ull)% 0x1ff) & 1;

The upper type has only 4 operations and is only valid for bytes. find the parity of the total bits number (parallel method)

unsigned int v;  Input to find the parity of the total bits of
v ^= v >>;
V ^= v >> 8;
V ^= v >> 4;
V &= 0xf;
return (0x6996 >> v) & 1;

The above formula is only about 9 operations and is suitable for 32 words. Some optimizations can be made to a single byte (delete 2, 3 rows). The 0x6996 in the above formula is the 4-bits parity lookup table, and the No. 0 bit after the shift is the parity value. Exchange Value (XOR mode)

#define SWAP (A, B) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b)))

This is the method of exchanging values without additional temporary variables, which I believe is

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.