precise-numpy
Interval arithmetic with guaranteed error bounds for Python, powered by Rust.
Quickstart · API · Benchmarks · Correctness · Changelog
What You Can Verify
Need guaranteed error bounds on numerical computing? Browse the capability grid below — every operation returns a rigorous (midpoint, radius) enclosure over the true mathematical value.
| Domain | What it does | Status |
|---|---|---|
| Core arithmetic | + - * / ** @, in-place, broadcasting, scalar both sides |
Available |
| Math functions | sin, cos, tan, exp, ln, log2, log10, sqrt, abs, floor, ceil, trunc, round, sign, clip, power |
Available |
| Reductions | sum, mean, prod, var, std, min, max, argmin, argmax, all, any — with optional axis |
Available |
| Linear algebra | det, inv, solve, lstsq, pinv, cholesky, matrix_power, cond, matrix_rank |
Available |
| Eigen / SVD | eig (symmetric + general), svd — rigorous eigenvalue, eigenvector, singular-value and singular-vector enclosures |
Available |
| Norms | norm(a, ord, axis) — numpy-compatible ord in {None/2/'fro', 1, -1, inf, -inf, 'nuc'} |
Available |
| Random | rand, randn, randint, uniform, normal, random_sample — xoshiro256**, reproducible |
Available |
| Interop | __array_ufunc__ (NEP-13), __array_function__ (NEP-18), to_numpy, from_numpy, save_npy, load_npy, astype |
Available |
| I/O | .pn (binary mid+rad), .npy (numpy-compatible), .txt (text with shape header) |
Available |
Stack
| Piece | What it does |
|---|---|
| Rust core | All arithmetic kernels, SIMD-amenable SoA buffer, interval primitives with directed rounding |
| GEMM radius pass | 4 parallel dgemm calls (midpoint + 3 radius terms) + one global RTN inflation; 1000×1000 matmul ≈ 0.14s |
| Exact error tracking | FMA residuals + TwoSum per-product rounding errors; no silent rounding loss |
| Rayon parallelism | Row-block decomposition over threads; GIL released during long computations |
| PyO3 abi3 wheel | CPython >= 3.10, single wheel for Linux/macOS/Windows |
precise-numpy vs NumPy
| precise-numpy | NumPy | |
|---|---|---|
| Element type | Interval (midpoint, radius) — two f64 per element |
float64 — one f64 per element |
| Memory per element | 16 bytes | 8 bytes |
| Arithmetic result | Rigorous enclosure guaranteed | Floating-point result; no error bound |
| matmul (1000³) | ≈ 0.14s (4 dgemm passes) | ≈ 0.02s (1 dgemm pass) |
| Writeable views | Not supported (copy on write) | Full strided views, in-place ops |
| Drop-in replacement | No — result types are intervals | Yes — returns float64 |
| Guarantee | Every result contains the true mathematical value | No formal guarantee |
Installation
pip install precise-numpy
Requires Python >= 3.10. Build from source:
git clone https://github.com/kuntal-devrat/precise-numpy.git
cd precise-numpy
maturin develop --release
Quick Start
import precise_numpy as pnp
import numpy as np
# Create interval arrays with error bounds
a = pnp.array([0.1, 0.2, 0.3], error=1e-4)
b = pnp.array([0.4, 0.5, 0.6], error=1e-4)
# Arithmetic propagates both midpoints and radii
c = a + b
print(c.radii()) # [2e-4, 2e-4, 2e-4]
print(c.max_radius()) # 2e-4
# Reductions return (midpoint, radius) tuples
mid, err = c.sum()
print(f"sum = {mid} +/- {err}")
# NumPy ufuncs work via NEP-13
r = np.exp(pnp.array([0.0, 1.0]))
print(r.values()) # [1.0, e]
# np.linalg works via NEP-18
A = pnp.array([[1.0, 2.0], [3.0, 4.0]])
print(np.linalg.norm(A)) # Frobenius norm: (mid, rad)
print(np.linalg.eigvals(A)) # eigenvalue intervals
print(np.linalg.svd(A)) # U, singular values, Vt (all interval)
API Reference
Array creation
array(values, error=0.0), asarray, zeros(shape), ones, empty, full(shape, value, error=0.0),
eye(n, m=None, k=0), identity(n), diag(v), arange(start, stop, step=1.0),
linspace(start, stop, num=50, endpoint=True), from_raw_parts(midpoints, radii, shape).
empty(shape) zeros memory on purpose — uninitialised radii would violate the rigorous enclosure guarantee.
to_numpy(a, dtype=None), from_numpy(x, error=scalar_or_array), astype(a, dtype), save_npy(path, arr), load_npy(path).
Properties & conversions
shape, ndim, size, dtype ("interval64"), itemsize (16), nbytes, strides, t,
values(), radii(), tolist(), get(i), item(i), midpoint(i), radius(i),
copy(), flatten(), ravel(), reshape(*shape), transpose(), sort(), argsort().
__array__(dtype=None) (NEP-18) — returns a plain float64 ndarray of midpoints so np.asarray(pnp_array) and np + pnp_array work naturally.
Indexing
Integer (with negatives), slices (a[1:4], a[::-1]), fancy integer lists (a[[0, 2]]),
boolean masks (a[a > 2.0], a[BoolArray]), and 2D tuples (m[1, :], m[:, 0]).
Assignment works for integers, slices, and lists.
Arithmetic & math
+ - * / ** @, in-place variants, scalar operands on either side, NumPy broadcasting.
sin, cos, tan, exp, ln, log2, log10, sqrt, abs, floor, ceil, trunc, round, clip(a_min, a_max), sign, nan_to_num, power(x, y), maximum(x, y), minimum(x, y).
Comparisons
==, != (overlap), <, <=, >, >= (strict ordering) return BoolArray values with
& | ^ ~, any(), all(), sum(), count_nonzero(), tolist().
Reductions
sum, mean, prod, var, std, min, max, argmin, argmax, all, any — each with an optional axis;
plus min_val(), max_val(), cumsum(axis=None), norm(ord=None, axis=None)
with numpy-compatible ord in {None/2/'fro', 1, -1, inf, -inf, 'nuc'} and int axis.
Stacking & selection
concatenate(arrays, axis=0), stack, vstack, hstack, split(a, sections_or_indices, axis=0),
where(condition, x, y), nonzero(a) (tuple of index lists per axis).
Linear algebra (precise_numpy.linalg)
det, inv, solve(A, b), lstsq(A, b), pinv, eig, svd, norm, cholesky, matrix_power, matrix_rank, cond.
Rigor notes:
eig_symmetric (Jacobi) — rigorous eigenvalue and eigenvector enclosures via residual bounds + Davis–Kahan.
eig_general (Hessenberg QR + Schur back-substitution) — rigorous eigenvalue radii via Bauer–Fike; eigenvector radii via perturbation bound (bounded by 1.0 at defective limit; inf for fully defective matrices).
svd — rigorous singular-value radii (cluster hull for degenerate clusters) + Davis–Kahan singular-vector radii.
pinv — interval reciprocals of singular values, sound for all conditioning levels.
solve — rigorous LU with partial pivoting + forward/back substitution.
Random (precise_numpy.random)
seed, rand(*size), random_sample(*size), random(*size), randn(*size),
randint(low, high, *size), uniform(low, high, *size), normal(loc=0.0, scale=1.0, *size).
Deterministic xoshiro256**; randint scalar returns a Python int.
Error-Bound Example: AI Quantization Audit
import precise_numpy as pnp
# Wrap input data with interval error bounds
X = pnp.array(floats, error=1e-4).reshape([128, 64])
W = pnp.array(weights).reshape([64, 64])
# Propagate error through a linear layer
Q = X.matmul(W)
print("Max Radius Error:", Q.max_radius())
print("Max Relative Error:", Q.max_relative_error())
Semantics
- Values:
get(i),a[0],sum(), etc. return a(midpoint, radius)tuple. To get raw float arrays usea.values()/a.radii(). ==/!=mean interval overlap;<, <=, >, >=use strict endpoint ordering (a.hi < b.lo, etc.).- Division by zero raises a
RuntimeWarningand produces the entire real line (radiusinf) for the affected element. len(a)isa.shape[0], matching NumPy.- Reductions (
sum,mean, ...) support an optionalaxisargument; scalar results come back as(midpoint, radius)tuples, axis results asIntervalArrays. - dtype is
"interval64",itemsizeis 16 (twof64s per element). - Rounding (
round) uses round-half-to-even, like Python and NumPy. reshape(-1, ...)infers the missing dimension;transpose/.tsupport 1D/2D.- NEP-13 ufunc:
np.add,np.multiply,np.negative,np.absolute,np.exp,np.log,np.sqrt,np.sin,np.cos,np.tan,np.isnan,np.isinf,np.isfinite,np.rint,np.sign,np.matmulall work onIntervalArray. - NEP-18 function:
np.linalg.norm,np.linalg.inv,np.linalg.solve,np.linalg.svd,np.linalg.eig,np.linalg.eigvals,np.linalg.pinv,np.sum,np.mean,np.std,np.var,np.max,np.min,np.all,np.any,np.concatenate,np.stack, etc.
Status
| Axis | State |
|---|---|
| Correctness | 98 Rust + 97 Python tests. All rigor proofs hold. Degenerate inputs → ∞ radius or ValueError, never fake precision. |
| Performance | matmul 1000×1000: ~0.14s. Element-wise: ~1.1–2× vs numpy. 50 random triplets verified rigorous vs float128. |
| API surface | Creation, arithmetic, reductions, broadcasting, indexing, linalg, random, I/O, NEP-13/18 interop |
| Missing vs numpy | Complex intervals, float32 intervals, writeable views, np.fft, np.partition, np.take, many ufuncs (tanh, arccos, erf) |
| Classification | Stable (1.0.0) — API frozen; rigorous enclosures guaranteed. Feature gaps remain vs numpy. |
Testing
make check # fmt + clippy + ruff + all tests
make test # Rust + Python tests
cargo test # Rust unit tests
python -m unittest tests/python/test_api.py # Python integration tests
CI runs the full lint + test matrix on Linux, macOS and Windows for Python
3.10–3.13 on every push and pull request. Tagged v* releases build wheels
for all platforms and publish to PyPI.
License
MIT License. See LICENSE for details.
Metadata
Release files for precise-numpy 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| precise_numpy-1.0.0.tar.gz | 482.6 kB | Without provenance | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| precise_numpy-1.0.0-cp310-abi3-win_amd64.whl | CPython 3.10 | abi3 | Windows x86-64 | Details |
| precise_numpy-1.0.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| precise_numpy-1.0.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| precise_numpy-1.0.0-cp310-abi3-macosx_11_0_arm64.whl | CPython 3.10 | abi3 | macOS 11.0+ ARM64 | Details |
| precise_numpy-1.0.0-cp310-abi3-macosx_10_12_x86_64.whl | CPython 3.10 | abi3 | macOS 10.12+ x86-64 | Details |
Total release size: 2.7 MB
Release files / precise_numpy-1.0.0.tar.gz
| Download URL | precise_numpy-1.0.0.tar.gz |
|---|---|
| Size | 482.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
998de867a7212f58f9c21b35a3f3988301bde39f793b14f224e3ef1648cd4383
|
|
BLAKE2b-256 checksum How to use checksums |
2aaff2a001ba1f131c0018347725b1c0c86ac917fd85ab1e45ed1e1009063fa2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / precise_numpy-1.0.0-cp310-abi3-win_amd64.whl
| Download URL | precise_numpy-1.0.0-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 407.6 kB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
de63c2e2128326ff5499c8d92e31d0234acb2caf7d25723d1a863a76f139e33c
|
|
BLAKE2b-256 checksum How to use checksums |
9dfd554ec10d77018d032c9402d8f1963edc2915b2c94110eb90f0accc47abfd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / precise_numpy-1.0.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | precise_numpy-1.0.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 515.2 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
584ab9664a492ed615639af8104298e4c82d3121d7df95bc3f81af8aa5c5b298
|
|
BLAKE2b-256 checksum How to use checksums |
7e5c587d87a58c80c43490b15a5dd6adec7abcf78bb4b2d3d0976916d9f625ef
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / precise_numpy-1.0.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | precise_numpy-1.0.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 452.8 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
954b1339e2b9de2ccaab6b5aec842a3c7d4cf544982997094a0680db13d35a32
|
|
BLAKE2b-256 checksum How to use checksums |
837c6407595f91249dbaf2d2a5993358790d753599cc0672ea9623da224a9adc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / precise_numpy-1.0.0-cp310-abi3-macosx_11_0_arm64.whl
| Download URL | precise_numpy-1.0.0-cp310-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 412.8 kB |
| Tags | CPython 3.10 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
49afddd0c4fc5696662e2d6e85cfab2c85b4b1920df976d14e6dda0630f8c1b9
|
|
BLAKE2b-256 checksum How to use checksums |
f08ed242d9f964a6ad927b18c1a0fbbd8a2948be3999e79584555662b7637dc4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / precise_numpy-1.0.0-cp310-abi3-macosx_10_12_x86_64.whl
| Download URL | precise_numpy-1.0.0-cp310-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 474.9 kB |
| Tags | CPython 3.10 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
f833bc187f7f3d39efe85c4db7a2d3d99c7ce8f414cb3067e0859c3cfb4d2314
|
|
BLAKE2b-256 checksum How to use checksums |
63a96a16a9af5dfe3b0ca1449967a80ea550230ad5ee33a6ae9bd219f6e7057f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Security for precise-numpy 1.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.