Available on:
Implementation of arithmetic and bitwise operations for unsigned 64-bit integers in pure Luau. Utilizes vector objects to pack the integers efficiently, meaning it avoids expensive table accesses and allocations.
Major features:
- Arithmetic (addition, subtraction, mutiplication, division, modulo, and exponentiation)
- Bitwise operations (everything implemented in
bit32as of this time except forreplace/extract) - Convenience functions for converting to and from other forms of data (hex strings, buffers, etc)
This does not implement math library functionality! Implementations of things like math.random are far beyond scope for this library, and implementation of things like math.sin are prohibitively complex and incredibly slow. It would also be very difficult to write tests for these that were appropriately exhaustive and it's irresponsible to release them into the world without tests.
This module is made as fast as is reasonably possible. However, they are still a fair bit slower than native integers; this will hopefully not be a surprise. You should expect very good performance, but it's possible that depending upon your use case storing two 32-bit integers and operating on them will be faster.
If you wish to contribute to this module, whether it be through optimizations or new functionality, please open a pull request.
| Logical | Arithmetic | Bitwise |
|---|---|---|
gt |
add |
band |
gt_equal |
sub |
bor |
lt |
mult |
bxor |
lt_equal |
div |
bnot |
pow |
lshift |
|
rshift |
||
arshift |
||
lrotate |
||
rrotate |
||
countlz |
||
countrz |
||
btest |
||
byteswap |
int64.from_f64(f64: number): vectorConstructs a 64-bit integer from the passed f64. Put more plainly, converts a normal Luau number to a 64-bit integer.
The number is truncated into an integer first. Note that Luau numbers cannot accurately represent integers past 2 ^ 53.
int64.from_dec_string(str: string): vectorReturns the provided value parsed as a 64-bit integer. Expects the provided string to contain only the digits 0-9 and will error if it does not.
Leading zeros are accepted and parsed appropriately.
Due to the implementation, the resulting integer will wrap around if it is too large to fit in a 64-bit integer rather than erroring.
int64.from_pair(most: number, least: number): vectorConstructs a 64-bit integer from the passed u32 values.
The provided most value fills the upper 32 bits of the integer, and the provided least value fills the lower 32-bits.
int64.from_u32(u32: number): vectorConstructs a 64-bit integer from the passed u32.
This number is truncated in a 32-bit integer, even if it is larger than the max value.
int64.from_buffer(buf: buffer, offset: number?): vectorReads a u64 from the provided buffer. If offset is provided, reads from that spot in the buffer. Otherwise, reads from the beginning.
This function reads a little-endian value from the buffer.
int64.from_byte_string(str: string, offset: number?): vectorReads a u64 from the provided string. If offset is provided, reads from that point in the string. Otherwise starts at the beginning.
This function reads a little-endian value from the string.
int64.to_f64(u64: vector): numberConverts the provided u64 to an f64 (or put plainly: a normal Luau number).
This function does not check for precision loss. f64 values lose precision past 2 ^ 53.
int64.to_dec_string(u64: vector): stringReturns the provided value as a string of decimal digits.
Equivalent to formatting normal numbers with %u or calling tostring on them.
int64.to_pair(u64: vector): (number, number)Converts the provided u64 into two 32-bit integers.
This returns the most significant portion of the number first.
int64.to_quartet(u64: vector): (number, number, number, number)Converts the provided u64 into four 16-bit integers.
This returns the most significant portion of the number first.
int64.to_buffer(u64: vector): bufferConverts the provided u64 to a buffer.
The integer is written as a little-endian value.
int64.write_to_buffer(b: buffer, u64: vector, offset: number)Writes the provided u64 to the provided buffer. The value is written to the buffer at the provided offset.
The integer is written as a little-endian value.
int64.to_byte_string(u64: vector): stringConverts the provided u64 to string of binary data.
The integer is written as if it were little-endian.
int64.to_hex_string(u64: vector): stringConverts the provided u64 to a string of 16 hexadecimal digits.
The returned string will always be 16 bytes and the number is formatted as if it were big-endian. It also always uses lowercase letters.
int64.to_bin_string(u64: vector): stringConverts the provided u64 to a string of 64 binary digits.
The returned string will always be 64 bytes and the number is formatted as if it were big-endian.
A constant representing the 64-bit representation of 0.
A constant representating the 64-bit representation of 1.
A constant representating the 64-bit representation of 2.
A constant representing the maximum possible 64-bit value (18446744073709551615, or 2 ^ 64 - 1).
A constant representing the maximum possible 32-bit value (4294967295, or 2 ^ 32 - 1).
A constant representing the maximum integer that is exactly representable by a normal Luau number (9007199254740992 or 2 ^ 53).
A constant representing the maximum integer that is exactly representable by a 32-bit floating point value (16777216, or 2 ^ 24).
int64.gt(lhs: vector, rhs: vector): booleanReturns whether lhs is greater than rhs.
int64.gt_equal(lhs: vector, rhs: vector): booleanReturns whether lhs is greater than or equal to rhs.
int64.lt(lhs: vector, rhs: vector): booleanReturns whether lhs is less than rhs.
int64.lt_equal(lhs: vector, rhs: vector): booleanReturns whether lhs is less than or equal to rhs.
int64.add(augend: vector, addend: vector): vectorCalculates the sum of the two provided values. Equivalent to + for normal integers.
If the sum is equal to or greater than 2 ^ 64, the returned value will overflow rather than expanding beyond 64 bits.
int64.sub(minuend: vector, subtrahend: vector): vectorCalculates the difference of the two provided values. Equivalent to - for normal integers.
If the difference is less than 0, the returned value will overflow rather than going negative.
int64.mult(multiplier: vector, multiplicand: vector): vectorCalculates the product of the two provided values. Equivalent to * for normal integers.
If the product is greater than or equal to 2 ^ 64, the returned value will overflow rather than expanding beyond 64 bits.
int64.div(dividend: vector, divisor: vector): (vector, vector)Calculates the quotient of the two provided values and returns it, along with the remainder.
Equivalent to // and % for normal integers.
This function will error if divisor is 0.
int64.pow(base: vector, power: number): vectorCalculates the result of base raised to power. Equivalent to ^ for normal integers. power is interpreted as a 32-bit integer.
If the result is greater than or equal to 2 ^ 64, the returned value will overflow rather than expanding beyond 64 bits.
Additionally, 0 ^ 0 is treated as being 1.
int64.band(lhs: vector, rhs: vector): vectorComputes the bitwise AND of the two provide values.
This does not accept a vararg like the bit32 equivalent for performance reasons.
int64.bor(lhs: vector, rhs: vector): vectorComputes the bitwise OR of the two provide values.
This does not accept a vararg like the bit32 equivalent for performance reasons.
int64.bxor(lhs: vector, rhs: vector): vectorComputes the bitwise XOR of the two provide values.
This does not accept a vararg like the bit32 equivalent for performance reasons.
int64.bnot(u64: vector): vectorComputes the bitwise negation of the provided value.
int64.lshift(u64: vector, n: number): vectorShifts the provided u64 logically left by n bits.
This function will error if n is negative.
int64.rshift(u64: vector, n: number): vectorShifts the provided u64 logically right by n bits.
This function will error if n is negative.
bit64.arshift(u64: vector, n: number): vectorShifts the provided u64 arithmetically right by n bits. Since these numbers are unsigned, this effectively just copies the most significant bit into the empty space rather than filling them with zeros.
This function will error if n is negative.
int64.lrotate(u64: vector, n: number): vectorRotates the bits of the provided u64 left by n bits.
If n is negative, this is equivalent to rrotate. Otherwise, if n is greater than 64-bits, it will wrap around.
int64.rrotate(u64: vector, n: number): vectorRotates the bits of the provided u64 right by n bits.
If n is negative, this is equivalent to lrotate. Otherwise, if n is greater than 64-bits, it will wrap around.
int64.countlz(u64: vector): numberReturns the number of consecutive zero bits in the provided u64 starting from the left-most (most significant) bit.
int64.countrz(u64: vector): numberReturns the number of consecutive zero bits in the provided u64 starting from the right-most (least significant) bit.
int64.btest(lhs: vector, rhs: vector): booleanReturns a boolean describing whether the bitwise AND of lhs and rhs are different than zero.
This does not accept a vararg like the bit32 equivalent for performance reasons.
int64.byteswap(u64: vector): vectorReturns the provided u64 with the order of bytes swapped.