• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

SOLVED Bit operation?

Neptune

Member
I'm unfamiliar with how this kind of code works, can someone explain these 3 lines in a simple if/else logical sense?
'val' is just an integer.
GML:
val & $FFFF;
vy = val >> 16;
vy << 16 | vx
 

drandula

Member
When you are doing bit-operations you should think values as bits.
Like 6 would be "110" (one one zero, not 'one hundred and ten').
Look GML manual: https://docs2.yoyogames.com/source/_build/1_overview/3_additional_information/bitwise_operators.html

I'll try explain your code in a while, I'll edit this reply.

1) val & $FFFF.
- (This would cause error alone, use something like: val = val & $FFFF)
- Operator here is Bit AND operator, &.
- $FFFF is Hexadecimal number, which would be 65535 in decimal, in bits 111111111111.
- The code compares two value's bits together and returns third value. Third value has 1's only where both values had also 1.
- For visualization, line values up for checking.
Code:
// Lets say val is:
val = 12345678;
// val as bits is: 101111000110000101001110

// $FFFF is hex-number, as decimal number it is 65535.
// $FFFF is in bits 1111111111111111    (16 ones)

// When using & operator we compare these two.
//
//    101111000110000101001110    val
//            1111111111111111    $FFFF
//                                result

// Where val AND(&) $FFFF have 1, result will have 1.
//
//    101111000110000101001110    val
//            1111111111111111    $FFFF
//             11    1 1  111     Result

// Rest are 0's
//
//    101111000110000101001110    val
//            1111111111111111    $FFFF
//            0110000101001110    Result

// 
// Result number is therefore: 110000101001110
// Same in decimal is "24910"

// 
// Sidenote, because $FFFF is in bits all 1's, here it is used to clamp value. With $FFFF maximium result can be 65535.
2. vy = val >> 16
- Bitwise shift operator >>. Moves bits in given direction with given amount, and returns this new value.
Code:
// Lets say again that val is:
val = 12345678;
// and as bits is: 101111000110000101001110
/*

I will visually show when we do 'val >> 1'

                             |
a) Original val:             |
     101111000110000101001110|
                             |
b) Do shift >> 1:            |
      10111100011000010100111|0        <- Notice how bits move.
                             |
    
Here from your example:
a) val:                      |
     101111000110000101001110|     
                             |
b) val >> 16:                |
                     10111100|0110000101001110
                             |
c) result:                   |
                     10111100|   <- Notice how rest is cut away.
                             |
                            
So result is 10111100 in bits, which is in decimal 188
Shifting to right reduces number.
3. vy << 16 | vx
- This has operators Left Bit-shift "<<" and OR "|". These both are similiar to previous two.
- Bit Operator | is OR, if either values has bit "1" in same position, resulting will have there too 1.
- Left Bit-shift << moves bits left, this enlarges number.


Code:
Left Bit-Shift Operator
Let's use previous result 188 (bits: 10111100) for val

a) val:                      |
                     10111100|     
                             |
b) val << 16:                |
     10111100________________|   <- Is moved left 16 times 
                             |
c) result:                   |
     101111000000000000000000|   <- Empty spots are filled with 0's.
                             |
                            
So result is 101111000000000000000000 in bits, which is in decimal 12320768
Shifting to left enlarges number.

Code:
// Bit OR Operator
// Let's use original val 12345678(in bits 101111000110000101001110) for example.
// Let's say vx is 36638 (in bits 1000111100011110)
//
// When using | bit-operator, we check if val OR vx has 1.
//
//    101111000110000101001110    val
//            1000111100011110    vx
//                                result

// Where val OR(|) vx has 1, result will be 1.
//
//    101111000110000101001110    val
//            1000111100011110    vx
//    1 1111  111 1111 1 1111     Result
//
// Rest are 0's
//    101111000110000101001110    val
//            1000111100011110    vx
//    101111001110111101011110    Result

//
// Result number is therefore: 101111001110111101011110    
// Same in decimal is "12382046"
//
 
Last edited:

Neptune

Member
@drandula Thankyou very much for the in-depth response.

This val & $FFFF could be?
GML:
if val > 65535 {val = 65353;}
This vy = val >> 16 could be... Is there a if/else conditional way to do something like this? Or is this essentially what the shift >> << is for, subtracting/adding based on current value?
 

chamaeleon

Member
@drandula Thankyou very much for the in-depth response.

This val & $FFFF could be?
GML:
if val > 65535 {val = 65353;}
This vy = val >> 16 could be... Is there a if/else conditional way to do something like this? Or is this essentially what the shift >> << is for, subtracting/adding based on current value?
Doing a bit-shift is like multiply or dividing by a power of two. n<<1 is the same as n*2, n<<2 is the same as n*4, n>>1, is the same as n/2, and so on. Generally, n<<m is the same as n*(2^m) and n>>m is the same as n/(2^m).
 

Neptune

Member
@drandula These would be same statements?
GML:
cx = 65353*(rnd > 65353) | rnd;
And
GML:
cx = rnd & $FFFF; //$FFFF is hexdecimal for 65353?
 
Last edited:

chamaeleon

Member
They are not the same. The first line does not make much sense though. $FFFF is 65535, btw.

For the expressions you will need to keep in mind that the bitwise-or operator in the first statement will make the result have a bit set of it is set in one of the two operands, while bitwise-and requires it to be set on both sides.

If rnd can be any number, the bitwise-or in the first example can result in high bits being set while the second line prevents any bits outside the range of $FFFF being set because those bits are zero in the $FFFF value.
 
Top