tags:

views:

181

answers:

2

I am writing a function short getBits(short data, int p, int n)

I have tried:

public static short getBits(short data, int p, int n) {
 short bitmask = (short) ((~0 << (16 -n)) >>> p);
 short returnVal = (short) ((bitmask & data) >>> (16 - n));
 return returnVal;
}

This works for getBits( (short) 0x7000, 0, 4) but if I were to replace the 7 with an 8 I get a negative value.

+1  A: 

There are a few things to remember about java data types, to make this thing work.

I'm assuming you're using int variables because of the absence of explicit casts in your expression. If you're using an int type for your variables: data start_pos, and length; you should be using 32 instead of 16, since int's are 32-bit values.

Also if you're going to use integer primitive types like int, short or byte, remember that these primitive types are two's complement that are sign-extended, meaning that if you do a right shift on negative numbers like ~0 (evaluates to -1), ones will be appended on the higher order bit (sign bit) instead of zeroes.

For instance:

1111 1111 1111 1111 1111 1111 1111 1000        
>>1
1111 1111 1111 1111 1111 1111 1111 1100

Now going back to your problem. The general idea is to be able to do a:

data & mask

Now, generating the mask is a bit tricky on signed data types. It would make sense to generate the mask using:

(~0 << (32 - length) >> (32 - length - start_pos))

But this won't work of course because of the sign extension.

I would suggest that instead of using right-shift >>, use rotate operator >>> that way instead of ones being appended on the higher order bit, the rotate operator will append the lower order bit.

For instance:

1111 1111 1111 1111 1111 1111 1111 1000        
>>>1
0111 1111 1111 1111 1111 1111 1111 1100

so...

mask = (~0 << 32-length >>> 32-length-start_pos)

And your final answer would look something like:

(data & (~0 << 32-length >>> 32-length-start_pos)) >>> start_pos

The outermost rotate operation moves your masked data to the lower order bits.

jafaeldon
powerj1984
@powerj1984 - The OP appear to have "p" mean; counting from the least significant bits. Your solution would work if you mean; counting from the most significant bit.
Peter Lawrey
Would be great marking your question as resolved by theis anwser, elsewhere StackOverflow will soon become a stack overflow of unanwsered questions.
Riduidel
A: 

Not sure why you need to use short. Here is a solution using long.

public static long getBits(long data, int p, int n) {
    assert p >= 0 && p < 64;
    assert n >= 0 && n < 64;
    return (data >> p) & ((1 << n) - 1);
}
Peter Lawrey