Is there still no bitwise NOT?

BlitzMax Forums/BlitzMax Beginners Area/Is there still no bitwise NOT?

sswift(Posted 2006) [#1]
I have discovered I can so Blah = Blah Xor $FFFFFFFF to do a bitwise not, but I would think I should be able to do a normal bitwise not, like you can in C. I think in C it would go something like Blah = !Blah.

Maybe the Boolean Not would work in BlitzMax, but I'm pretty sure it didn't work in other versions of Blitz, so I don't trust it will work here.


tonyg(Posted 2006) [#2]
x=1
x=not x
print x



ImaginaryHuman(Posted 2006) [#3]
Bitwise not is ~

There is a thread elsewhere about the difference between using ~ for not or for xor.

If you do:

x=1
x=~x
print x

you'll get a bitwise not of x only

if you include a second variable in the operation, it turns it into an xor

x=1
y=2
x=x~y
print x

prints the xor of the two values

If you think about it, since ~value is the same as FFFFFFFF xor value, it would be a waste of space for BRL to create a separate specific ! operator. If you want to do something like:

a=b + !d

do

a=b+(~d)

put it in brackets.


taxlerendiosk(Posted 2006) [#4]
tonyg: That is logical "Not", not bitwise.


sswift(Posted 2006) [#5]
Angel:
Thanks, that works!

But you don't need to put it in brackets to use it as in your last example.

And I don't think it would be a waste to allow us to use !. It would be one less difference from other languages like C, and it would not confuse people who think it is doing something with xor but they can't figure out what.


Azathoth(Posted 2006) [#6]
Isn't ! used for declaring Doubles or something?


Dreamora(Posted 2006) [#7]
Binary not: Not
Bit Not: ~
binary invert (bitwise not for all bits): value ~ $FF (or how many bytes it has)


Michael Reitzenstein(Posted 2006) [#8]
binary invert (bitwise not for all bits): value ~ $FF (or how many bytes it has)

Or just ~value, surely?


ImaginaryHuman(Posted 2006) [#9]
Yup.

And yes, I think ! is used for something more important. Get over it ;-D


Dreamora(Posted 2006) [#10]
No ~value does not work ... tried that back when someone asked on the bug board. I would have assumed a similar behavior as well ...


Michael Reitzenstein(Posted 2006) [#11]
Yes, it DOES work.

Local value = %111

Print Bin( ~value )



Yan(Posted 2006) [#12]
I think he means...
Local b:Byte = 0
Print Bin(~b) ' gives -1 (I meant just negative) even though it's unsigned.
Print Bin(Byte(~b))
Print Bin(b ~ $FF)
Local b:Byte
Local i:Int = $FFFFFFFF

Print Bin(i ~ (~b))
Print Bin(i ~ (b ~ $FF))


SSwift, What do you mean *still*?

~ has been the bitwise compliment/not since B2D (at least)!


Dreamora(Posted 2006) [#13]
Yes if you use binary.
But any number is in real a binary so it should work any numeric type without inverting it!

If you invert 0 (type Byte) you should get 255 which you do not get as a mather of facts.


sswift(Posted 2006) [#14]
Bill:
Wow. You're right.

But where is it in the freaking help file?!

I've been coding in Blitz for about five years now, asking for bitwise NOT at times, like when trying to work directly with Windows, and other folks have agreed with me that it was unfortunate it didn't have it, and would offer "solutions" like using subtraction. I ended up solving the problem by simply not using not, and using constants that I inverted manually. I only just found the xor trick the other day.

It sure would have been nice if it were documented, or Mark, or someone else in the know would have answered my posts asking for a bitwise not all those times. Sheesh!


ImaginaryHuman(Posted 2006) [#15]
I think Bin `extends` the variable to an Integer before displaying it? If the uppermost bit in the number is set, it will fill all the upper 24 bits with 1's as well, to represent -1 as an Integer. I had the same thing happen with Hex$() trying to display Double's. As soon as you set the 31st bit it fills the upper 32 bits with 1's, as part of displaying it (original data unchanged).

So you're SEEING -1, as 11111111111111111111111111111111, but that's because of the display technique. If you print value Shr 8 you'll notice it's 0 instead of having 8 0's at the top end.

And yes, again, it DOES work to do ~value, same as !value


Dreamora(Posted 2006) [#16]
I'm sorry
I'm wrong. Seems like one of the last SyncMods changed something since the thing was posted in the bugs

sorry for that *shutting myself*

PS: I'm aware how the 2 complement in PC works ... its part of my education ...


Yan(Posted 2006) [#17]
And yes, again, it DOES work to do ~value, same as !value
Yes, I know. I was the one that showed you (your thread about subtracting 2 unsigned longs). :o)

I think you're missing the point I was making (albeit, rather badly)...
Local b:Byte = $FF

Print b

Print ~b ' Should an unsigned variable be represented as being negative? I'd say not.


[edit]But It appears that wasn't what Dreamora was going on about anyway...:o)[/edit]


Dreamora(Posted 2006) [#18]
That was my point. But the convert to string seems to involve a convert to a different numeric type first. If you enclose the ~b with a byte() it will result in 255 (checked that before the above posting).

Its just another of BMs extremely inconsistent handling of situations and operators :(


Yan(Posted 2006) [#19]
If you enclose the ~b with a byte() it will result in 255
Yeah, I already did that above.

It's still wrong IMHO!

A byte containing $FF when converted to an int should be $000000FF, not $FFFFFFFF...
Local b:Byte
Local i:Int = $FFFFFFFF

Print i & (~b) ' Shouldn't this be $FFFFFFFF AND $FF (255) ??

'b' = ~b
Print i & b ' Like this?
'b' shouldn't be converted to an int before inversion.

Am I just talking from my nether regions here?


Anyway, after that completely pointless rantette...


@Sswift - It's in the docs (for B3D at least), but it *is* well hidden. ;o)

Go to 'Language Reference>Expressions'.


Azathoth(Posted 2006) [#20]
For some reason you need to cast (~b) to a byte
This works
Local b:Byte
Local i:Int = $FFFFFFFF

Print i & Byte(~b) ' $000000FF

'b' = ~b
Print i & b ' Like this?



ImaginaryHuman(Posted 2006) [#21]
I think it is the print statement itself that extends it from byte to Int equivalent, producing the extra bits. Probably when you do ~byte it actually does only invert the 8 bits, but when you PRINT it it prints additional made-up bits. Your byte variable is still only $FF.


sswift(Posted 2006) [#22]
Local a:Int
Local b:Byte

b = %100000001
b = ~b

Print Bin(b)

a = ~b

Print Bin(a)


I suspect this is the source of the problem. B is getting converted to an int before the NOT is performed, and when you perform the NOT on an int, you get the result you see here.


Yan(Posted 2006) [#23]
LOL...This is what happens when you try to operate a forum when you're suffering from sleep deprivation. ;oD

I know that's what's happening, I just didn't explain it very well.

It's definitely not just the print statement...
Local b:Byte = 0
Local i2:Int = $FFFFFFFF

Local i2:Int = i & ~b

Print "'i2' should be 255, it's actually " + i2
Print "Especially for AngelDaniel - " + (i2 Shr 24)

i2 = i & Byte(~b)
Print i2
It's probably not a good idea to be mixing different variable types like this anyway though.

I just thought it was worth a mention. I tend to just stick to ints anyway.


ImaginaryHuman(Posted 2006) [#24]
The operation is wrong

It should be Local i2:Int=i~b


Yan(Posted 2006) [#25]
*sigh*...I give up... 8o/

But, can I have some?


rdodson41(Posted 2006) [#26]
In C bitwise xor is the ^ opperator and bitwise not is the ~ character. So BMX just uses the ~ for both because ^ is the exponent opperator. But making ! the bitwise not opperator would be bad because in every other language ! is the logical not. ( The notequal opperator <> should be != but I think it doesn't matter as much.)

I was thinking that maybe the Byte type is actually signed, because in C (or at least in the MacOS X gcc implementation) a char is signed:
char c = 0xFF;
printf("%i\n", c);
/* produces -1 */

So that could be explaining why you kept getting some of those problems because Bytes are signed.

EDIT:

I just tried a small Byte test and got some strange results:
Local b1:Byte = $FF
Local b2:Byte = ~b1
Print b1      ' produces 255'
Print ~b1    ' produces -256'
Print b2      ' produces 0'
Print ~b2    ' produces -1'

Printing b1 made me think that Bytes are unsigned as it printed 255 which is what would be expected in an unsigned byte. But when I printed ~b2 it came as -1 which would be expected in a signed byte! Printing b2 seemed right as it came out to 0, but the strangest one was b1 which came out to -256!

-256 cannot be expressed as either a signed or unsigned byte so I'm thinking that what happened was that b1 ( $FF ) was converted to an int ( $000000FF )
and then the bitwise not of that is $FFFFFF00 which is -256. That would explain the b1 which is 255 because if it is $FF then it is converted to an int which is $000000FF which is 255. ~b2 is right because b2 is converted to an int which is $00000000 and the not of that is $FFFFFFFF which is -1. b2 is 0 either way.

So in the end, all these problems arrise because everything seems to be converted to an int before any operators are applied in the Print function.And I still don't know whether Bytes are signed or unsigned.


Pineapple(Posted 2006) [#27]
If I had BlitzMax, I would prefer they kept away from ! operator, because since you can pump C code inside Max, you might automatically place the ! in the source thinking it was the bitwise not operator, then finding out it goes titties up because it should really be the ~ operator!

Que head scratching for a while! :)

Dabz


TomToad(Posted 2006) [#28]
Here's what I think is happening. ~ is used to XOR two numbers together. I bet that when you don't specify 2 parameters, BlitzMax will XOR one parameter with a constant, and I bet that constant is $FFFFFFFF.
So if you do
Local v1:Byte = $FF
Print ~v1

What happens is that v1 needs to be converted to an int because the constant is an int. Then v1 is XORed with the constant and the result is returned to Print. So $FF is converted to $000000FF, then XORed with $FFFFFFFF, giving you $FFFFFF00 which is -256.
Now when you cast the number to byte, then the top 24 bits are truncated leaving you with $00. So if you did
[code]
Local v1:Byte = $FF
Local v2:Byte = ~v1
Print v2
[code]
Then v1 is converted to $000000FF, XORed with $FFFFFFFF leaving you with $FFFFFF00, then converted to byte and assigned to v2, making v2 = $00.

It seems the solution is to treat ~ as only an XOR if you're using anything other than ints. So to do a NOT on a byte, just use $FF ~ v1. Now since both sides of the equation are bytes, it'll not do any conversions and give you the correct answer.


rdodson41(Posted 2006) [#29]
Ah that would explain why the bytes were mysteriously being converted to Ints and printing out strange and unexpected values. Though I think if you are XORing a byte, even if it is with an implicit constant like it seems to be here, BMX should at least XOR it with a Byte constant and not an Int constant, since v1 is a Byte and not an Int.


Dreamora(Posted 2006) [#30]
It should ... thats the problem ...
And as worse part it does not even mention that it does this not allowed conversion