Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Explanation of JavaScript bit operators in this function

I have this code block:

EventBus.on('pfio.inputs.changed', function(state, prev_state) {
    var changed = prev_state ^ state;
    for (var pin = 0; pin < 8; pin++) {
        if ((changed & (1 << pin)) === (1 << pin)) {
            EventBus.emit('pfio.input.changed', pin, ((state & (1 << pin)) === (1 << pin)));
        }
    }
});

state will be an 8 bit number: 00000000
prev_state will be an 8 bit number: 11001110

These numbers relate to switch states, so the first in state means pin 1 is off. In prev_state the first 1 means the switch 8 is on.

I understand the simple code execution, its these bits I can't get my head round:

(changed & (1 << pin)) === (1 << pin))

((state & (1 << pin)) === (1 << pin)));

prev_state ^ state;

Any explanation on this matter would help immensely!

like image 281
Callum Linington Avatar asked Feb 14 '14 15:02

Callum Linington


2 Answers

^ is the XOR operator - given two numbers it "lines up" their places and flips the place only if only one of the two numbers has that place:

// All of these are binary
111 ^ 111 === 000
110 ^ 111 === 001
110 ^ 110 === 000

This means that changed will be a number with only those places set that are set in prev_state or state but not both.

As for << that is the left-shift operator - it is effectively raising the left-hand side number by the power of two that is the right hand side number:

// Decimal numbers on the left, binary numbers on the right
1 << 1 === 10    // 2
1 << 2 === 100   // 4 
1 << 3 === 1000  // 8

// You can use any number on the LHS
2 << 1 === 100   // 4
3 << 2 === 1100  // 12
// Remember, 3 in decimal is equal to 11 in binary

Lastly, & is the binary and operator - it returns a number where the place is only set if both numbers have 1 in that place:

// Both sides binary
1 & 1 === 1
11 & 10 === 10
010 & 100 === 0

So, in your loop, the first 8 bits of changed are being checked to see if any of them are set - if any of them are set, something changed and an event is fired. It may be easier to see if we break it down for two steps:

// All numbers in binary save for 8 ;-)
prev_state = 11111111;
state = 11011111;
changed = 00100000;

Iteration #1:

mask = 1 << 0                   // 0
changeAtPower = changed & mask  // 0
// 0            0         0
mask === changedAtPower         // false

Iteration #2:

mask = 1 << 1                   // 10
changeAtPower = changed & mask  // 0
// 00           00        01
mask === changedAtPower         // false

Skipping iterations #3 through #5, which all look the same, let's look at #6:

mask = 1 << 5                    // 100000
changedAtPower = changed & mask  // 100000
// 100000        100000    100000
mask === changedAtPower         // true 
// Event triggered

And then it continues on for the remaining iterations (#7 and #8) and since nothing has changed, fires no more events.

like image 107
Sean Vieira Avatar answered Sep 28 '22 15:09

Sean Vieira


prev_state ^ state

makes a mask of bits that is 1 wherever a bit in the prev_state disagrees with the corresponding bit in state, see xor.

(changed & (1 << pin)) === (1 << pin))

tests whether the bit with index pin is set, which would mean that that pin at position has changed.

((state & (1 << pin)) === (1 << pin)))

also tests whether the bit with index pin is set, which in this case means that the pin at that position is now 1/set/true

like image 28
harold Avatar answered Sep 28 '22 14:09

harold