bit32Luau

The bit32 library does bitwise logic, shifts, rotations, bit fields and bit counting on 32-bit unsigned integers. Luwu has no bitwise operators. Packing flags into one number, reading fields of binary formats and hashing all go through this library.

Every argument is converted to a 32-bit unsigned integer first. Fractions are truncated and values outside 0 to 2^32 - 1 wrap around. Results are always in that range: bit32.band(-1) returns 4294967295.

Summary

Logic

bit32.bandLuau
Returns the bitwise and of its arguments
bit32.borLuau
Returns the bitwise or of its arguments
bit32.bxorLuau
Returns the bitwise exclusive or of its arguments
bit32.bnotLuau
Flips every bit of a number
bit32.btestLuau
Checks whether the bitwise and of its arguments isn't 0

Shifts and rotations

bit32.lshiftLuau
Shifts bits left and fills the low bits with 0
bit32.rshiftLuau
Shifts bits right and fills the high bits with 0
bit32.arshiftLuau
Shifts bits right and fills the high bits with the sign bit
bit32.lrotateLuau
Rotates bits left
bit32.rrotateLuau
Rotates bits right

Fields

bit32.extractLuau
Reads a field of bits from a number
bit32.replaceLuau
Replaces a field of bits in a number

Counting and byte order

bit32.countlzLuau
Counts the zero bits starting from the most significant bit
bit32.countrzLuau
Counts the zero bits starting from the least significant bit
bit32.byteswapLuau
Reverses the order of a number's four bytes

Logic

bit32.bandLuau

function bit32.band(...: number): number

Returns the bitwise and of its arguments: a bit is set in the result when it's set in every argument. With no arguments it returns a number with all 32 bits set.

Input
print(string.format("%04x", bit32.band(0xABCD, 0x0FF0)))
Output
0bc0

bit32.borLuau

function bit32.bor(...: number): number

Returns the bitwise or of its arguments: a bit is set in the result when it's set in any argument. With no arguments it returns 0.

Input
const READ = 0x1
const WRITE = 0x2
const EXECUTE = 0x4
print(bit32.bor(READ, WRITE, EXECUTE))
Output
7

bit32.bxorLuau

function bit32.bxor(...: number): number

Returns the bitwise exclusive or of its arguments: a bit is set in the result when it's set in an odd number of arguments. With no arguments it returns 0.

Input
print(string.format("%04x", bit32.bxor(0xFF00, 0x0FF0)))
Output
f0f0

bit32.bnotLuau

function bit32.bnot(x: number): number

Returns x with every one of its 32 bits flipped.

Input
print(string.format("%08x", bit32.bnot(0x0000FFFF)))
Output
ffff0000

bit32.btestLuau

function bit32.btest(first: number, ...: number): boolean

Returns true when the bitwise and of its arguments isn't 0. It tests whether a flag is set:

Input
const WRITE = 0x2
const permissions = 0x5
print(bit32.btest(permissions, WRITE))
Output
false

Shifts and rotations

bit32.lshiftLuau

function bit32.lshift(x: number, disp: number): number

Shifts x left by disp bits. The vacated low bits are 0 and bits shifted past bit 31 are lost. A negative disp shifts right instead and a disp of 32 or more returns 0.

Input
print(bit32.lshift(1, 4))
print(bit32.lshift(1, 32))
Output
16
0

bit32.rshiftLuau

function bit32.rshift(x: number, disp: number): number

Shifts x right by disp bits and fills the vacated high bits with 0. A negative disp shifts left instead and a disp of 32 or more returns 0. Use bit32.arshift to keep the sign bit.

bit32.arshiftLuau

function bit32.arshift(x: number, disp: number): number

Shifts x right by disp bits and fills the vacated high bits with copies of the most significant bit. That keeps the sign of x when it's read as a signed 32-bit integer. A negative disp shifts left instead.

Input
print(string.format("%08x", bit32.arshift(0x80000000, 4)))
print(string.format("%08x", bit32.rshift(0x80000000, 4)))
Output
f8000000
08000000

bit32.lrotateLuau

function bit32.lrotate(x: number, disp: number): number

Rotates x left by disp bits. Bits that leave the high end come back in at the low end. A negative disp rotates right and any disp works modulo 32.

Input
print(string.format("%08x", bit32.lrotate(0x80000001, 4)))
Output
00000018

bit32.rrotateLuau

function bit32.rrotate(x: number, disp: number): number

Rotates x right by disp bits. Bits that leave the low end come back in at the high end. A negative disp rotates left and any disp works modulo 32.

Fields

bit32.extractLuau

function bit32.extract(n: number, field: number, width: number?): number

Returns the width bits of n starting at bit field as an unsigned number. Bit 0 is the least significant bit and width defaults to 1.

Input
-- the green channel of a 0xRRGGBB color
print(string.format("%02x", bit32.extract(0x12AB34, 8, 8)))
Output
ab

A negative field, a width of 0 or less, or a range that goes past bit 31 is an error.

bit32.replaceLuau

function bit32.replace(n: number, v: number, field: number, width: number?): number

Returns n with the width bits starting at bit field replaced by the low bits of v. width defaults to 1. The same arguments as bit32.extract are errors.

Input
-- set the green channel of a 0xRRGGBB color
print(string.format("%06x", bit32.replace(0x12AB34, 0xFF, 8, 8)))
Output
12ff34

Counting and byte order

bit32.countlzLuau

function bit32.countlz(n: number): number

Returns how many consecutive zero bits n has starting from the most significant bit. Returns 32 when n is 0.

Input
print(bit32.countlz(1))
print(bit32.countlz(0x00FF0000))
Output
31
8

bit32.countrzLuau

function bit32.countrz(n: number): number

Returns how many consecutive zero bits n has starting from the least significant bit. Returns 32 when n is 0.

Input
print(bit32.countrz(8))
print(bit32.countrz(0))
Output
3
32

bit32.byteswapLuau

function bit32.byteswap(n: number): number

Returns n with the order of its four bytes reversed. It converts a 32-bit value between little-endian and big-endian byte order.

Input
print(string.format("%08x", bit32.byteswap(0x12345678)))
Output
78563412