Python bindings for working with 24-bit integers.
Project description
i24: 24-bit Integer Types for Python
The i24 package provides specialized 24-bit integer types for Python: I24 (signed) and U24 (unsigned). These types are implemented in Rust for high performance and provide a Python interface for working with 24-bit integers commonly found in audio processing, embedded systems, network protocols, and binary data formats.
Features
Integer Types
- I24: 24-bit signed integer (range: -8,388,608 to 8,388,607)
- U24: 24-bit unsigned integer (range: 0 to 16,777,215)
Core Functionality
- Full arithmetic and bitwise operations with overflow checking
- Conversion to/from Python
intandbytes - Little-endian, big-endian, and native byte order support
- NumPy integration for array operations
- Immutable (frozen) types for thread safety
- High performance Rust implementation
- Checked arithmetic operations (return
Noneon overflow) - Complete set of comparison operators
This package is part of the i24 project, which also provides Rust implementations. The Python bindings were created to support the Wavers audio processing library.
Installation
Requirements
- Python 3.10 or later
- NumPy 1.26 or later (automatically installed as a dependency)
From PyPI
pip install i24
Upgrading
pip install --upgrade i24
From Source
For development or to use the latest unreleased features:
git clone https://github.com/jmg049/i24.git
cd i24
pip install maturin
maturin develop --release
Quick Start
Basic Usage
from i24 import I24, U24
# Create 24-bit integers
signed = I24(1000)
unsigned = U24(2000)
# Arithmetic operations
result = signed + I24(500)
print(result.to_int()) # 1500
# Conversions
as_int = int(signed)
print(as_int) # 1000
Working with Bytes
from i24 import I24, U24
# Create from bytes (little-endian)
bytes_le = bytes([0x00, 0x10, 0x00])
value = I24.from_bytes(bytes_le, byteorder='little')
print(value.to_int()) # 4096
# Convert to bytes (big-endian)
be_bytes = value.to_bytes(byteorder='big')
print(be_bytes) # b'\x00\x10\x00'
# Create from big-endian bytes
bytes_be = bytes([0x12, 0x34, 0x56])
value = I24.from_bytes(bytes_be, byteorder='big')
print(hex(value.to_int())) # 0x123456
Checked Arithmetic
Checked arithmetic methods return None on overflow instead of raising exceptions:
from i24 import I24
a = I24(8_000_000)
b = I24(500_000)
# Safe addition
result = a.checked_add(b)
if result is None:
print("Addition would overflow")
else:
print(f"Result: {result.to_int()}")
# Other checked operations
result = a.checked_sub(b) # Checked subtraction
result = a.checked_mul(I24(2)) # Checked multiplication
result = a.checked_div(b) # Checked division (also checks for division by zero)
Value Ranges and Overflow Behavior
Value Ranges
- I24: [-8,388,608, 8,388,607]
- U24: [0, 16,777,215]
Overflow Behavior
Standard operators raise OverflowError when results exceed the valid range:
from i24 import I24
a = I24(8_000_000)
b = I24(500_000)
try:
result = a + b # This will overflow
except OverflowError as e:
print(f"Overflow: {e}")
Use checked arithmetic methods when you want to handle overflow explicitly without exceptions.
Division by Zero
Division operations raise ZeroDivisionError:
from i24 import I24
a = I24(1000)
zero = I24(0)
try:
result = a / zero
except ZeroDivisionError as e:
print(f"Error: {e}")
Supported Operations
Arithmetic Operations
from i24 import I24, U24
a = I24(1000)
b = I24(500)
# Standard operators
sum_val = a + b # Addition
diff = a - b # Subtraction
prod = a * b # Multiplication
quot = a / b # Division (returns float)
floor_div = a // b # Floor division
mod = a % b # Modulo
neg = -a # Negation
pos = +a # Unary plus
# Checked operations (return None on overflow)
safe_sum = a.checked_add(b)
safe_diff = a.checked_sub(b)
safe_prod = a.checked_mul(b)
safe_quot = a.checked_div(b)
Bitwise Operations
from i24 import I24, U24
a = I24(0b111100001111)
b = I24(0b110011001100)
# Bitwise operators
and_result = a & b # Bitwise AND
or_result = a | b # Bitwise OR
xor_result = a ^ b # Bitwise XOR
not_result = ~a # Bitwise NOT
left_shift = a << 4 # Left shift
right_shift = a >> 2 # Right shift
Comparison Operations
from i24 import I24
a = I24(1000)
b = I24(2000)
# All standard comparison operators
is_equal = a == b # Equality
not_equal = a != b # Inequality
less = a < b # Less than
less_eq = a <= b # Less than or equal
greater = a > b # Greater than
greater_eq = a >= b # Greater than or equal
Byte Operations and Endianness
All byte operations support three byte orders:
'little': Little-endian (least significant byte first)'big': Big-endian (most significant byte first)'native': Native byte order (platform-dependent)
Converting to Bytes
from i24 import I24
value = I24(0x123456)
# Little-endian (LSB first)
le_bytes = value.to_bytes(byteorder='little')
print(le_bytes) # b'\x56\x34\x12'
# Big-endian (MSB first)
be_bytes = value.to_bytes(byteorder='big')
print(be_bytes) # b'\x12\x34\x56'
# Native byte order (platform-dependent)
native_bytes = value.to_bytes(byteorder='native')
Creating from Bytes
from i24 import I24
# From little-endian bytes
bytes_le = bytes([0x12, 0x34, 0x56])
value = I24.from_bytes(bytes_le, byteorder='little')
print(hex(value.to_int())) # 0x563412
# From big-endian bytes
bytes_be = bytes([0x12, 0x34, 0x56])
value = I24.from_bytes(bytes_be, byteorder='big')
print(hex(value.to_int())) # 0x123456
Use Cases
Audio Processing
24-bit integers are commonly used in professional audio applications:
from i24 import I24
# Read 24-bit audio samples
def read_24bit_samples(data: bytes) -> list[I24]:
samples = []
for i in range(0, len(data), 3):
sample_bytes = data[i:i+3]
sample = I24.from_bytes(sample_bytes, byteorder='little')
samples.append(sample)
return samples
Binary Protocols
Handling network protocols with 24-bit fields:
from i24 import U24
# Parse a 24-bit packet ID
packet_bytes = bytes([0x12, 0x34, 0x56])
packet_id = U24.from_bytes(packet_bytes, byteorder='big')
print(f"Packet ID: {packet_id.to_int()}")
Embedded Systems
Working with hardware that uses 24-bit data types:
from i24 import U24
# Read 24-bit sensor value
sensor_data = bytes([0xFF, 0x00, 0x12])
sensor_value = U24.from_bytes(sensor_data, byteorder='little')
print(f"Sensor reading: {sensor_value.to_int()}")
Type Safety
Both I24 and U24 are immutable (frozen) types, making them safe for use in multi-threaded environments:
from i24 import I24
value = I24(1000)
# value.some_attribute = 42 # This would raise an error
# I24 instances cannot be modified after creation
Performance
The i24 package is implemented in Rust using PyO3, providing:
- Near-native performance for arithmetic operations
- Similar to
i32andu32performance
Documentation
Full documentation is available at: https://jmg049.github.io/i24/
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Visit the main repository at: https://github.com/jmg049/i24
License
This project is licensed under MIT - see the LICENSE file for details.
Links
- PyPI: https://pypi.org/project/i24/
- Documentation: https://jmg049.github.io/i24/
- Source Code: https://github.com/jmg049/i24
- Issue Tracker: https://github.com/jmg049/i24/issues
- Changelog: https://github.com/jmg049/i24/blob/main/CHANGELOG.md
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file i24_type-2.3.1.tar.gz.
File metadata
- Download URL: i24_type-2.3.1.tar.gz
- Upload date:
- Size: 1.6 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.11.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
07b2c5141a328047272cf918447018e5f9297edb315fc8275cfe8083653ed18c
|
|
| MD5 |
dfa631f5c77f5743aa94bc8ca962f1fb
|
|
| BLAKE2b-256 |
33b488edacdac71cc8a9025b040d0a11a3ed62ad1a879ff5bed9e34d2106e358
|
File details
Details for the file i24_type-2.3.1-cp311-cp311-manylinux_2_34_x86_64.whl.
File metadata
- Download URL: i24_type-2.3.1-cp311-cp311-manylinux_2_34_x86_64.whl
- Upload date:
- Size: 259.2 kB
- Tags: CPython 3.11, manylinux: glibc 2.34+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.11.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9a13c47820e1a269a65e2a30f91a8052404c26879304f20ee8196a3bdec105ef
|
|
| MD5 |
ae37e00b02f7b0fe239fc971b303bd74
|
|
| BLAKE2b-256 |
131ed159c89d0793d18583fbf41c0a533f5c335fe09f621f7f91b757fd6c3e27
|