Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I create a 1-to-64 bits bitmask without a conditional in Java?

Tags:

java

bitmask

I want to write a function that takes an int between 1 and 64, and returns an appropriate "bitmask", with as many 1 bits as the input.

I started like this:

/** Computes a bitmaks */
private static long mask(final int bitsPerValue) {
    return (1L << bitsPerValue) - 1L;
}

But realized that it gives the wrong value for 64:

(1L << 64) - 1L == 1L - 1L == 0

Now I have this:

/** Computes a bitmaks */
private static long mask(final int bitsPerValue) {
    return (bitsPerValue == 64) ? -1 : ((1L << bitsPerValue) - 1L);
}

It's rather ugly. And conditionals can change the control flow, so they are more expensive than simple arithmetic operations. I could just pre-compute the masks and put them in a static array, but array access is also more expensive than simple arithmetic operations, probably even more expensive than the conditional.

Is there a reasonable way of writing this without a conditional? This code is going to run zillions of time per second, so it has to be fast.

like image 520
Sebastien Diot Avatar asked Jan 23 '12 11:01

Sebastien Diot


People also ask

What is bitmask Java?

Bitmasking allows us to store multiple values inside one numerical variable. Instead of thinking about this variable as a whole number, we treat its every bit as a separate value. Because a bit can equal either zero or one, we can also think of it as either false or true.

What is the purpose of a bitmask?

In computer science, a mask or bitmask is data that is used for bitwise operations, particularly in a bit field. Using a mask, multiple bits in a byte, nibble, word, etc. can be set either on or off, or inverted from on to off (or vice versa) in a single bitwise operation.

How do Bitmasks work?

Bit masks are used to access specific bits in a byte of data. This is often useful as a method of iteration, for example when sending a byte of data serially out a single pin. In this example the pin needs to change its state from high to low for each bit in the byte to be transmitted.

What is bit masking in C?

Bit masking is simply the process of storing data truly as bits, as opposed to storing it as chars/ints/floats. It is incredibly useful for storing certain types of data compactly and efficiently. The idea for bit masking is based on boolean logic.


2 Answers

Here is a way to do it without conditionals:

private static long mask(final int bitsPerValue) {
    return ((1L << bitsPerValue) - (bitsPerValue >> 6)) - 1L;
}

In Java, 1L << bitsPerValue only uses the six lowest-order bits of bitsPerValue, which means that calling your original function with bitsPerValue=64 is the same as calling it with bitsPerValue=0. The version I present above takes care of that: when bitsPerValue=64, the expression reduces to

(1L - 1L) - 1L == -1L

Now, if you're really going to be calling this "zillions of times per second", I think the best strategy is to benchmark all variants of the code, including the one with conditionals and the one with the lookup table.

like image 177
NPE Avatar answered Sep 30 '22 01:09

NPE


I tried:

long value = 0xffffffffffffffffl >>> (64 - i); // that's ef ef ef... el.

but this seems to give a problem with i = 0. My gripe with Java not having unsigned ints again. The above works in c. Maybe the above will work in Java 7, given that 'value' is unsigned.

However, since you don't need zero, the above will work fine for you, i.e. values 1 to 64.

like image 27
Jaco Van Niekerk Avatar answered Sep 30 '22 02:09

Jaco Van Niekerk