bitmasks - but my brain is fried
bitmasks - but my brain is fried
Author
Discussion

TheExcession

Original Poster:

11,669 posts

280 months

Friday 27th May 2005
quotequote all
help....

I need to do some bit masking, I do have some Java project work from this before but it's all on a machine that I can't access at the moment.

ok - I have a mask value, let's start with something simple - 00000111 int 7 - I need to mask a value into this say 3 so the result would be 00000011

However next time I might have a mask 01110000 and when the value is three I need 00110000 as the result.

Likewise, if the mask is 11110000 and the value is 7 I need 01110000 as the result.

I know I need to AND the value and mask but how to shift the value I'm applying into the correct position to apply the AND...

Antone hot to trot on this?

cheers
Ex

>> Edited by TheExcession on Friday 27th May 15:42

TheExcession

Original Poster:

11,669 posts

280 months

Friday 27th May 2005
quotequote all
Sussed.... I think....

where sMask is a string like "11100000"
picking up the last 1 and trailing zeroes gives "100000"
parse this as binary number and multiply the Value to be masked/shifted.

int Multipler = Integer.parseInt(sMask.substring(sMask.lastIndexOf("1"),2);

int NewValue = Multipler * Value;

Seems to work, likely there is a better way.

cheers
Ex

BliarOut

72,863 posts

269 months

Friday 27th May 2005
quotequote all
TheExcession said:
Sussed.... I think....

where sMask is a string like "11100000"
picking up the last 1 and trailing zeroes gives "100000"
parse this as binary number and multiply the Value to be masked/shifted.

int Multipler = Integer.parseInt(sMask.substring(sMask.lastIndexOf("1"),2);

int NewValue = Multipler * Value;

Seems to work, likely there is a better way.

cheers
Ex


You need to get outside more, it's sunny out there

pdV6

16,442 posts

291 months

Friday 27th May 2005
quotequote all
Not sure you've explained what you're trying to do very well.

The usual use for bitmasks is to check if a certain bit is set. Therefore what you do is a logical AND on the value you have with the bit you're interested in. This masks out all the other bits to 0.

E.g.
If the bit you're interested in is the 3rd one (value 4) i.e. 00000100

For a given value of, say, 9 (00001001), 9 AND 4 returns 0 (00000000) so your bit isn't set
For a given value of 22 (00010110), 22 AND 4 returns 4 (00000100)


To elaborate, compare any number with your mask using a bitwise AND and you'll see how it works:

XXXXXXXX
AND
00000100
=
00000X00

where X is either 1 or 0

Not sure off the top of my head what the bitwise AND operator is in Java, so substitute it for "AND" as appropriate.

If there's more than one bit you're interested in, the principle is the same.

ATG

23,801 posts

302 months

Friday 27th May 2005
quotequote all
String slicing is a bit ugly. You could keep dividing your mask by two until the least significant bit is a 1, then do a "bitwise and" to apply the mask and then multiply the value by 2^(number of divide-by-twos you did earlier) to shift the masked bits back to the right.

editted to say, when I said "right" i obviously meant "left" ... dunno why, but I've always written binary numbers the wrong way round.

>> Edited by ATG on Friday 27th May 16:17

pdV6

16,442 posts

291 months

Friday 27th May 2005
quotequote all

Oh hang on, I see what you're after - you're simply trying to knock off the highest order bit from any given value?

If so, all you need to do is shift the original value down 1 bit and AND the result with itself.

e.g. (1)
01110000
AND
00111000
=
00110000

e.g. (2)
00000111
AND
00000011
=
00000011

Not sure what the Java operator for bit shifting is, though.

D'oh! Even if there isn't a native bit shift operator, you could simpy divide by 2 and discard any remainder

e.g. value 112 (01110000) /2 = 56 (00111000)
112 AND 56 = 48 (00110000)

value 7 (00000111) /2 = 3 (00000011)
7 AND 3 = 3 (00000011)

>> Edited by pdV6 on Friday 27th May 16:24

TheExcession

Original Poster:

11,669 posts

280 months

Friday 27th May 2005
quotequote all
BliarOut said:
You need to get outside more, it's sunny out there
It's pissing with rain over here....

pdV6 said:
Not sure you've explained what you're trying to do very well.
I'll try again now as....
ATG said:
String slicing is a bit ugly.
and what I just posted didn't work to well with a mask of 1000000 - it wrapped into a negative number...

So here goes.

I'm trying to encode 3GPP QoS values into a RADIUS message.

They apply several settings into one byte....

e.g. Octet 3 is encoded as follows:

bits
87654321
00------: spare - not used
--111---: Delay Class
-----111: Reliabillity Class

So as you can see these Classes can take 0 - 7 as a value.

I need to encode them into byte value ready to stick them into a RADIUS packet

So assuming my Delay Class is 5 and my Reliabillity Class is say 3 I need to end up with:
00101011 as a byte value.

Now to complicate matters, this structure is defined in a scripting languge that I've written.
This means I only have an octet number, a mask, and a value to work with.

To get the example given above I have two pieces of information:
a. octet = 1, mask = 00111000, value = 5
b. octet = 1, mask = 00000111, value = 3

from this info I need to create a byte value of 00101011

God, I'd rather be drinking beer.....

cheers
Ex



pdV6

16,442 posts

291 months

Friday 27th May 2005
quotequote all
TheExcession said:

I'm trying to encode 3GPP QoS values into a RADIUS message.

They apply several settings into one byte....

e.g. Octet 3 is encoded as follows:

bits
87654321
00------: spare - not used
--111---: Delay Class
-----111: Reliabillity Class

So as you can see these Classes can take 0 - 7 as a value.

I need to encode them into byte value ready to stick them into a RADIUS packet

So assuming my Delay Class is 5 and my Reliabillity Class is say 3 I need to end up with:
00101011 as a byte value.

Easy, then, if you have a bit-shift operator

radius value = (delay value upshifted by 3 bits) OR (reliability value)

Without a bitshift operator, multiply by 8 to upshift by 3

e.g.
del=5 (00000101)
rel=3 (00000011)
rad = (5*8) OR 3
= 40 OR 3
= 00101000 OR 00000011
= 00101011

volia!

chrisjl

787 posts

312 months

Friday 27th May 2005
quotequote all
pdV6 said:

Easy, then, if you have a bit-shift operator


I think part (or most?) of the problem is that the shift amount isn't known in advance, and has to be worked out from the placeholder (previously referred to as 'mask', but it's not really a mask in the conventional sense as it contains width and offset information in a single value).
Or maybe I've missed something in the description...

>> Edited by chrisjl on Saturday 28th May 09:50

d-man

1,019 posts

275 months

Friday 27th May 2005
quotequote all
ATG said:
You could keep dividing your mask by two until the least significant bit is a 1, then do a "bitwise and" to apply the mask and then multiply the value by 2^(number of divide-by-twos you did earlier) to shift the masked bits back to the right.

editted to say, when I said "right" i obviously meant "left" ... dunno why, but I've always written binary numbers the wrong way round.


this seems the best way, shift the mask right until the lsb is 1, bitwise and it with the value and then shift it back left the same number of times. Then just bitwise or all the results together to get the full byte you need.

GreenV8S

31,021 posts

314 months

Friday 27th May 2005
quotequote all
Wouldn't it be easier to do away with masks as the way to define the bitfield positions, and replace them with bit offset/width properties? Then it is straight forward to construct the mask, shift the mask and value the appropriate number of places and set them into the result.

>> Edited by GreenV8S on Friday 27th May 23:12

Size Nine Elm

5,167 posts

314 months

Saturday 28th May 2005
quotequote all
The easiest way to solve this problem is... to define precisely what the problem is before you start. Then its easy... a la GreenV8S below.

I hate it when people refer to posts 'above' or 'below' - it depends on your preferences setting.

john_p

7,073 posts

280 months

Saturday 28th May 2005
quotequote all
TheExcession said:

I'm trying to encode 3GPP QoS values into a RADIUS message.




Purely out of geeky interest, for what application?

TeamD

5,060 posts

262 months

Tuesday 31st May 2005
quotequote all
No doubt you've worked this out by now, but something like this should work (based upon the info supplied):


import java.io.*;

class TestMask
{
public byte maskUp(String mask, int value)
{
return (byte)(((value))<<(7-(mask.lastIndexOf("1" ) ) ) ) ;
}
}

class TestMain
{
public static void main(String[] argv)
{
String str1 = new String("00111000" ) ;
String str2 = new String("00000111" ) ;
int val1 = 5;
int val2 = 3;
byte result;
TestMask tm;

tm = new TestMask();
result=(byte)(tm.maskUp(str1,5)|tm.maskUp(str2, 3) ) ;
System.out.println("Result: " + result) ;
}
}

Dammit!, edited to get rid of the smilies, pesky mofos.

As for you comment about going negative, it doesn't mean that the bit pattern is wrong, just that the decimal interpetation is of a negative number. The bitwise OR operator ( | ) shouldn't give a stuff about the sign bit set or not because it's still a bit.

>> Edited by TeamD on Tuesday 31st May 17:55

>> Edited by TeamD on Tuesday 31st May 17:56