Skip to content

LinearAlgebra Missing Support #621

Description

@Nucs

Overview

NumSharp implements only a small corner of NumPy's linear algebra surface. The
matrix/vector products exist, but the entire LAPACK-backed core of numpy.linalg
— decompositions, eigenvalues, equation-solving, matrix inversion, determinants, and
norms — is absent, and there is no np.linalg namespace at all. This issue tracks the
gap and proposes building np.linalg out.

Problem

NumPy's "linear algebra" is really two surfaces:

  • numpy.linalg31 functions (+ the LinAlgError exception), almost all
    backed by LAPACK/BLAS (numpy/linalg/umath_linalg.cpp).
  • Matrix/vector products in the main np.* namespacedot, matmul, inner,
    outer, vdot, tensordot, einsum, kron, cross (NumPy 2.x re-exports several
    of these inside np.linalg for Array-API conformance).

NumSharp currently ships ~7 of ~40 of these routines and none of the
LAPACK-heavy core. Porting real ML / scientific code stalls immediately on norm,
inv, solve, lstsq, eig, svd, det — the most common calls — and there is no
np.linalg namespace for them to live in.

Background: the former NDArray.inv / qr / svd / lstqr / multi_dot methods were
non-functional stubs (each return null; / return default;), including a misspelled
lstqr (NumPy's is lstsq, returning a 4-tuple) and a wrong-shape multi_dot (NumPy
takes a sequence). They were mis-homed on NDArray (in NumPy these are np.linalg
module functions, never ndarray methods) and have been removed rather than left
as silent null-returning traps. This issue tracks implementing them correctly under
np.linalg.

Current coverage (final state)

Grouped by NumPy's own routines.linalg categories:

NumPy category Implemented in NumSharp Missing
Matrix & vector products dot, matmul, outer inner, vdot, vecdot, tensordot, einsum/einsum_path, kron, cross, linalg.multi_dot
Decompositions cholesky, qr, svd, svdvals
Matrix eigenvalues eig, eigh, eigvals, eigvalsh
Norms & other numbers trace, diagonal norm, matrix_norm, vector_norm, det, slogdet, cond, matrix_rank
Solving & inverting solve, lstsq, inv, pinv, tensorsolve, tensorinv
Matrix functions / transpose matrix_power, matrix_transpose, .T/transpose/swapaxes

Bottom line: every LAPACK-backed routine (all decompositions, all eigenvalues, all
solve/inverse/det, and all norms) is missing. What exists is only what can be expressed
with the existing elementwise/reduction/matmul kernels.

Proposal

  1. Introduce a np.linalg namespace mirroring numpy.linalg (np.linalg.inv(a),
    np.linalg.svd(a), …), instead of bolting functions onto NDArray. Add the
    LinAlgError type (NumPy raises it for singular matrices, non-convergence, etc.).
  2. Choose a backend for the LAPACK-heavy core — hand-writing SVD/QR/eig is a poor
    use of effort. Candidates (decide before implementing):
    • MathNet.Numerics — fully managed, easy, portable; slower.
    • OpenBLAS / LAPACKE via P/Invoke — native, fastest, matches NumPy; adds a native
      dependency + per-RID packaging.
  3. Implement in dependency order: products (pure kernels) → norms/det (reductions +
    an LU) → decompositions (qr/svd/cholesky) → eigenvalues → solve/inverse/lstsq/pinv
    (built on the decompositions).

Task checklist

Infra

  • Create the np.linalg static namespace + LinAlgError
  • Select and wire the LAPACK backend (MathNet vs OpenBLAS P/Invoke)
  • Alias existing dot/matmul/outer/trace/diagonal/matrix_power/matrix_transpose into np.linalg where NumPy 2.x also exposes them

Products & contractions (main np.* namespace)

Decompositions

  • linalg.cholesky
  • linalg.qr
  • linalg.svd
  • linalg.svdvals

Eigenvalues

  • linalg.eig
  • linalg.eigh
  • linalg.eigvals
  • linalg.eigvalsh

Norms & other numbers

Solving & inverting

Evidence

  • numpy.linalg.__all__ = 31 functions + LinAlgError (verified against NumPy 2.4.2
    numpy/linalg/_linalg.py): matrix_power, solve, tensorsolve, tensorinv, inv, cholesky, eigvals, eigvalsh, pinv, slogdet, det, svd, svdvals, eig, eigh, lstsq, norm, qr, cond, matrix_rank, multi_dot, trace, diagonal, cross, outer, tensordot, matmul, matrix_transpose, matrix_norm, vector_norm, vecdot.
  • These are LAPACK-backed in NumPy (umath_linalg.cpp), which is why they were never
    hand-ported to pure C#.
  • Several standing issues already request individual pieces (see Related), showing real
    user demand.
  • Real-world usage ranking (GitHub code search) — each missing routine was counted
    across public GitHub code to prioritize by demand (full table below). np.linalg.norm
    dominates by ~4×, and the top tier matches the "most common calls" named under
    Problem.

Usage across GitHub (prioritization signal)

Each missing routine was counted via GitHub REST code search
(gh api search/codetotal_count) in its canonical call form — np.<fn>( for the
main-namespace products, np.linalg.<fn>( for the linalg routines. The trailing (
counts real call sites and disambiguates prefixes (otherwise np.linalg.eig also swallows
eigh/eigvals/eigvalsh, svd swallows svdvals, inv swallows pinv).

np.linalg.norm dominates — ~305K hits, ~4× the runner-up (inv) and more than the
entire bottom half of the list combined. The top tier — norm → inv → cross → einsum →
det → solve → svd
— lines up with the "most common calls" named under Problem and
corroborates the standing norm requests (#239 / #441 / #485). This argues for an
impact-ordered build: norm first, then inv / det / solve / svd.

# Function Approx. GitHub hits
1 np.linalg.norm 304,640
2 np.linalg.inv 78,720
3 np.cross 56,736
4 np.einsum 35,456
5 np.linalg.det 29,584
6 np.linalg.solve 27,808
7 np.linalg.svd 25,312
8 np.linalg.lstsq 22,192
9 np.linalg.pinv 19,792
10 np.linalg.eig 17,936
11 np.kron 17,488
12 np.linalg.eigh 15,456
13 np.linalg.matrix_rank 10,680
14 np.linalg.matrix_norm 10,328
15 np.linalg.cholesky 10,160
16 np.linalg.eigvalsh 10,128
17 np.linalg.vector_norm 9,160
18 np.linalg.eigvals 8,288
19 np.tensordot 7,712
20 np.inner 7,688
21 np.linalg.qr 7,008
22 np.vdot 5,888
23 np.linalg.cond 4,800
24 np.linalg.multi_dot 4,720
25 np.linalg.slogdet 4,528
26 np.vecdot 2,436
27 np.linalg.tensorinv 1,672
28 np.linalg.tensorsolve 1,656
29 np.einsum_path 1,564
30 np.linalg.svdvals 1,392

Method: GitHub REST code-search total_count is an approximate estimate (noisy
±~10% on large result sets; re-queries drift) and counts only the dominant np. alias —
not numpy.linalg.… or from numpy.linalg import …. Those add roughly constant multipliers,
so the ranking is stable even though the absolute numbers are not exact. Measured 2026-07-19.

Scope / Non-goals

  • Not reintroducing the deleted null-returning stubs.
  • FFT (numpy.fft) is out of scope — separate module (Implement numpy.fft.fft #114).
  • einsum may be split into its own issue given its size/complexity.
  • This issue is about API existence + NumPy-correct behavior; SIMD/perf tuning of the
    new routines is follow-up work.

Related issues

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    NumPy 2.x ComplianceAligns behavior with NumPy 2.x (NEPs, breaking changes)apiPublic API surface (np.*, NDArray methods, operators)coreInternal engine: Shape, Storage, TensorEngine, iteratorsenhancementNew feature or requestmissing feature/sNumPy function not yet implemented in NumSharp

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions