JavaScript Bitwise operations - javascript

I would like to store all currently-pressed keycodes in a single variable by using bitwise operations when the key is pressed and when the key is released.
I'm not sure how to properly use bitwise operations, but I know this will be very simple to someone who does.
Once complete, it should be simple to see which key is currently depressed by asking "is this key's code in the variable?"
Thanks in advance!

This is technically impossible to do in a single variable, no datatype in javascript can store the 256 bits required to hold the bitmask (which supports bitwise operations), you will need to use an array instead.
Also, unless you have text to speech software which you've macroed to magically execute js functions for you, asking your computer: "is this key's code in the variable?" won't do squat.
The way you would do it would be to initialize an array with 256 indexes, and then when a key is pressed, you find the relevant index and set it to true and when a key is released, you set it to false
It's the only way to do it. There actually isn't any other.

I don't think that it is possible the way you want to do it. Have a look at the available keycodes. There you see, that e.g. backspace is 8 and tab is 9.
In binary, that would be 1000 and 1001. Using binary operators, you would use OR | to "combine" the values, which would result in 1001.
You would check if a value is set via AND &, e.g. 1001 & 1000 to see, if the backspace key was pressed. Unfortunately, this would also evaluate to true if only the tab key was pressed (as its value is 1001).
That said, you can only use such bitwise comparison techniques, if the different values you want to test are powers of 2 only, i.e. 1, 2, 4, 8, 16, 32 and so on, as this represents in binary 1, 10, 100, 1000,...
For example if we can have a status variable and possible statuses would be OPEN = 2, LIGHT ON = 4 and ALARM ON = 8.
Assume that it is OPEN and LIGHT ON, i.e.
0010
| 0100
-------
0110
Here we can easily check whether the ALARM is on, be using AND: 0110 & 1000 = 0. But if we would encode ALARM ON with 6 = 0110, we could not check this.
What you could do is, to map the key codes to a some power of 2 value and apply binary operations there. The Wikipedia article about bitmasks might be worth reading.
I hope my explanation was somehow clear.

javascript bit operations are generally reliable for the first 31 bits, and things go downhill from there. So, you can 31 different keys which you have given a value to act as a flag. for instance, if you wanted to track the four arrows and A and B, you would do something like this.
var KEYS = {
LEFT: 1 << 0,
UP: 1 << 1,
RIGHT: 1 << 2,
DOWN: 1 << 3,
A: 1 << 4,
B: 1 << 5
}
var flags = 0;
myElement.addEventListener ('keydown', function (e) {
switch (e.keyCode) {
case 37: // left
flags = flags | KEYS.LEFT;
break;
case 38: // up
flags = flags | KEYS.UP;
break;
... etc ...
}
}
} , false);
function checkKeys () {
if ( (flags & KEYS.LEFT) === KEYS.LEFT)
alert('LEFT key pressed');
}
if ( (flags & KEYS.UP) === KEYS.UP )
alert('UP key pressed');
}
... etc ...
}

I'm not sure if there is such a thing as a ByteArray in JavaScript but if so, you could do it much like how this fellow did his logic in ActionScript3. While I am a big fan of bitflags & bitwise operations, I don't get the bitshifting he's doing and much of his code is way over my head. I just know it works on as3 projects I've worked on.
Also if you'd like to learn more about bitflags & bitwise operations (aside from the bitshifting) check out this article - http://jwopitz.wordpress.com/2012/02/13/using-bitflags-and-bitwise-math/
Source - https://github.com/richardlord/Asteroids/blob/master/src/no-dependencies/net/richardlord/input/KeyPoll.as
//init the bytearray
_states = new ByteArray();
_states.writeUnsignedInt( 0 );
_states.writeUnsignedInt( 0 );
_states.writeUnsignedInt( 0 );
_states.writeUnsignedInt( 0 );
_states.writeUnsignedInt( 0 );
_states.writeUnsignedInt( 0 );
_states.writeUnsignedInt( 0 );
_states.writeUnsignedInt( 0 );
//on a keydown listener (note the bitwise OR for adding
_states[ event.keyCode >>> 3 ] |= 1 << ( event.keyCode & 7 );
//on a keyup listener (note the bitwise AND plus bitwise NOT
states[ ev.keyCode >>> 3 ] &= ~(1 << (ev.keyCode & 7));
//check for keydown
return ( states[ keyCode >>> 3 ] & (1 << (keyCode & 7)) ) != 0;
//check for keyup
return ( states[ keyCode >>> 3 ] & (1 << (keyCode & 7)) ) == 0;

Related

How to implement unsigned right shift for BigInt in JavaScript?

I tried this sort of implementation, but it doesn't appear to be working.
function urs32(n, amount) {
const mask = (1 << (32 - amount)) - 1
return (n >> amount) & mask
}
function flip32(n) {
const mask = (1 << 32) - 1
return ~n & mask
}
log(~0b10101010 >>> 0, urs32(~0b10101010, 0))
log(~0b10101010 >>> 0, flip32(0b10101010))
function log(a, b) {
console.log(a.toString(2), b.toString(2))
}
I would expect for a to equal b in both cases, if done right. Basically I am trying to flip 32-bits (so 1's become 0s, 0's become 1s). I see that 1 << 32 === 0, so to get the value, I do 2 ** 32, but still doesn't work.
How do you implement the equivalent of ~n >>> 0 on a BigInt?
Basically what I am trying to do is create the countLeadingOnes functions (out of the countLeadingZeroes functions), like so:
const LEADING_ZERO_BIT_TABLE = makeLeadingZeroTable()
function makeLeadingZeroTable() {
let i = 0
const table = new Uint8Array(256).fill(0)
while (i < 256) {
let count = 8
let index = i
while (index > 0) {
index = (index / 2) | 0
count--
}
table[i] = count
i++
}
return table
}
function countLeadingZeroes32JS(n)
{
let accum = LEADING_ZERO_BIT_TABLE[n >>> 24];
if (accum === 8) {
accum += LEADING_ZERO_BIT_TABLE[(n >>> 16)]
}
if (accum === 16) {
accum += LEADING_ZERO_BIT_TABLE[(n >>> 8)]
}
if (accum === 24) {
accum += LEADING_ZERO_BIT_TABLE[ n ]
}
return accum;
}
function countLeadingZeroes16JS(n)
{
let accum = LEADING_ZERO_BIT_TABLE[n >>> 8]
if (accum === 8) {
accum += LEADING_ZERO_BIT_TABLE[n]
}
return accum;
}
function countLeadingZeroes8JS(n)
{
return LEADING_ZERO_BIT_TABLE[n]
}
console.log('countLeadingZeroes32JS', countLeadingZeroes32JS(0b10100010001000100010001000100010))
console.log('countLeadingZeroes32JS', countLeadingZeroes32JS(0b00100010001000100010001000100010))
console.log('countLeadingZeroes32JS', countLeadingZeroes32JS(0b00000010001000100010001000100010))
console.log('countLeadingZeroes16JS', countLeadingZeroes16JS(0b1010001000100010))
console.log('countLeadingZeroes16JS', countLeadingZeroes16JS(0b0010001000100010))
console.log('countLeadingZeroes16JS', countLeadingZeroes16JS(0b0000001000100010))
console.log('countLeadingZeroes16JS', countLeadingZeroes16JS(0b0000000000100010))
console.log('countLeadingZeroes8JS', countLeadingZeroes8JS(0b10100010))
console.log('countLeadingZeroes8JS', countLeadingZeroes8JS(0b00100010))
console.log('countLeadingZeroes8JS', countLeadingZeroes8JS(0b00000010))
function countLeadingOnes32JS(n) {
return countLeadingZeroes32JS(~n >>> 0)
}
function countLeadingOnes16JS(n) {
return countLeadingZeroes16JS(~n >>> 0)
}
function countLeadingOnes8JS(n) {
return countLeadingZeroes8JS(~n >>> 0)
}
console.log('countLeadingOnes32JS', countLeadingZeroes32JS(0b00100010001000100010001000100010))
console.log('countLeadingOnes32JS', countLeadingZeroes32JS(0b11100010001000100010001000100010))
console.log('countLeadingOnes32JS', countLeadingZeroes32JS(0b11111100001000100010001000100010))
console.log('countLeadingOnes16JS', countLeadingOnes16JS(0b0100001000100010))
console.log('countLeadingOnes16JS', countLeadingOnes16JS(0b1111110000100010))
console.log('countLeadingOnes16JS', countLeadingOnes16JS(0b1111111111000010))
console.log('countLeadingOnes8JS', countLeadingOnes8JS(0b01000010))
console.log('countLeadingOnes8JS', countLeadingOnes8JS(0b11000010))
console.log('countLeadingOnes8JS', countLeadingOnes8JS(0b11111100))
But it appears that ~n >>> 0 doesn't work on 32-bit integers. How to get this working properly?
How to implement unsigned right shift for BigInt in JavaScript?
Unsigned right-shift is difficult to define meaningfully for arbitrary-size integers, so before you (or anyone) can implement it, you'll have to decide how you want it to behave.
That said, considering the rest of this question, I don't see why you would even need this.
I would expect for a to equal b in both cases
Why would it? Unsigned right-shift and bit flipping are different operations and produce different results.
I see that 1 << 32 === 0
Nope, 1 << 32 === 1. JavaScript (like x86 CPUs) performs an implicit &31 on the shift amount, so since 32 & 31 === 0, ... << 32 is the same as ... << 0.
How do you implement the equivalent of ~n >>> 0 on a BigInt?
The equivalent of ~n is ~n. (That's not a typo. It's literally the same thing.)
The equivalent of ... >>> 0 is BigInt.asUintN(32, ...). (Note that neither the Number version nor the BigInt version shifts anything, so this doesn't answer your headline question "how to implement USR for BigInt".)
it appears that ~n >>> 0 doesn't work on 32-bit integers.
It sure does work. In fact, it only works on 32-bit integers.
The >>> 0 part is completely unnecessary though, you could just drop it.
The reason why this line:
console.log('countLeadingOnes32JS', countLeadingZeroes32JS(0b00100010001000100010001000100010))
isn't producing the number of leading ones is because the function it's calling is ...Zeroes...; an apparent copy-paste bug.
The reason why countLeadingOnes16JS isn't working correctly is because ~ in JavaScript always flips 32 bits. Since a 16-bit number's 32-bit representation has (at least) 16 leading zeros, those all become ones after flipping, and countLeadingZeroes16JS gets an input that's far bigger than it can handle: LEADING_ZERO_BIT_TABLE[n >>> 8] looks up an element that doesn't exist in the table, because the result of n >>> 8 is a 24-bit number in this case, not an 8-bit number. The solution is to use a mask after flipping; a valid implementation of clo16 might be:
function countLeadingOnes16(n) {
return countLeadingZeroes16(~n & 0xFFFF);
}
No BigInts and no >>> 0 required.
countLeadingOnes8 is similar.
You may want to read https://en.wikipedia.org/wiki/Two%27s_complement (or some other description of that concept) to understand what's going on with bitwise operations on negative numbers.
You may also want to learn how to debug your own code. There's a range of techniques: for example, you could have:
inserted console.log statements for intermediate results,
or stepped through execution in a debugger,
or simply evaluated small snippets in the console,
any of which would have made it very easy for you to see what's happening on the path from input number to end result.
For anyone else reading this: there's Math.clz32, which is highly efficient because it gets compiled to a machine instruction, so implementing countLeadingZeros by hand is unnecessary and wasteful. For smaller widths, just subtract: function clz8(n) { return Math.clz32(n) - 24; }

Attempting to do a flag check with bitwise operators for the first time

So I'm finally going to try and optimize my code where I'm doing a bunch of flag checks.. I'm trying to start off simple by simply using 8 bits to represent an octagon, I'll have an 8bit number that represents 'used sides' and an 8bit number to represent 'unused sides'
Very straight forward since an octagon conveniently has 8 everything :D
So What I have in javascript is
let sidesNotInUse = 0b11111111;
let sidesInUse = 0b00000000;
I want to be able to write the following functions
function inUse(sideIndex) {
// checks that the 1 flag at index is set in sidesInUse
}
function use(sideIndex) {
if(!(inUse(sideIndex))) {
// operator to set flag at index in sidesInUse to 1 and sidesNotInUse to 0
}
}
function unuse(sideIndex) {
if(inUse(sideIndex)) {
// operator to set flag at index in sidesInUse to 0 and sidesNotInUse to 1
}
}
Not sure if I'm looking at this wrongly but any help would be useful
Using a mask we can specify which bit we want to change.
let mask = 1 << 3;
means we want to change the bit at position 4 from the right 00000000.
Based on that we can refine your inUse() function to return the
bit at a specific position:
function inUse(sideIndex) {
let mask = 1 << sideIndex;
if ((sidesInUse & mask) != 0) {
return true;
} else {
return false;
}
}
Using the | (OR) operator we can set a bit to 1 while a combination of the ~ (NOT)
and the & (AND) operator gives us the power to finally set a bit to 0.
function use(sideIndex) {
let mask = 1 << sideIndex;
if (!(inUse(sideIndex))) {
sidesInUse |= mask;
sidesNotInUse &= ~mask;
}
}
function unuse(sideIndex) {
let mask = 1 << sideIndex;
if (inUse(sideIndex)) {
sidesInUse &= ~mask;
sidesNotInUse |= mask;
}
}
By the way - you don't really need two binary numbers, a single one is sufficient to know wether a side is in use or not.

The meaning of this `long` function (two's complement and bit-shifting)

I have encountered this function:
const LIMIT32 = 2147483648; // The limit at which a 32-bit number switches signs == 2 ^ 31
function long(v) {
// Two's complement
if (v >= LIMIT32) {
v = -(2 * LIMIT32 - v);
}
return [(v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
}
// e.g.
[-3, -2, -1, 0, 1,
-2147483649,-2147483648,-2147483647,
2147483647,2147483648,2147483649].forEach(x =>
console.log(`${x}: ${long(x)}`)
);
I'm wondering generally what this function is doing (why it's returning an array, and what the array elements are).
Then I'm wondering why it takes the v and does what looks like a sign flip and some multiplication.
Finally, the meaning of the bitshift and & operations for each item, why it's as multiples of 8, and why they chose 0xFF.
I'm wondering generally what this function is doing (why it's returning an array, and what the array elements are).
It returns an array of the 4 bytes that make up a int32 value. Why someone wrote the code to do that? I don't know.
Then I'm wondering why it takes the v and does what looks like a sign flip and some multiplication.
Because that's how int32 works: 0x7FFFFFFF + 1 === -0x80000000.
Although it is unnecessary in this code, the bit operations will take care of everything.
Finally, the meaning of the bitshift and & operations for each item, why it's as multiples of 8, and why they chose 0xFF.
Getting the distinct bytes of the int32, each one 8 bit long.

Decomposing a value into results of powers of two

Is it possible to get the integers that, being results of powers of two, forms a value?
Example:
129 resolves [1, 128]
77 resolves [1, 4, 8, 64]
I already thought about using Math.log and doing also a foreach with a bitwise comparator. Is any other more beautiful solution?
The easiest way is to use a single bit value, starting with 1 and shift that bit 'left' until its value is greater than the value to check, comparing each bit step bitwise with the value. The bits that are set can be stored in an array.
function GetBits(value) {
var b = 1;
var res = [];
while (b <= value) {
if (b & value) res.push(b);
b <<= 1;
}
return res;
}
console.log(GetBits(129));
console.log(GetBits(77));
console.log(GetBits(255));
Since shifting the bit can be seen as a power of 2, you can push the current bit value directly into the result array.
Example
You can adapt solutions from other languages to javascript. In this SO question you'll find some ways of solving the problem using Java (you can choose the one you find more elegant).
decomposing a value into powers of two
I adapted one of those answers to javascript and come up with this code:
var powers = [], power = 0, n = 129;// Gives [1,128] as output.
while (n != 0) {
if ((n & 1) != 0) {
powers.push(1 << power);
}
++power;
n >>>= 1;
}
console.log(powers);
Fiddle
Find the largest power of two contained in the number.
Subtract from the original number and Add it to list.
Decrement the exponent and check if new 2's power is less than the number.
If less then subtract it from the original number and add it to list.
Otherwise go to step 3.
Exit when your number comes to 0.
I am thinking of creating a list of all power of 2 numbers <= your number, then use an addition- subtraction algorithm to find out the group of correct numbers.
For example number 77:
the group of factors is { 1,2,4,8,16,32,64} [ 64 is the greatest power of 2 less than or equal 77]
An algorithm that continuously subtract the greatest number less than or equal to your number from the group you just created, until you get zero.
77-64 = 13 ==> [64]
13-8 = 7 ==> [8]
7-4 = 3 ==> [4]
3-2 = 1 ==> [2]
1-1 = 0 ==> [1]
Hope you understand my algorithm, pardo my bad english.
function getBits(val, factor) {
factor = factor || 1;
if(val) {
return (val % 2 ? [factor] : []).concat(getBits(val>>1, factor*2))
}
return [];
}
alert(getBits(77));

How do I swap endian-ness (byte order) of a variable in javascript

I am receiving and sending a decimal representation of two little endian numbers. I would like to:
shift one variable 8 bits left
OR them
shift a variable number of bits
create 2 8 bit numbers representing the first and second half of the 16 bit number.
javascript (according to https://developer.mozilla.org/en/JavaScript/Reference/Operators/Bitwise_Operators) uses big endian representation when shifting...
endianness is a bit foreign to me (I am only 90 percent sure that my outlined steps are what i want.) so swapping is a bit dizzying. please help! I only really need to know how to swap the order in an efficient manner. (I can only think of using a for loop on a toString() return value)
function swap16(val) {
return ((val & 0xFF) << 8)
| ((val >> 8) & 0xFF);
}
Explanation:
Let's say that val is, for example, 0xAABB.
Mask val to get the LSB by &ing with 0xFF: result is 0xBB.
Shift that result 8 bits to the left: result is 0xBB00.
Shift val 8 bits to the right: result is 0xAA (the LSB has "dropped off" the right-hand side).
Mask that result to get the LSB by &ing with 0xFF: result is 0xAA.
Combine the results from steps 3 and step 5 by |ing them together:
0xBB00 | 0xAA is 0xBBAA.
function swap32(val) {
return ((val & 0xFF) << 24)
| ((val & 0xFF00) << 8)
| ((val >> 8) & 0xFF00)
| ((val >> 24) & 0xFF);
}
Explanation:
Let's say that val is, for example, 0xAABBCCDD.
Mask val to get the LSB by &ing with 0xFF: result is 0xDD.
Shift that result 24 bits to the left: result is 0xDD000000.
Mask val to get the second byte by &ing with 0xFF00: result is 0xCC00.
Shift that result 8 bits to the left: result is 0xCC0000.
Shift val 8 bits to the right: result is 0xAABBCC (the LSB has "dropped off" the right-hand side).
Mask that result to get the second byte by &ing with 0xFF00: result is 0xBB00.
Shift val 24 bits to the right: result is 0xAA (everything except the MSB has "dropped off" the right-hand side).
Mask that result to get the LSB by &ing with 0xFF: result is 0xAA.
Combine the results from steps 3, 5, 7 and 9 by |ing them together:
0xDD000000 | 0xCC0000 | 0xBB00 | 0xAA is 0xDDCCBBAA.
Such function can be used to change endianness in js:
const changeEndianness = (string) => {
const result = [];
let len = string.length - 2;
while (len >= 0) {
result.push(string.substr(len, 2));
len -= 2;
}
return result.join('');
}
changeEndianness('AA00FF1234'); /// '3412FF00AA'
Use the << (bit shift) operator. Ex: 1 << 2 == 4.
I really think that the underlying implementation of JavaScript will use whatever endianess the platform it is running on is using. Since you cannot directly access memory in JavaScript you won't ever have to worry about how numbers are represented physically in memory. Bit shifting integer values always yield the same result no matter the endianess. You only see a difference when looking at individual bytes in memory using pointers.
Here is a oneliner for arrays to swap between big and little endian (and vise versa). The swapping is done using reverse on byte level. I guess for large arrays, it is more efficient than looping over scalar swap function.
function swapbyte(x) {
return new Float64Array(new Int8Array(x.buffer).reverse().buffer).reverse()
}
// Example
buf = new ArrayBuffer(16); // for 2 float64 numbers
enBig = new Float64Array(buf);
enBig[0] = 3.2073756306779606e-192;
enBig[1] = 2.7604354232023903e+199;
enLittle = swapbyte(enBig)
// two famous numbers are revealed
console.log(enLittle)
// Float64Array [ 6.283185307179586, 2.718281828459045 ]
// swapping again yields the original input
console.log(swapbyte(enLittle))
// Float64Array [ 3.2073756306779606e-192, 2.7604354232023903e+199 ]

Categories