Polars plugin for 256-bit U256 and signed I256 (two's complement) integers backed by ruint
Project description
polars-u256-plugin
Polars plugin for 256-bit integer arithmetic.
🙋 Why
Since Polars tops out at Int128, this will fail:
melania_bags = 2**129
pl.DataFrame(x=[melania_bags])
# OverflowError: int value too large for Polars integer types
with polars_u256_plugin any of these work:
import polars_u256_plugin as u256
df = pl.select(
x=u256.from_int(melania_bags),
y=u256.lit(melania_bags),
z=u256.from_hex(hex(melania_bags)),
)
In addition, you can perform full 256-bit arithmetic, bitwise ops, comparisons, and aggregations in Polars expressions with safe overflow handling (invalid ops yield null).
See examples/example.py and examples/benchmarks.py for more.
🚀 Quickstart
pip install polars_u256_plugin
✨ Features
Core Arithmetic & Operations
- Full 256-bit precision: Built on ruint, ensuring exact arithmetic without precision loss
- Operators: Arithmetic (
+,-,*,/,%,**), bitwise (&,|,^,~,<<,>>), comparisons (==,<,<=,>,>=) - Aggregation:
sum() - Series ops:
cumsum(),diff()
Data Types & Precision
- U256 (unsigned): Full 0 to 2²⁵⁶-1 range for token balances, wei amounts, and large counters
- I256 (signed): Two's complement signed integers with proper overflow handling and Euclidean division/remainder operations
- Exact decimal arithmetic: Enables high-precision financial calculations by storing scaled integers (e.g., storing cents as integers scaled by 10²)
- Safe overflow behavior: Operations return null on overflow rather than wrapping, preventing silent errors
Integration & Usability
- Native Polars expressions: Full integration with
select(),with_columns(),group_by().agg(), and all other Polars operations - Operator overloading: Natural syntax like
pl.col("balance").u256 + pl.col("amount").u256 - Expression namespaces: Fluent API via
.u256and.i256namespaces for operations like.to_hex(),.sum() - Multiple input formats: Accept Python integers, hex strings (
0x...), and raw bytes with automatic coercion
Performance & Storage
- Vectorized operations: All arithmetic implemented in Rust using ruint for optimal performance
- Efficient storage: Uses 32-byte big-endian binary representation via Polars BinaryView for memory efficiency
- Lazy evaluation: Full compatibility with Polars lazy evaluation and query optimization
- Benchmark tested: Significantly faster than Python object fallback methods for large datasets
Blockchain & DeFi Ready
- Ethereum compatibility: Native handling of wei values, token amounts, and smart contract integers
- Hex string support: Seamless conversion to/from hexadecimal for blockchain data interoperability
- No precision loss: Maintains full 256-bit precision throughout complex calculation pipelines
- Production tested: Powers real-world blockchain analytics and DeFi applications
API
Initialization
u256.from_int(value) # Python int → u256 expression
u256.from_int(pl.col()) # Convert int column to u256 (preferred)
u256.from_hex(pl.col()) # Hex strings → u256
u256.lit(value) # Create u256 literal (int/hex/bytes)
Helpers & Constants
# Validation helpers
u256.validate_hex(pl.col("hex_str")) # bool: valid hex/binary → u256
u256.validate_range(pl.col("int_col")) # bool: fits in unsigned 256-bit
# Common constants (as expressions)
u256.MAX_VALUE # 2**256 - 1
u256.MIN_VALUE # 0
i256.MAX_VALUE # 2**255 - 1
i256.MIN_VALUE # -2**255
Arithmetic
u256.add(a, b) # Addition
u256.sub(a, b) # Subtraction
u256.mul(a, b) # Multiplication
u256.div(a, b) # Division (null on div by zero)
u256.mod(a, b) # Modulo
u256.pow(a, b) # Exponentiation
Comparisons
u256.eq(a, b) # Equal
u256.lt(a, b), u256.le(a, b) # Less than, less/equal
u256.gt(a, b), u256.ge(a, b) # Greater than, greater/equal
Bitwise Operations
u256.bitand(a, b) # Bitwise AND
u256.bitor(a, b) # Bitwise OR
u256.bitxor(a, b) # Bitwise XOR
u256.bitnot(a) # Bitwise NOT
u256.shl(a, bits) # Left shift
u256.shr(a, bits) # Right shift
Aggregations & Conversions
u256.sum(col) # Sum aggregation
u256.to_hex(col) # → hex strings (0x...)
u256.to_int(col) # → Python int (if fits in i64)
Group-By Aggregations
df.group_by("account_id").agg(
u256.sum(u256.from_int(pl.col("tx_amount"))).alias("total_spent")
)
# Multiple aggregations
df.group_by("token_address").agg([
u256.sum(u256.from_int(pl.col("balance"))).alias("total_supply"),
pl.len().alias("holder_count"),
pl.col("last_updated").max()
])
# Mixed with regular Polars aggregations
df.group_by("wallet").agg([
u256.sum(u256.from_int(pl.col("wei_balance"))).alias("total_wei"),
pl.col("gas_used").sum(),
pl.col("block_number").max()
]).with_columns(
# Convert to readable hex for display
u256.to_hex(pl.col("total_wei")).alias("total_wei_hex")
)
Display Utilities
u256.format_u256_dataframe(df, cols) # Format u256 columns as hex
u256.print_u256_dataframe(df) # Print with hex formatting
df.with_u256_display("col") # Add hex display columns
df.show_u256_hex("col") # Replace binary with hex
df.u256.from_int(["balance", "amount"], replace=True) # Convert int cols → u256
df.u256.to_hex(["balance"], replace=False) # Add balance_hex
Fluent API (.u256 namespace)
# Arithmetic operators: +, -, *, /, //, %, **
pl.col("balance").u256 + pl.col("amount").u256
pl.col("value").u256 * 2
# Bitwise operators: &, |, ^, ~, <<, >>
pl.col("flags").u256 & 0xFF
# Comparisons: ==, <, <=, >, >=
pl.col("a").u256 < pl.col("b").u256
# Methods
pl.col("value").u256.to_hex()
pl.col("data").u256.sum()
# Aggregations
pl.col("data").u256.min()
pl.col("data").u256.max()
pl.col("data").u256.mean()
I256 (Signed) - Complete API
Supported operations (signed, two's complement): arithmetic (+, -, *, /, %, //=euclid), comparisons, aggregations (sum/min/max/mean), series ops (cumsum/diff), and helpers.
i256.div_euclid(a, b) # Euclidean division
i256.rem_euclid(a, b) # Euclidean remainder
i256.from_int(value_or_col) # Python int or Polars Expr; supports negatives
i256.to_int(col) # Returns signed integers
# Namespace: .i256 (same operators as .u256)
pl.col("balance").i256 + pl.col("amount").i256
Performance
Rows: 5,000,000
== Aggregations ==
u64: sum 0.001s
u256: sum only (preconv) 0.042s
u256: conversion only 0.035s
u256: from_int+sum 0.081s
i128: sum only (preconv) 0.001s
i128: conversion only 0.006s
Decimal(0): sum only (preconv) 0.001s
Decimal(0): conversion only 0.014s
Python Object: map+sum 0.215s
See examples/benchmarks.py for more.
Tip: preconvert once (with_columns(x256=u256.from_int(...))) and reuse.
Implementation Notes
- Storage: U256/I256 are 32-byte big-endian binary columns.
- Semantics:
- Division: u256 uses truncating integer division; i256 has truncating
divand Euclideandiv_euclid/rem_euclid. - Remainder:
i256.modcarries dividend sign; Euclidean remainder is non-negative. - Errors: div/mod by zero → null.
- Overflow: u256 add/mul overflow → null; i256 add/sub/mul wrap modulo 2²⁵⁶.
to_int: returns null if the value does not fit in signed 64-bit.
- Division: u256 uses truncating integer division; i256 has truncating
I256 (signed)
- Two’s complement over 256 bits.
divtruncates toward zero;modcarries dividend sign.- Euclidean:
i256.div_euclid(...)/i256.rem_euclid(...).
Note: Constructing a DataFrame directly with Python ints > 64 -bit may result in non-integer dtype (e.g., Object) depending on your Polars build. In such cases, prefer providing values as hex strings and from_hex, or generate constants in expressions via from_int(pl.lit(...)).
Credits
- ruint: High-performance Rust library for arbitrary-precision unsigned integers
- polars-evm: Utilities for working with EVM data in polars
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 Distributions
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 polars_u256_plugin-0.2.2.tar.gz.
File metadata
- Download URL: polars_u256_plugin-0.2.2.tar.gz
- Upload date:
- Size: 55.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.9.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e6e177fb9e4d8cc589682edb006c976ed0c4ba8ac472f922e79d0fae16d62e68
|
|
| MD5 |
70db2e65f7a562b8edd392c2b9afa952
|
|
| BLAKE2b-256 |
c8110900af9f0ec3aa31c6fda27fb6b9e15bac601b75a56789af030c49332b30
|
File details
Details for the file polars_u256_plugin-0.2.2-cp39-abi3-win_amd64.whl.
File metadata
- Download URL: polars_u256_plugin-0.2.2-cp39-abi3-win_amd64.whl
- Upload date:
- Size: 4.2 MB
- Tags: CPython 3.9+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.9.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c4d741e6642b782fc247e5a52c3c5e285ca5cb208b1708ed32e695052ba1a7ac
|
|
| MD5 |
05c6c55c616cca5f4ade2eaaf2876129
|
|
| BLAKE2b-256 |
31ca8ea29adc3aa6ffe8fbec98fa73fd5832c0eebf2cdeda20889c2a6c8dd701
|
File details
Details for the file polars_u256_plugin-0.2.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: polars_u256_plugin-0.2.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 4.2 MB
- Tags: CPython 3.9+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.9.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e942a0a99f51bd7175f0a4d1383bdbb51c0e384794be85bd95d942632c70233c
|
|
| MD5 |
9e2cfd704e8e107e2a1e2d632c06cff5
|
|
| BLAKE2b-256 |
915bcc6e528ee81b7b3c6db043af529a6dc4c85991ba174e4e40d61e4162efa5
|
File details
Details for the file polars_u256_plugin-0.2.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: polars_u256_plugin-0.2.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 3.9 MB
- Tags: CPython 3.9+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.9.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5fa4d84a94093811a7755966b013df2a5ddd94030f9c84fff09b90d6dd98b89d
|
|
| MD5 |
14607f8e40c8b5332c28a2b40d31188a
|
|
| BLAKE2b-256 |
e87dee9c178355c9150a2c592816c31f9cbaf82ba3292190821638a568c38e5b
|
File details
Details for the file polars_u256_plugin-0.2.2-cp39-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: polars_u256_plugin-0.2.2-cp39-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 3.7 MB
- Tags: CPython 3.9+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.9.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aa4dfa7c81e4a97acd973797658ec074527f1de53cef5131645ebc49863de08f
|
|
| MD5 |
648955411f6477c8feb074bc89698669
|
|
| BLAKE2b-256 |
69859b0c5ec355376b0eadcbf49e28a45a92f7c67d1257b75cf53de30f42735e
|
File details
Details for the file polars_u256_plugin-0.2.2-cp39-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: polars_u256_plugin-0.2.2-cp39-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 4.1 MB
- Tags: CPython 3.9+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.9.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f6257c60d3a88a1b46047e679b373540fd1648b0db54623ed3970a035bc95e6
|
|
| MD5 |
55466ae16326cad92196964230dc71e0
|
|
| BLAKE2b-256 |
e5f02b520001aa6b8f4fd263b3f8c4a65cb2ad6279b4d47e243b5a15179f4dc2
|