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, complex Hermitian eigen, 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.2

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.2
File Size Uploaded
numeric_al-2026.10.2.tar.gz 29.0 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for numeric-al 2026.10.2
File
numeric_al-2026.10.2-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details
numeric_al-2026.10.2-cp310-abi3-win32.whl CPython 3.10 abi3 Windows x86-32 Details
numeric_al-2026.10.2-cp310-abi3-musllinux_1_2_x86_64.whl CPython 3.10 abi3 Linux musl 1.2+ x86-64 Details
numeric_al-2026.10.2-cp310-abi3-musllinux_1_2_aarch64.whl CPython 3.10 abi3 Linux musl 1.2+ ARM64 Details
numeric_al-2026.10.2-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.2-cp310-abi3-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl CPython 3.10 abi3 Linux glibc 2.24+ ARM64, Linux glibc 2.28+ ARM64 Details
numeric_al-2026.10.2-cp310-abi3-macosx_11_0_x86_64.whl CPython 3.10 abi3 macOS 11.0+ x86-64 Details
numeric_al-2026.10.2-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details

Total release size: 11.4 MB

Release files / numeric_al-2026.10.2.tar.gz

Download URL numeric_al-2026.10.2.tar.gz
Size 29.0 kB
Tags Source
SHA-256 checksum
How to use checksums
ecf9eac9ac39e51f22b30c2730e11bf2b86d55c085c7425fa750f9f538161141
BLAKE2b-256 checksum
How to use checksums
7a7d7f4a63ff1f41dba294852870011842c62317fd64c2e32f6cf15083e215eb
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.2-cp310-abi3-win_amd64.whl

Download URL numeric_al-2026.10.2-cp310-abi3-win_amd64.whl
Size 406.2 kB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
d46fa87014a2cba3525c1ee0e0986220b180385c04d87d84532c5da92823b6cf
BLAKE2b-256 checksum
How to use checksums
f4120f0b3c825ad6bfc42ee4a186fa057162ff36efb3d11b317f76afeae5ddb2
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.2-cp310-abi3-win32.whl

Download URL numeric_al-2026.10.2-cp310-abi3-win32.whl
Size 385.0 kB
Tags CPython 3.10 Windows x86-32 abi3
SHA-256 checksum
How to use checksums
52acd93c3a63503c624bf9c99e9d302a73c650171fc6d9225416e2b214cd1448
BLAKE2b-256 checksum
How to use checksums
8c8b1c323444c862c9533ab757730e55ba2ebe1bbeda01684a2033cb5b316909
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.2-cp310-abi3-musllinux_1_2_x86_64.whl

Download URL numeric_al-2026.10.2-cp310-abi3-musllinux_1_2_x86_64.whl
Size 3.1 MB
Tags CPython 3.10 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
d4ef5489092e96cb6d77df68ef107f8331b0429d336c2eb219077797aa161dfd
BLAKE2b-256 checksum
How to use checksums
e18a7e05e919a986f371e24fe87ff45d88bc979004067fa86f3e7482c81b55d3
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.2-cp310-abi3-musllinux_1_2_aarch64.whl

Download URL numeric_al-2026.10.2-cp310-abi3-musllinux_1_2_aarch64.whl
Size 2.9 MB
Tags CPython 3.10 Linux musl 1.2+ ARM64 abi3
SHA-256 checksum
How to use checksums
20f6690f1fe46a2f6903a00c6e349d30cbe6a42ef4b111117c241d3967d1dc5e
BLAKE2b-256 checksum
How to use checksums
e0dc84b15481e1bb94870b814d7ff4094fe3ccda39ca1dfc25ee7b81c2942d68
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.2-cp310-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl

Download URL numeric_al-2026.10.2-cp310-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Size 2.1 MB
Tags CPython 3.10 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64 abi3
SHA-256 checksum
How to use checksums
33583d06be46f55b2d5067c6343be4daecf32e551a0743160e7e2ce3a7b513c7
BLAKE2b-256 checksum
How to use checksums
f4540a1bd4bae396388dec691ea4cf06239ff53b9c3caab8d8025e00fb79ec04
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.2-cp310-abi3-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl

Download URL numeric_al-2026.10.2-cp310-abi3-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
Size 2.0 MB
Tags CPython 3.10 Linux glibc 2.24+ ARM64 Linux glibc 2.28+ ARM64 abi3
SHA-256 checksum
How to use checksums
8cc779956f578789a2530e9f503084c6d40b7fb4cd454a23166c839e9d62c2c6
BLAKE2b-256 checksum
How to use checksums
2f02ca434bfff4d2678b7b1f2f19ae78fabcefec791a4c67e164c1f01e1c2fbc
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.2-cp310-abi3-macosx_11_0_x86_64.whl

Download URL numeric_al-2026.10.2-cp310-abi3-macosx_11_0_x86_64.whl
Size 257.9 kB
Tags CPython 3.10 abi3 macOS 11.0+ x86-64
SHA-256 checksum
How to use checksums
fdc7949ff3a3627cda924db39143b9b210cb2da0f166c5c4e56a14e4b500c828
BLAKE2b-256 checksum
How to use checksums
0dba5264de77f6c73d878c168f12530178a82c918194a7465b937dcd0d1efb45
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.2-cp310-abi3-macosx_11_0_arm64.whl

Download URL numeric_al-2026.10.2-cp310-abi3-macosx_11_0_arm64.whl
Size 234.4 kB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
d14659cc91b9691af747adb8a6dcbd12986a7078c2581ce35fe49cb4a018d367
BLAKE2b-256 checksum
How to use checksums
a28e8dc61c78f5af654ed16084e7025219dbbeb949a51a0ee81f0710e2057284
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