Skip to content

TesseroPHP, Serious math, without leaving PHP

Numerical computing for PHP 8.2+

Tessero, Scientific & Numerical Library for PHP

N-dimensional arrays, linear algebra, FFT, NumPy-identical random numbers, sparse matrices, optimisation and mixed-integer programming, on one small SIMD C kernel, with results matched against NumPy and SciPy to full parity and re-checked by an independent BCMath oracle.

$ composer config repositories.tessero vcs https://github.com/DMJ-CV-91913/tessero

$ composer require tessero/tessero:dev-main

$ vendor/bin/tessero build

$ vendor/bin/tessero doctor

Tessero is not on Packagist yet and has no tagged release, so there are no prebuilt binaries. These commands install the main branch from GitHub; the build step needs a C compiler. Install guide

Tessero 0.2.0 released 2026-09-26 see what's new →

A quick taste

Operators, broadcasting and solvers, in PHP.

Work with arrays the way you would in NumPy: element-wise maths, boolean masks, reshaping and reductions, plus SciPy-style optimisation. One C kernel drives both backends, so the exact same numbers come back whether you run the FFI package or the native Zend extension.

Browse more examples →

peak-load.php
use Tessero\Ext\NDArray;         // native extension: operators & masks
use Tessero\Ext\Engine;

$load = NDArray::array($hourlyLoad);            // PHP array -> float64
$z    = ($load - $load->mean()) / $load->std(); // operators, broadcasting
$peak = $load[$z->gt(2.0)];                     // boolean mask
$day  = $load->reshape(-1, 24)->mean(0);        // hour-of-day profile

$plan = Engine::linprog([-40, -30], [[2, 1], [1, 1]], [100, 80]);
$plan['x'];       // [20, 60]
$plan['ineqlin']; // shadow prices [-10, -20], SciPy's convention
Native-extension syntax above (operators and masks). With the FFI package the same program uses Tessero\NDArray and Tessero\Optimize\LinearProgramming::linprog($c, $A_ub, $b_ub), which returns the identical result array (['x' => ..., 'fun' => ..., 'ineqlin' => ...]).

1,554 / 1,560

kernel functions verified on both backends. FFI and the native Zend extension return identical numbers.

100.0%

of NumPy core, fully covered and verified symbol by symbol on both backends, with non-numeric and non-deterministic symbols transparently excluded.

100.0%

of SciPy, fully covered and verified symbol by symbol on both backends, with non-numeric and non-deterministic symbols transparently excluded.

Every figure here is generated from the library's coverage report, never hand-typed.

See the full NumPy & SciPy coverage report →

Checked three independent ways.

Every symbol is compared to NumPy and SciPy on both backends. Core scalar and combinatorial functions are re-derived from first principles by an independent BCMath oracle, a second correctness check that shares no code with the kernel. And real multi-step workflows are run end to end on both backends, so compositions are verified, not just functions in isolation. The workflow checks are representative, not exhaustive.

Coverage by module

Module In scope FFI Extension
NumPy core 683 683 (100.0 %) 683 (100.0 %)
numpy 340 340 (100.0 %) 340 (100.0 %)
numpy.ndarray 56 56 (100.0 %) 56 (100.0 %)
numpy.linalg 31 31 (100.0 %) 31 (100.0 %)
numpy.fft 18 18 (100.0 %) 18 (100.0 %)
numpy.polynomial 6 6 (100.0 %) 6 (100.0 %)
numpy.polynomial.polynomial 28 28 (100.0 %) 28 (100.0 %)
numpy.polynomial.chebyshev 33 33 (100.0 %) 33 (100.0 %)
numpy.polynomial.legendre 31 31 (100.0 %) 31 (100.0 %)
numpy.polynomial.laguerre 31 31 (100.0 %) 31 (100.0 %)
numpy.polynomial.hermite 31 31 (100.0 %) 31 (100.0 %)
numpy.polynomial.hermite_e 31 31 (100.0 %) 31 (100.0 %)
numpy.random 4 4 (100.0 %) 4 (100.0 %)
numpy.random.Generator 43 43 (100.0 %) 43 (100.0 %)
SciPy 1497 1497 (100.0 %) 1497 (100.0 %)
scipy.special 336 336 (100.0 %) 336 (100.0 %)
scipy.stats 296 296 (100.0 %) 296 (100.0 %)
scipy.linalg 92 92 (100.0 %) 92 (100.0 %)
scipy.fft 35 35 (100.0 %) 35 (100.0 %)
scipy.optimize 65 65 (100.0 %) 65 (100.0 %)
scipy.integrate 28 28 (100.0 %) 28 (100.0 %)
scipy.interpolate 54 54 (100.0 %) 54 (100.0 %)
scipy.signal 156 156 (100.0 %) 156 (100.0 %)
scipy.signal.windows 26 26 (100.0 %) 26 (100.0 %)
scipy.sparse 38 38 (100.0 %) 38 (100.0 %)
scipy.sparse.linalg 33 33 (100.0 %) 33 (100.0 %)
scipy.sparse.csgraph 22 22 (100.0 %) 22 (100.0 %)
scipy.spatial 15 15 (100.0 %) 15 (100.0 %)
scipy.spatial.distance 27 27 (100.0 %) 27 (100.0 %)
scipy.cluster.vq 4 4 (100.0 %) 4 (100.0 %)
scipy.cluster.hierarchy 32 32 (100.0 %) 32 (100.0 %)
scipy.ndimage 75 75 (100.0 %) 75 (100.0 %)
scipy.constants 163 163 (100.0 %) 163 (100.0 %)

Generated from the library's coverage report, full tables & translation reference →

Parity, and past it

Beyond NumPy and SciPy

The coverage above is measured against NumPy and SciPy's own surface, so it stops at 100%. Tessero also ships numerics those libraries do not have.

Reproducible f32 functions

rsqrt, exp2, exp, erf, recip and tanh are built only from correctly-rounded f32 operations, so each returns one defined bit pattern, identical across SIMD level, thread count and CPU architecture. On top of them sit the composites sigmoid, gelu_tanh, softmax, rmsnorm and layernorm and their gradients. np.exp and scipy.special.erf give you a correct value; they do not promise the same bits on different hardware. These do, and each is pinned to a golden SHA-256 so any build can prove it reproduces the exact bytes. Primitive, composite and gradient goldens are all confirmed on two independent hosts.

One result, every machine

The CPU result is the canonical one, so the same model evaluated on a laptop and in a data centre agrees exactly, not just to a tolerance. Talario's GPU kernels mirror these definitions and match them bit for bit on NVIDIA A10, A100 and H100 PCIe, attested at 1024 x 1024; other GPUs are not yet attested. IEEE pins +, * and fused multiply-add, but not exp or erf, so building them from the pinned operations is what makes the whole result reproducible.

Measured, not asserted

BLAS-class speed, on both backends

Dense matrix multiplication routes through OpenBLAS, so heavy linear algebra runs at BLAS-class throughput. On a commodity Intel i7-4790, routing matmul through OpenBLAS is roughly 17x faster at four threads, and about 9x single-threaded. Both backends share one C kernel, so they measure the same. The benchmark is committed and reproducible, run back to back in one process with the hardware stated.

See the benchmarks →

Works with your stack

What you can build

Tessero reproduces the numerical core that real scientific Python relies on, so the patterns behind scikit-learn, pandas, statsmodels, astropy, networkx, librosa and PyMC can run in native PHP: standardize and reduce feature matrices, fit and evaluate models, run FFTs and signal pipelines, solve linear and mixed-integer programs, and more. Usage-weighted parity across an 18-package corpus means the calls real code makes are the calls Tessero verifies.

API reference

Every class, function and signature

Browse the full, NumPy/SciPy-mapped API, generated from the library itself.

Open the API reference →

API tokens

Personal access tokens

Signed-in members can mint scoped tokens for scripts and CI from the members area.

Manage API tokens →

Mission

Tessero's mission is to make PHP a first-class language for numerical and scientific computing. We provide numerically identical NumPy and SciPy arrays, statistics, linear algebra and optimization for PHP, with full verified parity against the reference implementations measured from recorded test runs. We build in the open, credit the work we stand on, and work with the wider PHP community so that the libraries, frameworks and applications PHP developers already use can do serious numerical work in native PHP, with no call-out to Python, running the same C kernel through either a compiler-free package or a native extension.

Read more about the project →