Skip to content

Instantly share code, notes, and snippets.

@ChiChou
Created December 17, 2018 10:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ChiChou/71d2f6a8cf11dc72200088e1ef9450a8 to your computer and use it in GitHub Desktop.
Save ChiChou/71d2f6a8cf11dc72200088e1ef9450a8 to your computer and use it in GitHub Desktop.
import { Struct } from "./utils";
function operator(target, name, descriptor) {
const oldValue = descriptor.value;
descriptor.value = function() {
if (arguments.length != oldValue.length)
throw Error("Not enough arguments for function " + name);
for (let arg of arguments)
if (!(arg instanceof Int64))
arguments[i] = new Int64(arg);
return oldValue.apply(this, arguments);
};
return descriptor;
}
export default class Int64 {
constructor() {
this.bytes = new Uint8Array(8);
switch (typeof v) {
case 'number':
v = '0x' + Math.floor(v).toString(16);
case 'string':
if (v.startsWith('0x'))
v = v.substr(2);
if (v.length % 2 == 1)
v = '0' + v;
var bigEndian = unhexlify(v, 8);
bytes.set(Array.from(bigEndian).reverse());
break;
case 'object':
if (v instanceof Int64) {
bytes.set(v.bytes());
} else {
if (v.length != 8)
throw TypeError('Array must have excactly 8 elements.');
bytes.set(v);
}
break;
case 'undefined':
break;
default:
throw TypeError('Int64 constructor requires an argument.');
}
}
asDouble() {
// Check for NaN
if (bytes[7] == 0xff && (bytes[6] == 0xff || bytes[6] == 0xfe))
throw new RangeError("Integer can not be represented by a double");
return Struct.unpack(Struct.float64, bytes);
}
asJSValue() {
if ((bytes[7] == 0 && bytes[6] == 0) || (bytes[7] == 0xff && bytes[6] == 0xff))
throw new RangeError("Integer can not be represented by a JSValue");
// For NaN-boxing, JSC adds 2^48 to a double value's bit pattern.
this.assignSub(this, 0x1000000000000);
const res = Struct.unpack(Struct.float64, bytes);
this.assignAdd(this, 0x1000000000000);
return res;
}
bytes() {
return Array.from(bytes);
}
byteAt(i) {
return bytes[i];
}
toString() {
return '0x' + hexlify(Array.from(bytes).reverse());
}
@operator
assignNeg() {
for (let i = 0; i < 8; i++)
bytes[i] = ~this.byteAt(i);
return this.assignAdd(this, Int64.One);
}
neg() {
return new Int64(this).assignNeg();
}
@operator
assignAdd(b) {
let carry = 0;
for (let i = 0; i < 8; i++) {
const cur = this.byteAt(i) + b.byteAt(i) + carry;
carry = cur > 0xff | 0;
bytes[i] = cur;
}
return this;
}
add(op) {
return new Int64(this).assignAdd(op);
}
@operator
assignSub(b) {
let carry = 0;
for (let i = 0; i < 8; i++) {
const cur = this.byteAt(i) - b.byteAt(i) - carry;
carry = cur < 0 | 0;
bytes[i] = cur;
}
return this;
}
sub(op) {
return new Int64(this).assignSub(op);
}
static fromDouble(d) {
const bytes = Struct.pack(Struct.float64, d);
return new Int64(bytes);
}
}
Int64.Zero = new Int64(0);
Int64.One = new Int64(1);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment