views:

320

answers:

4

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?

+1  A: 

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.

Murali
I guess I am asking for a down vote? :-)
Murali
+1: it's hacky solution to a really odd problem.
Simeon Pilgrim
Nah, it's a legit solution, even if it's not the kind of solution I'm hoping for. No downvotes for you.
Jeff
+1  A: 

The only way I think it can be done is to create an int64 class which internally contains two 32 bit integers and performs shifting by carrying between them.

wallyk
+2  A: 

Keep your 64-bit number as separate high and low halves. 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.

Doug Currie
I like this way of doing it, but will the fact that the numbers are signed cause any gotchas? The most significant bit stores the sign.
Jeff
Oh, you said less than 32. Looks like that takes care of the problem.
Jeff
Jason Orendorff
A: 

Here's a values based rotate.

double d = 12345678901.0;
// get high int bits in hi, and the low in
int hi = (int)(d / 16.0 / 16.0 / 16.0 / 16.0);
int low = (int)d;

int rot = 3; // thus * 8
int newhi = (low >> (32 - rot)) | (hi << rot);
int newlow = (hi >> (32 - rot)) | (low << rot);

double newdouble = ((double)hi * 16.0 * 16.0 * 16.0 * 16.0) + (double)low;
Simeon Pilgrim
Well that's a C# version, and because of the signed int's the last step does not actually work as expected. Infact it's most likely will also not work for negative doubles ether...
Simeon Pilgrim