Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I simulate a bitwise rotation of a 64-bit (unsigned) integer in JavaScript?

I need to perform a circular left shift of a 64-bit integer in JavaScript. However:

  • JavaScript numbers are doubles
  • JavaScript converts them to 32-bit signed ints when you start with the << and the >> and the >>> and the ~ and all of the bit-twiddling business. And then it's back to doubles when you're done. I think.
  • I don't want the sign. And I definitely don't want the decimal bits. But I definitely do want 64 bits.

So, how do I perform a bitwise left rotation of a 64-bit value?

like image 951
Jeff Avatar asked Nov 20 '09 02:11

Jeff


3 Answers

Keep your 64-bit number as separate high and low partitions. To rotate left N when N < 32:

hi_rot = ((hi << N) | (lo >>> (32-N))) & (0xFFFFFFFF)

lo_rot = ((lo << N) | (hi >>> (32-N))) & (0xFFFFFFFF)

If N >= 32, then subtract 32 from N, swap hi and lo, and then do the above.

like image 71
Doug Currie Avatar answered Oct 18 '22 03:10

Doug Currie


I believe so, though not the most efficient way, convert the number to a string in binary form (64-bits), use substring to move the char at the beginning and append it to the end (for left rotation) and convert the binary form back to number. I am sure you can figure out how to convert a decimal number to its binary form into a string and back.

like image 39
Murali Avatar answered Oct 18 '22 02:10

Murali


As @Doug Currie put it you need to represent the 64-bit number as two numbers, then do bit-wise operations on them. The code I've used is:

//Constructor for a Long..
function Long(high, low) {
    //note: doing "or 0", truncates to 32 bit signed
    //big-endian 2's complement int..
    this._high = high | 0;
    this._low = low | 0;
}
Long.prototype.rotateLeft = function(bits) {
    var newHigh;
     if(bits === 32){ //just switch high and low over in this case..
        newHigh = this._low;
        this._low = this._high;
        this._high = newHigh;
    } else {
        newHigh = (this._high << bits) | (this._low >>> (32-bits)); 
        this._low = (this._low << bits) | (this._high >>> (32-bits));
        this._high = newHigh;
    }
    return this; //for chaining..
};
//Rotates the bits of this word round to the right (max 32)..
Long.prototype.rotateRight = function(bits) {
    var newHigh;
    if(bits === 32){ //just switch high and low over in this case..
        newHigh = this._low;
        this._low = this._high;
        this._high = newHigh;
    } else {
        newHigh = (this._low << (32-bits)) | (this._high >>> bits); 
        this._low = (this._high << (32-bits)) | (this._low >>> bits);
        this._high = newHigh;
    }
    return this; //for chaining..
};

To use it try running: console.log(new Long(0,1).rotateLeft(4)); then inspecting the _high and _low properties.

like image 20
Mark Rhodes Avatar answered Oct 18 '22 03:10

Mark Rhodes