Skip to main content

NumericAL

A pure, header-only C++20 numerical computing library — a leaf of the SciLang ecosystem (a sibling of REAL), generic over its scalar type and depending on nothing but the C++ standard library.

NumericAL is agnostic of expressions and of any symbolic layer: it computes with concrete numeric structures — vectors, matrices, tensors — and the algorithms over them. SciLang consumes it as a numeric backend through its module seam; the symbolic↔numeric reconciliation stays in SciLang.

Capabilities

Small and complete, grown measured, honest about what is not yet here:

  • numerical::vector<T> — a dense, value-semantic vector: element-wise arithmetic, scalar multiplication, dot product, tolerance comparison, shape checks.
  • numerical::matrix<T> — a dense, row-major, value-semantic matrix: element-wise arithmetic, scalar / matrix–vector / matrix–matrix products, transpose, tolerance comparison, shape checks.
  • numerical::lu_decomposition<T> — an LU factorisation (partial pivoting) computed once and reused: solve (any number of right-hand sides), determinant, and inverse. Free solve / determinant / inverse are one-shot conveniences.
  • numerical::cholesky_decomposition<T> — A = L Lᴴ for a Hermitian positive-definite matrix (about twice as cheap as LU): the factor lower(), solve, and determinant; throws not_positive_definite_error otherwise.
  • numerical::qr_decomposition<T> — A = Q R (Householder reflections, so Q stays orthonormal to rounding however ill-conditioned A is) for an m × n matrix of any shape, as NumPy's reduced qr: the factors q() (m × k) / r() (k × n), k = min(m, n), and for m ≥ n a least-squares solve of A x ≈ b, which throws singular_matrix_error when A is rank-deficient.
  • numerical::hermitian_eigen — the same for a complex Hermitian matrix (real eigenvalues, a unitary V), reduced to a real tridiagonal by Householder reflections and unit phases as LAPACK's zheev does.
  • numerical::symmetric_eigen — eigenvalues (ascending) and eigenvectors of a real symmetric matrix (A = V Λ Vᵀ): Householder tridiagonalisation then implicit QL, as LAPACK's dsyev; cyclic Jacobi rotations on request (eigen_method::jacobi).
  • numerical::svd_decomposition<T> — the singular value decomposition A = U Σ Vᴴ of a real or complex m × n matrix, any shape: a Householder QR, then Golub–Kahan bidiagonalisation of R and implicit-shift QR, as LAPACK's dgesvd; one-sided Jacobi on R on request (svd_method::jacobi), which gives every singular value to high relative accuracy. singular_values() (descending), u() (m × k), v() (n × k) and vh(), with k = min(m, n); U and V stay orthonormal for a rank-deficient A.
  • numerical::lstsq(a, b) — the minimum-norm least-squares solution of A x ≈ b, as NumPy's lstsq gives it, for any shape and rank (from the SVD), b a vector or a matrix of right-hand sides (as solve(a, b) takes too); pinv(a) and matrix_rank(a) from the same SVD, and lu_decomposition::log_determinant() — NumPy's slogdet, which does not underflow where the determinant does.
  • numerical::tensor<T> — a dense, row-major, N-dimensional tensor (rank-1 is a vector, rank-2 a matrix, rank-0 a scalar; built directly or from a vector / matrix), with einsum — Einstein-summation index notation for contractions and general products, as in NumPy / PyTorch. einsum is the unifying primitive of the algebra: "ij,jk->ik" is the matrix product, "i,i->" the dot product, "ij->ji" the transpose, "ii->" the trace, "i,j->ij" the outer product, "ij->i" a row reduction. It takes one or more operands and sums over every label absent from the output, in a deterministic order.
  • Arithmetic on tensors (tensor_ops.hpp): + - * / element by element with NumPy's broadcasting, sum, mean, max, min of every element or along an axis (sums by NumPy's pairwise blocks), reshape, and zeros, ones, full, eye, arange, linspace.

Grows in as measured: sparse storage, non-symmetric eigenvalues, FFT, numeric autodiff, iterative solvers, numerical integration, arbitrary precision.

Build

make test        # build and run the test suite
make coverage    # line-coverage summary + HTML report
make sanitize    # tests under AddressSanitizer + UndefinedBehaviorSanitizer
make lint        # clang-tidy
make format      # uncrustify, in place
make doc         # API reference (Doxygen) with embedded coverage

Override the compiler with make test CXX=g++-14.

numerical::numerical is the CMake target — add_subdirectory, FetchContent, or an installed config package:

# After `cmake --install <build> --prefix <prefix>`:
find_package(numerical CONFIG REQUIRED)
target_link_libraries(app PRIVATE numerical::numerical)

Releasing

make release computes the next calendar version YYYY.M.PATCH — the patch resets each month, the first release of a month is .0 (PEP 440 drops leading zeros, so 2026.6.1, never 2026.06.001) — bumps it in pyproject.toml and python/numerical/__init__.py, then commits, tags and pushes from a clean main. Pushing the tag drives release.yml, which checks the tag matches the version, builds the abi3 wheels (Linux x86-64/aarch64, macOS universal, Windows) and the sdist, and publishes to PyPI via Trusted Publishing (OIDC, no stored secret).

One-time PyPI setup (before the first release): create a Trusted Publisher for the project numeric-al — owner RECHE23, repository NumericAL, workflow release.yml, environment pypi — and create the matching GitHub Environment named pypi. Until that exists the build/sdist jobs still run, but the publish step fails; the pushed tag remains a valid versioned snapshot regardless.

Python binding

pip install numeric-al        # the distribution is numeric-al; the module is numerical

A CPython binding (stable ABI, one cp310 abi3 wheel serves 3.10+) exposes the unifying object numerical.Tensor (rank-1 a vector, rank-2 a matrix, rank-0 a scalar; float64 or complex128) and the algebra over it. Every function takes a Tensor or anything asarray reads — a NumPy array, a nested list, a number:

import numerical
a = [[1, 2], [3, 4]]
numerical.einsum("ij,jk->ik", a, [[5, 6], [7, 8]])   # matrix product
numerical.einsum("i,i->", [1, 2, 3], [1, 2, 3])       # dot
numerical.solve(a, [1.0, 1.0])                         # a @ x = b

A failure is a numerical.LinAlgError: a ValueError, as numpy.linalg.LinAlgError is, and a numerical.error. A Tensor indexes (t[i, j], t[1:5:2, ::-1]), iterates, transposes (t.T) and multiplies (a @ b) as a NumPy array of rank 1 or 2 does, and computes as one:

t = numerical.arange(6).reshape(2, 3)
(t + 1) * [10, 0, 1] / 2      # element-wise, broadcast as NumPy's
t.sum(), t.mean(axis=0), t.max(axis=-1)
numerical.zeros((2, 2)), numerical.eye(3), numerical.linspace(0, 1, 5)
numerical.exp(t), numerical.sqrt(t), abs(t), t ** 2

Shapes that do not broadcast raise a ValueError worded as NumPy's. max and min take float64 only (NumPy orders complex numbers lexicographically; NumericAL does not order them).

The decomposition layer is exposed too (a numpy.linalg-style surface): determinant(a), slogdet(a) → (sign, logabsdet), inverse(a), pinv(a), matrix_rank(a), lstsq(a, b), cholesky(a), qr(a) → (Q, R), eigh(a) → (values, vectors), svd(a) → (U, S, Vh) — NumPy's svd(a, full_matrices=False), so (U * S) @ Vh is a. Every one accepts float64 and complex128; eigh of a complex Hermitian matrix gives real values and complex vectors.

A Tensor is a citizen of the scientific Python stack, zero-copy:

import numpy as np, torch
np.asarray(t)          # via __array_interface__ (a read-only view)
np.from_dlpack(t)      # via __dlpack__
torch.from_dlpack(t)   # the same DLPack capsule — JAX / CuPy consume it too
numerical.asarray(np.eye(3))   # the other direction (a copy)

asarray copies any NumPy array — bool, integer, float32/64 or complex64/128 elements, in either byte order, at any strides (a transposed, sliced or reversed view) — as well as a nested list or tuple of numbers and a plain number (rank 0), into float64, or complex128 for complex input.

numerical.get_include() returns the header directory, so the C++ library can be located through its Python install. make python builds the extension in place; make python-test runs the binding suite — including a seeded differential fuzzer that checks hundreds of random einsum specifications and linear-algebra problems against NumPy within tolerance (when NumPy is importable, as in CI). PETSc (petsc4py) has no such exchange protocol — bridging it would require an explicit copy into a PETSc object.

Benchmarks

NumericAL is validated against NumPy for both result and speed — make bench-python checks every operation matches NumPy within a tolerance, then times it; make python-test runs the correctness parity suite alone (also in CI). The results and methodology, with an honest reading of the gap, are in BENCHMARKS.md: NumericAL is a portable, dependency-free reference implementation: correct within tolerance, and competitive with NumPy's own einsum/linalg (it beats np.einsum's non-BLAS path and the decompositions land within ~1–4×). Against hand-tuned BLAS (np.matmul) its packed, register-tiled, std::thread-parallel GEMM is ~3× slower and steady from n = 256 to 2048 — what remains is per-architecture assembly, which a header-only library does not carry. See BENCHMARKS.md for the honest details.

Numerical discipline

Floating-point accuracy is documented, never claimed exact where it cannot be; results are deterministic given inputs and any tolerance/seed; differential tests compare against references within a documented tolerance. Same gate bar as the rest of the ecosystem: 100% coverage, clang and g++-14, lint, format, and sanitizers green.

License

MIT — see LICENSE.

Author

René Chenard

Metadata

Release files for numeric-al 2026.10.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for numeric-al 2026.10.3
File Size Uploaded
numeric_al-2026.10.3.tar.gz 96.5 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for numeric-al 2026.10.3
File
numeric_al-2026.10.3-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details
numeric_al-2026.10.3-cp310-abi3-win32.whl CPython 3.10 abi3 Windows x86-32 Details
numeric_al-2026.10.3-cp310-abi3-musllinux_1_2_x86_64.whl CPython 3.10 abi3 Linux musl 1.2+ x86-64 Details
numeric_al-2026.10.3-cp310-abi3-musllinux_1_2_aarch64.whl CPython 3.10 abi3 Linux musl 1.2+ ARM64 Details
numeric_al-2026.10.3-cp310-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl CPython 3.10 abi3 Linux glibc 2.24+ x86-64, Linux glibc 2.28+ x86-64 Details
numeric_al-2026.10.3-cp310-abi3-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl CPython 3.10 abi3 Linux glibc 2.28+ ARM64, Linux glibc 2.24+ ARM64 Details
numeric_al-2026.10.3-cp310-abi3-macosx_11_0_x86_64.whl CPython 3.10 abi3 macOS 11.0+ x86-64 Details
numeric_al-2026.10.3-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details

Total release size: 4.4 MB

Release files / numeric_al-2026.10.3.tar.gz

Download URL numeric_al-2026.10.3.tar.gz
Size 96.5 kB
Tags Source
SHA-256 checksum
How to use checksums
10cb326c6dd27a687bbc27d25a6df2f263a9d8a0e839611ceb1ee7d5eb017e0c
BLAKE2b-256 checksum
How to use checksums
65ced8f3c6edfc7e1af0ee60fbc57e3814aef0f8a387187d7a7b9248b01287d0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / numeric_al-2026.10.3-cp310-abi3-win_amd64.whl

Download URL numeric_al-2026.10.3-cp310-abi3-win_amd64.whl
Size 407.2 kB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
fcb25c9f9f6bf3ae08da807cb5d07bcd720b4863a4583af5319d692175ae3d00
BLAKE2b-256 checksum
How to use checksums
19961aa71942a83162bb8f2c444a882e4529cf07f76ab6d6f4cd65748e11482d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / numeric_al-2026.10.3-cp310-abi3-win32.whl

Download URL numeric_al-2026.10.3-cp310-abi3-win32.whl
Size 385.8 kB
Tags CPython 3.10 Windows x86-32 abi3
SHA-256 checksum
How to use checksums
0775ed5beff91a3442e4f76b7b9d1df3d96939f466f6473fcfc12255b191ccbf
BLAKE2b-256 checksum
How to use checksums
804d33e93cc7e3b2f6c3a39c8f852aeea2e982e7c2d6e9317c5d9afcb854ca01
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / numeric_al-2026.10.3-cp310-abi3-musllinux_1_2_x86_64.whl

Download URL numeric_al-2026.10.3-cp310-abi3-musllinux_1_2_x86_64.whl
Size 1.3 MB
Tags CPython 3.10 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
142d7bf5d6c4699b873a3fc53cf423145746002a300e1a080c0c6e0390d13967
BLAKE2b-256 checksum
How to use checksums
c98312afa23538a978f18e672add5e06de387600330aacb70f1bdc6fef770443
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / numeric_al-2026.10.3-cp310-abi3-musllinux_1_2_aarch64.whl

Download URL numeric_al-2026.10.3-cp310-abi3-musllinux_1_2_aarch64.whl
Size 1.2 MB
Tags CPython 3.10 Linux musl 1.2+ ARM64 abi3
SHA-256 checksum
How to use checksums
afdd549af275b0486ab40eb2ef813931d13f4efe6ec76ba7b68d9a557e9876a4
BLAKE2b-256 checksum
How to use checksums
dc8e86272ed56181fc999a04824b328dc8f0ea1818678126bc5bc4831627d0a6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / numeric_al-2026.10.3-cp310-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl

Download URL numeric_al-2026.10.3-cp310-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Size 267.5 kB
Tags CPython 3.10 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64 abi3
SHA-256 checksum
How to use checksums
7802673661f9c40c0c2363bb52fc9ffa6ae671b0b062ec9bde832f6bcd8c7a46
BLAKE2b-256 checksum
How to use checksums
364296886ccab8bd6f3b3224e86a7767749224bc0aa647aed68c19d228dca689
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / numeric_al-2026.10.3-cp310-abi3-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl

Download URL numeric_al-2026.10.3-cp310-abi3-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
Size 240.0 kB
Tags CPython 3.10 Linux glibc 2.24+ ARM64 Linux glibc 2.28+ ARM64 abi3
SHA-256 checksum
How to use checksums
5c7fe764792e98c7191b58cac1ea9d823be315b4fef4d701d52e9cf813f5d669
BLAKE2b-256 checksum
How to use checksums
3de3eb380c06f9a5158e2bb8d26f9ac6cab08214da28fca7509838df42518114
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / numeric_al-2026.10.3-cp310-abi3-macosx_11_0_x86_64.whl

Download URL numeric_al-2026.10.3-cp310-abi3-macosx_11_0_x86_64.whl
Size 251.8 kB
Tags CPython 3.10 abi3 macOS 11.0+ x86-64
SHA-256 checksum
How to use checksums
09dbcace8e6d2e41b24bd4b1664b5b228ba0a62e95aa3cbc945ad5694a9ebcb4
BLAKE2b-256 checksum
How to use checksums
bf01e675173b1ca6a53b14f26c1a06ecfe6620c031f14e5998e877ed6735ff1e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / numeric_al-2026.10.3-cp310-abi3-macosx_11_0_arm64.whl

Download URL numeric_al-2026.10.3-cp310-abi3-macosx_11_0_arm64.whl
Size 227.9 kB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
0d0745efbdf60b317419e641410173c43f5e08551ef6f827b9088b76ba25ecf8
BLAKE2b-256 checksum
How to use checksums
fec20099f686c6ba008bea154e01f43a106ab964ab98a2baf26585d567b168f5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page