A robust implementation of fixed-width integers in Python that precisely emulates C-style behavior.
Project description
fixed-width-int
A robust implementation of fixed-width integers in Python that precisely emulates C-style behavior. Ideal for low-level programming, hardware emulation, and situations requiring exact control over integer representation and arithmetic.
Features
- C-like Behavior:
- Two's complement signed integers
- Modular arithmetic for unsigned integers
- Value wrapping on overflow/underflow
- C-style division (truncates toward zero)
- C-style modulo (matches division behavior)
- Automatic type promotion
- Type System:
- Dynamic type creation via bit-width parameterization (e.g.,
Unsigned[8],Signed[10]) - Intuitive subtype relationships:
Signed[m]is a supertype ofSigned[n]when m > nUnsigned[m]is a supertype ofUnsigned[n]when m > nSigned[m]is a supertype ofUnsigned[n]when m > n
- Full support for
isinstanceandissubclasschecks
- Dynamic type creation via bit-width parameterization (e.g.,
- Compatibility
- Pure Python
- Supports Python 2+
Installation
pip install fixed-width-int
Quick Start
from fixed_width_int import Unsigned, Signed
# Type definitions
U8 = Unsigned[8] # 8-bit unsigned
S10 = Signed[10] # 10-bit signed
# Basic operations
assert U8(255) + U8(1) == U8(0) # Wraps around
assert S10(511) + S10(1) == S10(-512) # Two's complement behavior
# Type promotion
assert type(U8(200) + S10(100)) is S10
assert U8(200) + S10(100) == S10(300)
Comprehensive Examples
Type System and Basic Operations
from fixed_width_int import Unsigned, Signed
# Type definitions
U8 = Unsigned[8]
U16 = Unsigned[16]
S8 = Signed[8]
S16 = Signed[16]
# Subtyping checks
assert issubclass(U8, U16) # Wider unsigned types are supertypes
assert issubclass(S8, S16) # Wider signed types are supertypes
assert issubclass(U8, S16) # Unsigned is subtype of wider signed
assert not issubclass(S8, U16) # Signed isn't subtype of wider unsigned
# Value wrapping
assert U8(256) == U8(0) # Modular arithmetic
assert S8(128) == S8(-128) # Two's complement wrap
assert S8(-129) == S8(127) # Underflow handling
# Addition/subtraction
assert U8(200) + U8(100) == U8(44) # 300 % 256
assert S8(-100) - S8(30) == S8(126) # Wraps around
# Multiplication
assert U8(20) * U8(13) == U8(4) # 260 % 256
assert S8(-10) * S8(13) == S8(126) # -130 wraps to 126
# C-style division
assert S8(7) / S8(3) == S8(2) # Truncates toward zero
assert S8(-7) / S8(3) == S8(-2) # Negative division
# C-style modulo
assert S8(7) % S8(3) == S8(1)
assert S8(-7) % S8(3) == S8(-1) # Matches division
# Basic bitwise ops
assert U8(0b10101010) & U8(0b11001100) == U8(0b10001000)
assert U8(0b10101010) | U8(0b11001100) == U8(0b11101110)
# Shifts
assert S8(0b11110000) >> S8(2) == S8(-4) # Arithmetic right shift
assert U8(0b11110000) >> U8(2) == U8(0b00111100) # Logical right shift
assert U8(1) << U8(7) == U8(128)
assert U8(1) << U8(8) == U8(0)
# Exponentiation
assert pow(U8(3), U8(4)) == U8(81)
assert pow(S8(2), S8(5), S8(9)) == S8(5) # With modulus
# Type coercion and promotion
# Coerced to unsigned
assert type(U8(200) + S8(100)) is U8
assert U8(200) + S8(100) == U8(44)
# Promoted to wider signed
assert type(S16(-10) + U8(10)) is S16
assert S16(-10) + U8(10) == S16(0)
# Coerced to wider unsigned
assert type(U16(10) + S8(-11)) is U16
assert U16(10) + S8(-11) == U16(65535)
# Comparisons
assert S8(-1) == U8(255) # Value equality
assert U8(255) > S8(0) # Comparison works across types
assert U8(1) < S8(-1) # Because S8(-1) gets coerced to U8(255)
# Negation, identity, absolute
assert -S8(5) == S8(-5)
assert +S8(-5) == S8(-5)
assert abs(S8(-5)) == S8(5)
assert abs(S8(-128)) == S8(-128) # Overflow!
Implementation Highlights
Core Architecture
- Metaclass Magic:
FixedWidthIntMetadynamically creates fixed-width types while caching them for efficiency - Strict Type Safety: Prevents direct instantiation of raw
Signed/Unsignedwithout bit-width specification
Key Components
-
Metaclass
FixedWidthIntMeta:- Dynamically generates concrete integer types through
__getitem__ - Manages type caching
- Sets width-specific properties (BIT_WIDTH, MODULO, etc.)
- Dynamically generates concrete integer types through
-
Base Class
FixedWidthIntBase:- Implements all
numbers.Integralabstract methods - Handles core arithmetic with proper wrapping behavior
- Stores actual value in
promoted_to_int
- Implements all
-
Signed and Unsigned Types:
Signed: Implements two's complement behaviorUnsigned: Implements modular arithmetic behavior- Both implement
wrap_integralto handle value truncation/interpretation - Both implement
__subclasshook__to establish the subtype relationships described in the requirements- Carefully avoids infinite recursion
-
Preventing Direct Instantiation:
FixedWidthIntBase.__new__checks ifcls.BIT_WIDTH == inf- If true, raise an informative error telling users they must use
Signed[bit_width]orUnsigned[bit_width]first - This prevents raw
Signed()orUnsigned()instantiation
from fixed_width_int import Signed
# This works for type checking
assert issubclass(Signed[8], Signed)
assert issubclass(Signed[8], Signed[8])
assert issubclass(Signed[8], Signed[9])
assert isinstance(Signed[8](42), Signed)
assert isinstance(Signed[8](42), Signed[8])
assert isinstance(Signed[8](42), Signed[9])
# Raises ValueError about needing to specify bitwidth
Signed(42)
Why Use This Library?
- Precision: Get exactly the integer behavior you need for emulators, protocols, or low-level code
- Safety: Clear error messages and strict type checking prevent subtle bugs
- Pythonic: Integrates smoothly with Python's type system and number hierarchy
- Performance: Optimized implementation with minimal overhead
Contributing
Contributions are welcome! Please submit pull requests or open issues on the GitHub repository.
License
This project is licensed under the MIT License.
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 fixed_width_int-0.1.0a2.tar.gz.
File metadata
- Download URL: fixed_width_int-0.1.0a2.tar.gz
- Upload date:
- Size: 8.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
710b199761fe4574032bd1545712a71afb9831db236a62faf5ace528f1247d3d
|
|
| MD5 |
f364b240ac9726f1b90d103cc4ed6417
|
|
| BLAKE2b-256 |
e1437b6c62d098d1dfc1f02e861b6a0aa70af778cfc6ca68405e265242ca849d
|
File details
Details for the file fixed_width_int-0.1.0a2-py2.py3-none-any.whl.
File metadata
- Download URL: fixed_width_int-0.1.0a2-py2.py3-none-any.whl
- Upload date:
- Size: 8.3 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8f5881bfb21b7cd3e14f8d4c5cb1cf4f76f3818e04af755e7cdd819718b84c82
|
|
| MD5 |
60741514a5aac0adc400df22401a6ac1
|
|
| BLAKE2b-256 |
24cfb98b6666ed5ddf9c3784e056de6e851fafdd85f0fa7c56d285c2d528f91e
|