Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Rindow Math Matrix Laravel Package

rindow/rindow-math-matrix

Rindow Math Matrix is a PHP library for scientific matrix operations, providing N-dimensional arrays, broadcasting, BLAS, linear algebra, and machine learning functions. It integrates C/C++ libraries like OpenBLAS and CLBlast via FFI and supports GPU acceleration through OpenCL.

View on GitHub
Deep Wiki
Context7

Getting Started

rindow/rindow-math-matrix is essentially "NumPy for PHP": an N-dimensional array object plus broadcasting, BLAS bindings, linear algebra, and random number generation. It is the numerical foundation that rindow/rindow-neuralnetworks sits on, so it is proven in a real ML stack even though the package itself has only 13 stars and effectively no independent dependents.

Minimum setup:

composer require rindow/rindow-math-matrix
composer require rindow/rindow-math-matrix-matlibffi

The second line is not optional if you care about speed. Without a plugin driver the package runs in pure-PHP "Basic" mode, which is correct but roughly an order of magnitude slower. Then install the prebuilt binaries (Rindow-Matlib / OpenBLAS / CLBlast) linked from the rindow-math-matrix-matlibffi repo. PHP 8.1–8.4 are supported; 2.2.0 adds PHP 8.5 test coverage. Legacy PHP 7.x/8.0 users must stay on the 1.1.x line.

Verify the driver actually loaded before writing any code:

vendor/bin/rindow-math-matrix -v

The -v flag was added in 2.0.4 specifically to show the boot log when the driver fails to load and the service level silently drops to Basic. Bookmark that command — it is your first debugging step for every performance complaint.

Where to look first: the docs live at rindow.github.io/mathematics, not in the repository, so do not judge the package by its README. Inside the code, start at Rindow\Math\Matrix\MatrixOperator (the developer-facing facade) and drop into Rindow\Math\Matrix\LinearAlgebra only when you need buffer-level control. The release notes in release/ are the de-facto API changelog and are worth skimming for whichever functions you plan to use.

First real use case: replacing nested PHP loops for batch scoring or feature transforms. The canonical sample is:

use Rindow\Math\Matrix\MatrixOperator;

$mo = new MatrixOperator();
$a = $mo->array([[1,2],[3,4]]);
$b = $mo->array([[2,3],[4,5]]);
echo $mo->toString($mo->cross($a,$b), indent:true)."\n";

That is enough to prove the install; a batch dot-product over 10k rows is enough to prove the value.

Implementation Patterns

Two layers, pick deliberately. MatrixOperator is the ergonomic wrapper (array(), toString(), cross(), zeros()) and is what you want 90% of the time. LinearAlgebra is the low-level service operating on NDArray objects with explicit dtypes and output buffers. Mixing them casually is the most common source of confusion — decide per class whether you are in "friendly" or "buffer" land.

Pin your dtypes explicitly. Since 2.0, array() no longer auto-detects type; the default is float32. Any code doing money-ish, scientific, or integer-index work must pass dtype: NDArray::float64 or int32. Treat an unqualified array() call as a code smell in review.

Broadcast instead of looping. The package supports NumPy-style broadcasting; a row-wise normalization should be $x / $mean on a [N,1] operand, not a foreach. This is where the speedup and the readability both come from.

Reuse output buffers in hot loops. BLAS-style functions accept an output buffer (gemm, matmul). In an inference or training loop, allocate once outside the loop and pass the same NDArray in. This avoids the per-iteration allocation that otherwise dominates PHP-level runtime.

Reproducibility. Use setSeed() (added in 2.2.0) plus randInt()/randomUniform()/randomNormal()/randomCategorical(). Seed in your service constructor, not in a test helper, so training runs are reproducible by config rather than by accident.

Shape gymnastics. expandDims/squeeze for rank fixes, gatherb/masking/where for selection, einsum for arbitrary contractions and einsum4p1 when you specifically have 4+1 dimensional attention-shaped tensors and need the fast path. slice/stack/concat/split cover the recurrent-network style plumbing.

GPU when the laptop has no NVIDIA. laAccelerated('clblast', ['deviceType'=>'GPU']) routes through OpenCL and works on Intel/AMD iGPUs. Wrap driver selection behind a config value (math.driver) so CI and local dev can force Basic mode and stay deterministic.

Laravel integration. Bind MatrixOperator in a service provider, but instantiate per queued job rather than sharing a singleton across long-lived workers — the object carries a LinearAlgebra instance with driver state and RNG state. Put heavy computation in jobs, never in the request cycle; a 2000×2000 gemm is still a request-killer even accelerated.

Persistence caution. The serialization format changed in 2.0 (class names replaced by keywords). Do not let cached/serialized NDArrays cross a major-version upgrade; re-derive them or store raw arrays instead.

Gotchas and Tips

The silent downgrade to Basic mode is the number one trap. Nothing throws — you just get slow code. Every deployment should assert the service level at boot, and vendor/bin/rindow-math-matrix -v is the diagnostic. Also check ffi.enable in php.ini, since 2.0 made FFI the default access path and a disabled FFI quietly costs you everything.

macOS is degraded. Because of an issue in rindow-math-buffer-ffi, macOS currently only supports PHP-only Basic mode. If your team is on MacBooks, plan for Linux or WSL for anything performance-sensitive, and expect your Mac devs to see different timings than CI.

Fractional indexing semantics changed. Version 1 treats [0,4] as elements 0 through 4; version 2 treats [0,5] as the equivalent. Legacy NDArrayPhp::$rangeStyle / RANGE_STYLE_1 exist, but the clean fix is to use the explicit R(0,5) helper so intent is unambiguous regardless of global state.

Device selection options are mutually exclusive. 'device' => '0,1' means platform 0, device 1; 'deviceType' => 'GPU' means the first GPU. Passing both is invalid (clarified in 1.2.4 after a typo in the original option names).

gather()/reduceGather() warn rather than throw since 1.2.2, which was a deliberate workaround but means malformed indices can produce garbage silently. Validate index ranges yourself before calling.

Complex numbers are BLAS-only. You cannot rely on complex support across the general function surface, and as a consequence amax/amin return the absolute value when complex types are in play. Do not use them as a drop-in for "find the max coefficient".

Preview functions can vanish. topk and gathernd are explicitly marked preview; keep them behind a thin wrapper so a minor-version bump cannot ripple through your codebase.

Zero-dimensional arrays as scalars in offsetSet only works from 2.2.0. If you support older pins, guard that pattern.

Debug by differential testing. For anything non-trivial, generate the expected result in NumPy once, commit it as a fixture, and assert with isclose(). toString()/shapeToString()/dtypeToString() (2.2.0) make failure messages readable; isfinite/isinf/isnan catch the NaN propagation that PHP's loose typing otherwise hides.

Abandoned old-extension path. The rindow_openblas/rindow_opencl/rindow_clblast PHP extensions still exist but are explicitly "not actively updated." Build new work on the FFI plugin; treat the extension as a fallback for hosts where FFI is unavailable.

Vendor risk is real. BSD-3-Clause is friendly, but the bus factor is roughly one maintainer, the docs live off-repo, and the API has broken compatibility across 1.x → 2.x (default dtype, range syntax, serialization). Isolate the library behind a small internal interface — a MatrixOps contract with a handful of methods — so a future swap to the extension driver, a different library, or an out-of-process Python service is a contained change rather than a rewrite.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support