jamesbrowder / guava-libraries

Automatically exported from code.google.com/p/guava-libraries
Apache License 2.0
0 stars 0 forks source link

Bit manipulation for primitive types #739

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Hello everybody,

it would be great to have a class to perform simple bit manipulation on 
primitives in a human readable way.

Assume we have...

 short i=123; //0b0111_1011
 int bitIndex=3; //the index of the bit we want to manipulate

...add the following use cases:

  //1. set a bit
  i |= (1<<bitIndex); 

  //2. clear a bit
  i &= ~(1<<bitIndex);

  //3. Check if the bit at the given index is 'true'
  if (((i>>bitIndex)&1)==1){..}

  //or 
  if ((i>>bitIndex&1)==1){..}

All 3 cases are extreme hard to read and i think it can be done in an more 
readable way. Since 'java.util.BitSet' can't help use here I would like to see 
a class like 'com.google.common.primitives.Bits'. Here are 2 samples for the 3 
cases using a mirco-DSL API :

import static com.google.common.primitives.Bits.*;

//---- proposal A
  //1. set a bit
  i = setBit(bitIndex,true).on(i); 

  //2. clear a bit
  i = setBit(bitIndex,false).on(i);

  //3. Check if the bit at the given index is 'true'
  if (isBit(bitIndex).on(i)==true){..}

//---- proposal B
  //1. set a bit
  i = using(i).setBit(bitIndex,true); 

  //2. clear a bit
  i = using(i).setBit(bitIndex,false);

  //3. Check if the bit at the given index is 'true'
  if (using(i).getBitAt(bitIndex)==true){..}

What do you think about it? 

Original issue reported on code.google.com by chriss....@gmail.com on 5 Oct 2011 at 1:01

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
The attachment contains a simple implementation of proposal A.

Original comment by chriss....@gmail.com on 5 Oct 2011 at 6:33

Attachments:

GoogleCodeExporter commented 9 years ago
This might happen in common.math, but...I'm not sure it's necessary.  If you're 
doing bit manipulation at all, you're already doing pretty low-level stuff, and 
I'm not sure that most people doing bit manipulation at all need increased 
readability?

Original comment by wasserman.louis on 10 Oct 2011 at 2:30

GoogleCodeExporter commented 9 years ago
(I'm very much willing to be convinced here.  I just want someone else to 
convince me.)

Original comment by wasserman.louis on 10 Oct 2011 at 2:33

GoogleCodeExporter commented 9 years ago
When it comes to bit manipulation at the most ppl get afraid because:
* it is a mess of '>>', '^', ...   
* it takes to much time to remind basic bit operations (as you said, it not a 
common task) 
* it's error prone ('>>' vs '>>>')
* is unreadable and it takes a too looooong to understand code that perform 
plenty bit operations
* there a to many ways to perform even simple tasks (some ppl using 
math-operation like % to check for a bit)

Original comment by chriss....@gmail.com on 10 Oct 2011 at 4:04

GoogleCodeExporter commented 9 years ago
I know I have looked at code that does bit manipulation and been thinking "what 
the he**?" Crap, now I have to go refresh on bit manipulation. I recently 
looked at BitSet but was not impressed. After that I immediately went to Guava 
primitives and was sad to see that there was not a better bit manipulation 
class.

Original comment by dancerj...@gmail.com on 10 Oct 2011 at 8:15

GoogleCodeExporter commented 9 years ago
I don't think that such a class would get used a lot. Dealing with bits usually 
means that efficiency is important, and creating an object in order to set a 
single bit could mean a slowdown by a big factor. Your proposal A could 
possibly be optimized by pre-creating 64 BitGetter-s and 128 BitManipulator-s, 
your proposal B could not. I'm not sure if it helps much, since it could lead 
to more cache-misses.

So maybe a low-level syntax A'

i = setBit(bitIndex, true, i);
if (isBit(bitIndex, i)){..}

or maybe B'

i = setBitOf(i, bitIndex, true);
if (isBitOf(i, bitIndex)){..}

could get more use as it involves no runtime cost.

Original comment by Maaarti...@gmail.com on 12 Oct 2011 at 6:12

GoogleCodeExporter commented 9 years ago
I probably wouldn't use it either (for performance reasons) but the votes on 
this StackOverflow answer suggest that some coders prefer an 
inefficient-but-more-readable syntax:

http://stackoverflow.com/questions/1092411/java-checking-if-a-bit-is-0-or-1-in-a
-long/1092551#1092551

Original comment by fin...@gmail.com on 13 Oct 2011 at 1:14

GoogleCodeExporter commented 9 years ago
I have written a small performance test, it calculates a checksum 2mio times. 
The results are closer than expected...
~3700ms  <- proposal A (without any parameter assertions)
~1500ms  <- using raw operations

..not that bad, i think ! 

Original comment by chriss....@gmail.com on 13 Oct 2011 at 5:55

Attachments:

GoogleCodeExporter commented 9 years ago
Btw.: The raw implementation took 2h of my life, till I figured out that a 
right shift operation on byte-value 0b1000_0000 is not 0b0100_0000 as expected. 
For some crazy reason it's 0b1100_0000.
People who won't spend time on solving java puzzles could take advantage of a 
Bits-class...    

Original comment by chriss....@gmail.com on 13 Oct 2011 at 6:14

GoogleCodeExporter commented 9 years ago
I would strongly prefer a somewhat less verbose implementation.  I don't think 
builder-style syntax is the way to go here.  I find bit-twiddling much more 
readable when important intermediate values can get their own variable with 
their own name.

Here are some methods I would be potentially in favor of offering, for each 
numeric type X:

X shiftLeft(X x, int bits)
   // (x << bits) just ignores all but the last X.SIZE bits, which can be unexpected.
   // shiftLeft(X, bits) would behave more predictably.
X shiftRightLogical(int x, int bits)
   // Not only does this share the advantages of shiftLeft over <<, but it
   // disambiguates >> and >>>.
X shfitRightArithmetic(int x, int bits)
X setBit(X x, int bit)
X clearBit(X x, int bit)
X flipBit(X x, int bit)
X setBit(X x, int bit, boolean value)
boolean testBit(X x, int bit)

Original comment by wasserman.louis on 16 Oct 2011 at 11:22

GoogleCodeExporter commented 9 years ago
I don't think this is an adequately common use case to really merit the number 
of methods that it would entail.

Original comment by wasserman.louis on 28 Oct 2011 at 4:30

GoogleCodeExporter commented 9 years ago
I am also highly skeptical; I think that most users who would use this should 
really be using an even higher abstraction.

Original comment by kevinb@google.com on 15 Nov 2011 at 10:30

GoogleCodeExporter commented 9 years ago
This issue has been migrated to GitHub.

It can be found at https://github.com/google/guava/issues/<id>

Original comment by cgdecker@google.com on 1 Nov 2014 at 4:15

GoogleCodeExporter commented 9 years ago

Original comment by cgdecker@google.com on 3 Nov 2014 at 9:09