UInt64

Draft
This page is not complete.

As JavaScript doesn't currently include standard support for 64-bit integer values, js-ctypes offers the Int64 and UInt64 objects to let you work with C functions and data that need (or may need) to use data represented using a 64-bit data type.

You use the UInt64 object to create and manipulate 64-bit unsigned integers.

Note: It's important to note that the 64-bit integer objects created by UInt64 are not UInt64 objects; rather, they're opaque objects whose values you manipulate through the other methods on the UInt64 object. See 64-bit integers for details.

Syntax

Creates and returns a new 64-bit unsigned integer.

UInt64 UInt64(
  value
);
Parameters
value
The value to assign the new 64-bit unsigned integer object. This may be specified as an integer (if the value can be represented as a 32-bit value), another 64-bit integer object (either signed or unsigned), or as a string, which may consist of an optional minus sign, followed by either a decimal number or "0x" or "0X" followed by a hexadecimal number. The string is then converted into the corresponding 64-bit integer value. You can therefore use a string to represent a 64-bit value that is too large to represent as a 32-bit JavaScript Number.
Return value

A new object representing the specified value.

Exceptions thrown
TypeError
The specified value cannot be converted into a 64-bit integer. Either it's not a Number, String, or 64-bit integer object, or it's a string that is incorrectly formatted or contains a value outside the range that can be represented in 64 bits. This will also be thrown if the source value is a floating-point number that can't be precisely represented as a 64-bit integer.

Method overview

Number compare(a, b);
Number hi(a);
UInt64 join(high, low);
Number lo(a);
String toSource();
String toString([radix]);

Methods

compare()

Compares two 64-bit integer values.

Number compare(
  a,
  b
);
Parameters
a
The first value to compare.
b
The second value to compare.
Return value

The returned value is -1 if a < b, 0 if a == b, and 1 if a > b.

Exceptions thrown
TypeError
One or both of the specified values is not a 64-bit integer (either signed or unsigned).


hi()

Returns the high 32 bits of the specified value.

Number hi(
  num
);
Parameters
num
The value whose high 32 bits are to be returned.
Return value

The high 32 bits of num are returned. This is essentially num >> 32.

Exceptions thrown
TypeError
num is not a 64-bit integer object.


lo()

Returns the low 32 bits of the specified value.

Number lo(
  num
);
Parameters
num
The Int64 value whose low 32 bits are to be returned.
Return value

The low 32 bits of num are returned. This is essentially num & 0xFFFFFFFF.

Exceptions thrown
TypeError
num is not a 64-bit integer object.


join()

Creates a 64-bit integer object with a value constructed using the specified high and low order 32-bit values.

UInt64 join(
  high,
  low
);
Parameters
high
The high-order 32 bits of the value to create.
low
The low-order 32 bits of the value to create.
Return value

A new 64-bit integer object comprised of the two values merged together. The returned value is (high << 32) + low.

Exceptions thrown
TypeError
One or both of the specified numbers is not a JavaScript number with an integral value.


toSource()

This method is for internal debugging use only.

Warning: Do not rely on the value returned by this method, as it's subject to change at any time, depending on the debugging needs of the developers.


toString()

Returns a string representation of the object's numeric value.

String toString(
  [radix]
);
Parameters
radix Optional
The radix (base) to use when constructing the string. If you don't specify a radix, base 10 is used.
Return value

A string representation of the value in the specified radix. This string consists of a leading minus sign, if the value was negative, followed by one or more lower-case digits in the specified radix.

Arithmetic Operations

    const UInt64 = ctypes.UInt64;
    const Int64 = ctypes.Int64;

    function ensureUInt64(aArr) {
        // makes elements in aArr a UInt64 if it can be made, else throws
        for (var i=0; i<aArr.length; i++) {
            var cCon = aArr[i].constructor.name;
            if (cCon != 'UInt64') {
                if (['String', 'Number'].indexOf(cCon) > -1) {
                    aArr[i] = UInt64(aArr[i]);
                } else {
                    throw new Error('Invalid type at position ' + i + ' it must be a numeric string, a number, or a UInt64. Type is "' + cCon + '"');
                }
            }
        }
    }

    function UInt64_add(...uint64) {
        ensureUInt64(uint64);

        var hi = UInt64.hi(uint64[0]);
        var lo = UInt64.lo(uint64[0]);;

        for (var i=1; i<uint64.length; i++) {
            hi += UInt64.hi(uint64[i]);
            lo += UInt64.lo(uint64[i]);

            if (lo > 0x100000000) {
                hi += 1;
            }
            hi = hi >>> 0;
            lo = lo >>> 0;
        }

        return UInt64.join(hi, lo);
    }

    function UInt64_sub(a, b) {
        var valArr = [a, b];
        ensureUInt64(valArr);
        a = valArr[0];
        b = valArr[1];

        var hi = UInt64.hi(a) - UInt64.hi(b);
        var lo = UInt64.lo(a) - UInt64.lo(b);
        if (lo < 0) {
            hi -= 1;
        }

        return UInt64.join(hi >>> 0, lo >>> 0);
    }

    function UInt64_mul(a, b) {
        var valArr = [a, b];
        ensureUInt64(valArr);
        a = valArr[0];
        b = valArr[1];

        var ah = UInt64.hi(a);
        var al = UInt64.lo(a);

        var bh = UInt64.hi(b);
        var bl = UInt64.lo(b);

        var a5 = ah >>> 20;
        var a4 = (ah >>> 7) & 0x1fff;
        var a3 = ((ah << 6) | (al >>> 26)) & 0x1fff;
        var a2 = (al >>> 13) & 0x1fff;
        var a1 = al & 0x1fff;

        var b5 = bh >>> 20;
        var b4 = (bh >>> 7) & 0x1fff;
        var b3 = ((bh << 6) | (bl >>> 26)) & 0x1fff;
        var b2 = (bl >>> 13) & 0x1fff;
        var b1 = bl & 0x1fff;

        var c1 = a1 * b1;
        var c2 = a1 * b2 + a2 * b1;
        var c3 = a1 * b3 + a2 * b2 + a3 * b1;
        var c4 = a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1;
        var c5 = a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1;

        c2 += c1 >>> 13;
        c1 &= 0x1fff;
        c3 += c2 >>> 13;
        c2 &= 0x1fff;
        c4 += c3 >>> 13;
        c3 &= 0x1fff;
        c5 += c4 >>> 13;
        c4 &= 0x1fff;

        var ch = ((c5 << 20) | (c4 << 7) | (c3 >>> 6)) >>> 0;
        var cl = ((c3 << 26) | (c2 << 13) | c1) >>> 0;

        return UInt64.join(ch, cl);
    }

    function UInt64_or(...uint64) {
        // bitwise OR
        // if there are logical OR and bitwise OR, bitwise OR may be named `bor` or `bitor`, but I don't think there could be logical OR, so I think just `or` is the right name

        ensureUInt64(uint64);

        var hi = 0;
        var lo = 0;

        for (var i=0; i<uint64.length; i++) {
            hi |= UInt64.hi(uint64[i]);
            lo |= UInt64.lo(uint64[i]);
        }

        return UInt64.join(hi >>> 0, lo >>> 0);
    }

    function UInt64_and(...uint64) {
        // bitwise AND could be applied to more than 2 operands, not sure if it's useful tho

        ensureUInt64(uint64);

        var hi = UInt64.hi(uint64[0]);
        var lo = UInt64.lo(uint64[0]);

        for (var i=1; i<uint64.length; i++) {
            hi &= UInt64.hi(uint64[i]);
            lo &= UInt64.lo(uint64[i]);
        }

        return UInt64.join(hi >>> 0, lo >>> 0);
    }

See Also