Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

int64 #2

Open
sugendran opened this issue Jun 22, 2012 · 1 comment
Open

int64 #2

sugendran opened this issue Jun 22, 2012 · 1 comment

Comments

@sugendran
Copy link

Hi,

Your code uses methods "writeUInt64BE" and "writeInt64BE" (with matching read methods) for the buffer object, but this is not part of the nodejs standard buffer object. I think your tests don't actually hit those lines of code because all int64 objects get treated as if they are doubles.

var a = Date.now();
console.log("using a bit operator");
console.log("%j is a double: %j", a, (a << 0) !== a);
console.log("using Math.floor");
console.log("%j is a double: %j", a, Math.floor(a) !== a);

I'm not sure of the correct work around for this since javascript doesn't really support uint64 out of the box...


Want to back this issue? Place a bounty on it! We accept bounties via Bountysource.

@parnesen
Copy link

parnesen commented May 8, 2015

under the 'encode' method, you see the following code. This doesn't work for ints over 32bits, probably because bit shift operators are meant for 32bit values (or so I've heard. I'm no expert).

// Floating Point
if ((value << 0) !== value) {
buffer[offset] = 0xcb;
bops.writeDoubleBE(buffer, value, offset + 1);
return 9;
}

Anyway, if you comment that out, and add a Math.floor for safety, you can then use the following code to encode ints up to +- 2^53-1 as 64bit uints and 64bit ints. I have forked version at https://github.com/parnesen/msgpack-js that implements this, though it sacrifices support for floats, since I don't need them and I haven't sorted out a proper floating point test.

var bytePositions = [
0x1000000000000,
0x10000000000,
0x100000000,
0x1000000,
0x10000,
0x100,
0x1
]

/** reads an unsigned int of max value 2^53-1 from a uint64 binary representation **/
function readUint53(bytes, offset) {
var value = 0;
for(var ii = 1; ii < 8; ii++) { //we can skip the most significant byte
value = (value * 0x100) + bytes[offset + ii];
}
if (value > 9007199254740991) throw "Overflow";
return value;
}

/** reads an signed int of max/min value +- 2^53-1 from a big endian two's complement int64 binary representation **/
function readInt53(bytes, offset) {
var num;
if(isNegative(bytes, offset)) {
var copy = copyBytes(8, bytes, offset);
negate(copy, 0);
var absValue = readUint53(copy, 0);
num = -absValue;
}
else {
//we can treat bytes this as a UINT because in two's complement notation, positive numbers much
//smaller than MaxUint64 are represented as just themselves.
num = readUint53(bytes, offset);
}
return num;
}

function writeUint53(value, buffer, offset) {
value = Math.floor(value);
if (value > 9007199254740991) throw "Overflow";

buffer[offset] = 0x0; //most significant bit is always zero
var accumulator = 0;
for(var ii = 1; ii < 8; ii++) {
buffer[offset + ii] = Math.floor((value / bytePositions[ii - 1]) - accumulator);
accumulator = (accumulator + buffer[offset + ii]) * 0x100;
}
}

function writeInt53(value, buffer, offset) {
if(value >= 0) {
//we can treat this as a UINT because in two's complement notation, positive numbers much
//smaller than MaxUint64 are represented as just themselves.
writeUint53(value, buffer, offset);
}
else {
writeUint53(-value, buffer, offset);
negate(buffer, offset);
}
}

function copyBytes(count, buffer, offset) {
var bytes = new Array(count);
for(var ii = 0; ii < 8; ii++) {
bytes[ii] = buffer[offset + ii];
}
return bytes;
}

/** determines whether the given big endian, two's complement byte representation of a 64 bit integer is negative **/
function isNegative(bytes, offset) {
//check the most significant bit.
return (bytes[offset] & 0x80) !== 0;
}

/** negates the given big endian byte representation of a 64 bit integer by taking the two's complement **/
function negate(bytes, offset) {
var overflow = 1;
for(var ii = 7; ii >= 0; ii--) {
var byte = bytes[offset + ii];
var onesCompliment = ~byte & 0xFF;
var twosComplement = onesCompliment + overflow;
overflow = (twosComplement & 0x100) == 0 ? 0 : 1;
var negated = twosComplement & 0xFF;
bytes[offset + ii] = negated;
}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants