Skip to content

Portable implementation of bitwise operations for 16-bit, 32-bit, and 64-bit integers with byte conversions. No C dependencies, supports Lua 5.1+ and LuaJIT.

License

Notifications You must be signed in to change notification settings

finitelabs/lua-bitn

Repository files navigation

lua-bitn

A portable bitwise operations library for 16-bit, 32-bit, and 64-bit integers with zero external dependencies. This library provides a complete, cross-platform implementation that runs on Lua 5.1, 5.2, 5.3, 5.4, and LuaJIT.

Features

  • Zero Dependencies: No C extensions or external libraries required
  • Automatic Optimization: Uses native bit operations when available (Lua 5.2+ bit32 library, Lua 5.3+ operators, LuaJIT bit library) with pure Lua fallback
  • Portable: Runs on any Lua interpreter (5.1+)
  • Complete: Full bitwise operations API for 16-bit, 32-bit, and 64-bit integers
  • Byte Conversions: Big-endian and little-endian byte string conversions
  • Well-tested: Comprehensive self-tests with embedded test vectors

Installation

Clone this repository:

git clone https://github.com/finitelabs/lua-bitn.git
cd lua-bitn

Add the src directory to your Lua path, or copy the files to your project.

Usage

Basic Example

local bitn = require("bitn")

-- Check version
print(bitn.version())

-- 32-bit operations
local bit32 = bitn.bit32
local result = bit32.band(0xFF00, 0x0FF0)      -- 0x0F00
local shifted = bit32.lshift(1, 8)             -- 256
local rotated = bit32.ror(0x12345678, 8)       -- 0x78123456

-- Byte conversions (big-endian)
local bytes = bit32.u32_to_be_bytes(0x12345678)
local num = bit32.be_bytes_to_u32(bytes)       -- 0x12345678

-- 16-bit operations
local bit16 = bitn.bit16
local masked = bit16.mask(0x12345)             -- 0x2345
local negated = bit16.bnot(0xFF00)             -- 0x00FF

-- 64-bit operations (using {high, low} pairs)
local bit64 = bitn.bit64
local a = bit64.new(0x00000001, 0xFFFFFFFF)    -- 0x1FFFFFFFF
local b = bit64.new(0x00000000, 0x00000001)    -- 0x1
local sum = bit64.add(a, b)                    -- {0x00000002, 0x00000000}
local xored = bit64.bxor(
  bit64.new(0x12345678, 0x9ABCDEF0),
  bit64.new(0x12345678, 0x9ABCDEF0)
)                                               -- {0, 0}

64-bit Value Representation

64-bit values are represented as {high, low} pairs where:

  • high is the upper 32 bits
  • low is the lower 32 bits

Example: 0x123456789ABCDEF0 is represented as {0x12345678, 0x9ABCDEF0}

Raw Operations (Performance-Critical Code)

The bit32 and bit64 modules provide raw_* variants for performance-critical code paths like cryptographic operations. These bypass the unsigned conversion wrapper used on LuaJIT, providing direct access to native bit library functions.

Available functions (bit32 and bit64):

  • raw_band, raw_bor, raw_bxor, raw_bnot
  • raw_lshift, raw_rshift, raw_arshift
  • raw_rol, raw_ror
  • raw_add

Important: On LuaJIT, raw_* functions may return signed 32-bit integers:

local bit32 = require("bitn").bit32

-- Regular function (always unsigned)
bit32.bxor(0x80000000, 1)      --> 2147483649

-- Raw function (signed on LuaJIT)
bit32.raw_bxor(0x80000000, 1)  --> -2147483647 (same bit pattern!)

When to use raw_ functions:*

  • Chained bitwise operations (XOR, AND, OR, rotate) where sign doesn't matter
  • Crypto algorithms (ChaCha20, etc.) that only care about bit patterns
  • Tight loops where the to_unsigned() overhead is measurable

When NOT to use raw_ functions:*

  • When comparing results (<, >, ==)
  • When doing arithmetic on the results
  • When formatting/displaying values
  • When you need guaranteed unsigned semantics

Development

Setup

# Install development dependencies (stylua, luacheck, amalg)
make install-deps

Testing

make test                # Run all tests
make test-bit32          # Run specific module tests
make test-matrix         # Run tests across all Lua versions
make test-matrix-bit32   # Run specific module across all Lua versions

# Or use scripts directly with custom Lua binary
LUA_BINARY=lua5.1 ./run_tests.sh

Benchmarking

make bench               # Run all benchmarks
make bench-bit32         # Run specific module benchmark
make bench-matrix        # Run benchmarks across all Lua versions
make bench-matrix-bit64  # Run specific module across all Lua versions

# Or use scripts directly with custom Lua binary
LUA_BINARY=lua5.4 ./run_benchmarks.sh

Code Quality

make check               # Run format check and lint
make format              # Format code with stylua
make format-check        # Check formatting without modifying
make lint                # Run luacheck

Building

make build               # Build single-file distribution (build/bitn.lua)
make clean               # Remove generated files

Help

make help                # Show all available targets

Current Limitations

  • Pure Lua fallback (Lua 5.1 without LuaJIT) is slower than native bit libraries
  • No constant-time guarantees

License

GNU Affero General Public License v3.0 - see LICENSE file for details

Contributing

Contributions are welcome! Please ensure all tests pass and add new tests for any new functionality.


Buy Me A Coffee

About

Portable implementation of bitwise operations for 16-bit, 32-bit, and 64-bit integers with byte conversions. No C dependencies, supports Lua 5.1+ and LuaJIT.

Resources

License

Stars

Watchers

Forks