Hi,
I seem to be having another problem
I have declared an array:
Dim StorageArray.b(320,240,3)
And I add a value to it:
StorageArray(1,1,1) = 255
Now, when I try and divide or bitshift that value, and write it to a file, I still end up with 0xFF (255):
WriteByte(StorageArray(1,1,1)>>3)
and:
WriteByte(StorageArray(1,1,1)/8)
Can anyone see what I am doing wrong?
I am sure it is something really obvious, I just can't see it...
Many Thanks,
Toris
[EDIT]
This odd thing is, that the following line works... :
WriteByte(255>>8)
It writes the correct value of 0x1F (31)...
[/EDIT]
Bitshifting or Dividing on an array?
It's not that obvouts though, you need to know something more to
understand that.
Here we go...
The thing is, that PB does mathematical shifting, not real bitwise shifting.
This means, that it takes care of signed numbers.
255 stored in a Byte is -1, which can't be shifted further down. (One might
think, that it should be shifted to 0, but the ASM command used here is
doing it that way, so no way to change that.)
The same applies to you attempt to divide the number by 8. PB replaces
multiplications and divisions by shifting if possible (so dividing by 2 is >>1,
and dividing by 2 is >>2 and so on). This increases speed very much.
The bad thing is, that -1>>3 which is what is internally the division by 8,
will also not be shifted towards 0, because of the SAR Assembler. command.
> WriteByte(255>>8)
This works, because it is calculated in 32bit math, where 255 is 255, and
the result is converted to a Byte. So there is no sitgned/unsigned problem
here.
To solve your problem, either use Variables that can hold your values
without coming into conflict with the signed bit. (use WORD or LONG
insted of BYTE)
The other way would be to use InlineASM, for your shifting, to preform
real bitwise shifting. Unfortunately this doesn't work with Arrays.
Don't forget to enable InlineASM support in the compiler options menu.
I hope this answers all questions...
Timo
understand that.
Here we go...
The thing is, that PB does mathematical shifting, not real bitwise shifting.
This means, that it takes care of signed numbers.
255 stored in a Byte is -1, which can't be shifted further down. (One might
think, that it should be shifted to 0, but the ASM command used here is
doing it that way, so no way to change that.)
The same applies to you attempt to divide the number by 8. PB replaces
multiplications and divisions by shifting if possible (so dividing by 2 is >>1,
and dividing by 2 is >>2 and so on). This increases speed very much.
The bad thing is, that -1>>3 which is what is internally the division by 8,
will also not be shifted towards 0, because of the SAR Assembler. command.
> WriteByte(255>>8)
This works, because it is calculated in 32bit math, where 255 is 255, and
the result is converted to a Byte. So there is no sitgned/unsigned problem
here.
To solve your problem, either use Variables that can hold your values
without coming into conflict with the signed bit. (use WORD or LONG
insted of BYTE)
The other way would be to use InlineASM, for your shifting, to preform
real bitwise shifting. Unfortunately this doesn't work with Arrays.
Code: Select all
var.b = StorageArray(1,1,1)
SHR var, 3 ; this is real bitwise shifting >>
;SHL var, 3 ; this is <<
Debug var
I hope this answers all questions...
Timo
quidquid Latine dictum sit altum videtur
Thankyou for the *brilliant* reply!
Now, I have changed the array to a long, which now makes it work perfectly when I manually assign the number.
However, when I load the number into the array using ReadByte(), it obviously does something odd... as it retains the problem, so even if I read a byte into a long array, it still doesn't work.
Is there any way to cast or something, the byte into long format, so it's stored correctly in the long array?
Again, Many thanks,
Toris
Now, I have changed the array to a long, which now makes it work perfectly when I manually assign the number.
However, when I load the number into the array using ReadByte(), it obviously does something odd... as it retains the problem, so even if I read a byte into a long array, it still doesn't work.
Is there any way to cast or something, the byte into long format, so it's stored correctly in the long array?
Again, Many thanks,
Toris
- tinman
- PureBasic Expert
- Posts: 1102
- Joined: Sat Apr 26, 2003 4:56 pm
- Location: Level 5 of Robot Hell
- Contact:
PureBasic will still treat the byte as signed so when you store it in the long it will be converted from a byte to a long and keep its signed value.Toris wrote:However, when I load the number into the array using ReadByte(), it obviously does something odd... as it retains the problem, so even if I read a byte into a long array, it still doesn't work.
You need to do this:
StorageArray(x,y,z) = ReadByte() & $FF
Which will mask off the extra 1 bits added by the conversion from byte to long.
If you paint your butt blue and glue the hole shut you just themed your ass but lost the functionality.
(WinXPhSP3 PB5.20b14)
(WinXPhSP3 PB5.20b14)
Of course, when converting a byte to long, PB takes also care of
signed variables, and since 255 resulted by ReadBYte() is -1, it will
also be -1 in the long.
A simple bitmasking with & (bitwise and) does the trick:
Assuming that the Array is now long or word type.
just for compleetnes, from word to long, it is:
Timo
Arg, you beat me, David but I'll catch up next time
signed variables, and since 255 resulted by ReadBYte() is -1, it will
also be -1 in the long.
A simple bitmasking with & (bitwise and) does the trick:
Code: Select all
SortArray(1,1,1) = ReadByte() & $FF
just for compleetnes, from word to long, it is:
Code: Select all
SortArray(1,1,1) = ReadWord() & $FFFF
Arg, you beat me, David but I'll catch up next time

Last edited by freak on Mon May 05, 2003 10:23 pm, edited 1 time in total.
quidquid Latine dictum sit altum videtur