Answering somewhat indirectly: a great reference on how bit twiddling routines like this (and hundreds of others) work is the book "Hacker's Delight" by Henry Warren. I highly recommend it -- it belongs on every programmer's bookshelf. http://www.amazon.com/Hackers-Delight-Henry-S-Warren/dp/0201914654
Just round down to the nearest power of 2 and then XOR that with the original value, e.g. using flp2() from Hacker's Delight:
uint32_t flp2(uint32_t x) // round x down to nearest power of 2
x = x | (x >> 1);
x = x | (x >> 2);
x = x | (x >> 4);
x = x | (x >> 8);
x = x | (x >>16);
return x - (x >> 1);
uint32_t clr_msb(uint32_t x) // clear most significant set bit in x
msb = flp2(x); // get MS set bit in x
return x ^ msb; // XOR MS set bit to clear it
Using Guava, it's as simple as
long c = LongMath.checkedAdd(a, b); // throws an ArithmeticException on overflow
which is, I'd like to think, very readable indeed. (LongMath Javadoc here.)
For the sake of fairness, I'll mention that Apache Commons provides ArithmeticUtils.addAndCheck(long, long).
If you want to know how they work, well, the answer is one line of bit-hackery for Guava: the result doesn't overflow if (a ^ b) < 0 | (a ^ (a + b)) >= 0. This is based on the trick that the bitwise XOR of two numbers is nonnegative iff they have the same sign.
(a ^ b) < 0 | (a ^ (a + b)) >= 0
So (a ^ b) < 0 is true if a and b have different signs, and if that's the case it'll never overflow. Or, if (a ^ (a + b)) >= 0, then a + b has the same sign as a, so it didn't overflow and become negative.
(a ^ b) < 0
(a ^ (a + b)) >= 0
a + b
(For more tricks like this, investigate the lovely book Hacker's Delight.)
Apache uses more complicated casework based on the sign of a and b.
Here is a somewhat more efficient version of @hirschhornsalz's sum_and_overflow function:
void sum_and_overflow(__v4si a, __v4si b, __v4si& sum, __v4si& overflow)
__v4si sa, sb;
sum = _mm_add_epi32(a, b); // calculate sum
sa = _mm_xor_si128(sum, a); // compare sign of sum with sign of a
sb = _mm_xor_si128(sum, b); // compare sign of sum with sign of b
overflow = _mm_and_si128(sa, sb); // get overflow in sign bit
overflow = _mm_srai_epi32(overflow, 31); // convert to SIMD boolean (-1 == TRUE, 0 == FALSE)
It uses an expression for overflow detection from Hacker's Delight page 27:
sum = a + b;
overflow = (sum ^ a) & (sum ^ b); // overflow flag in sign bit
Note that the overflow vector will contain the more conventional SIMD boolean values of -1 for TRUE (overflow) and 0 for FALSE (no overflow). If you only need the overflow in the sign bit and the other bits are "don't care" then you can omit the last line of the function, reducing the number of SIMD instructions from 5 to 4.
NB: this solution, as well as the previous solution on which it is based are for signed integer values. A solution for unsigned values will require a slightly different approach (see @Stephen Canon's answer).
There is a book which gathers many of those 'magic tricks' and that may be interesting for you: The Hacker's Delight.
You have for example many tricks like bit twiddling hacks etc... (you have several square root algorithms for example that you can see on the google books version)
HD probably refers to Hacker's Delight by Henry S. Warren. Indeed, this formula appears on page 11, section 2-1.
I don't understand why all the answers to that question are the same.
There are several ways to calculate the square root from a number. One of them was proposed by Isaac Newton. I'll only write one of the simplest implementations of this method. I use it to improve the accuracy of double's square root.
// x - a number, from which we need to calculate the square root
// epsilon - an accuracy of calculation of the root from our number.
// The result of the calculations will differ from an actual value
// of the root on less than epslion.
public static decimal Sqrt(decimal x, decimal epsilon = 0.0M)
if (x < 0) throw new OverflowException("Cannot calculate square root from a negative number");
decimal current = (decimal)Math.Sqrt((double)x), previous;
previous = current;
if (previous == 0.0M) return 0;
current = (previous + x / previous) / 2;
while (Math.Abs(previous - current) > epsilon);
About speed: in the worst case (epsilon = 0 and number is decimal.MaxValue) the loop repeats less than a three times.
If you want to know more, read this (Hacker's Delight by Henry S. Warren, Jr.)
Sean's an incredibly bright guy but he's more interested in building world-changing apps and web dev. as opposed to low-level systems programming. There are other classes here where you have to code in assembly and do all sorts of bit manipulation (OS's comes to mind). The core CS sequence in our school is also in C, which differs notably from other places that use Python, Java, etc.
For anyone who wants to learn more about bit manipulation, Henry Warren's "Hacker's Delight" is a terrific book (http://www.amazon.com/Hackers-Delight-Henry-S-Warren/dp/0201...).
Author covers really clever techniques to count bits, count non zero bytes like this etc etc. Bit manipulation at its best.