packages feed

linear-massiv-0.1.0.0: src/Numeric/LinearAlgebra/Massiv.hs

-- |
-- Module      : Numeric.LinearAlgebra.Massiv
-- Copyright   : (c) Nadia Chambers 2026
-- License     : BSD-3-Clause
-- Maintainer  : nadia.chambers@iohk.io
-- Stability   : experimental
--
-- @linear-massiv@: Type-safe numerical linear algebra backed by
-- <https://hackage.haskell.org/package/massiv massiv> arrays.
--
-- This library provides native Haskell implementations of algorithms from:
--
-- * Golub, G. H., & Van Loan, C. F. (2013). /Matrix Computations/ (4th ed.).
--   Johns Hopkins University Press. ISBN 978-1-4214-0794-4.
--
-- referred to throughout as __GVL4__.
--
-- = Derived Work Attribution
--
-- This code was co-authored by Claude Opus (Anthropic) and should be
-- considered a derived work of the various algorithmic examples and
-- reference implementations drawn upon during development, including but
-- not limited to:
--
-- * __LAPACK__ (Linear Algebra PACKage) — Anderson, E. et al. (1999).
--   /LAPACK Users' Guide/, 3rd ed., SIAM. The LAPACK testing methodology,
--   algorithm structures, and numerical stability techniques informed much
--   of the implementation.
--
-- * __OpenBLAS__ — Xianyi, Z., Qian, W., and Yunquan, Z. (2011--).
--   The tiled GEMM micro-kernel architecture, cache-blocking strategies,
--   and SIMD vectorisation patterns were inspired by OpenBLAS.
--
-- * __GVL4__ — The primary algorithmic reference, as noted above.
--
-- * __Higham__ — Higham, N. J. (2002). /Accuracy and Stability of Numerical
--   Algorithms/, 2nd ed., SIAM. Error analysis and numerical stability
--   frameworks.
--
-- = Design Principles
--
-- 1. __Type-level dimensional safety__: Matrix dimensions are tracked in the
--    type system via GHC @DataKinds@ and @KnownNat@ constraints. Dimensionally
--    incorrect operations (e.g., multiplying an \(m \times k\) matrix by an
--    \(n \times p\) matrix where \(k \neq n\)) are rejected at compile time.
--
-- 2. __Representation polymorphism__: All operations are parametric over
--    massiv's array representation @r@ (e.g., @P@ for primitive, @U@ for
--    unboxed, @S@ for storable, @B@ for boxed), constrained by
--    @'Data.Massiv.Array.Manifest' r e@. Users choose the representation at
--    the call site.
--
-- 3. __Parallelism via massiv__: Operations that construct arrays via
--    @makeArray@ inherit massiv's computation strategies. Use 'matMulComp'
--    with @Par@ or @ParN n@ for parallel matrix multiplication.
--
-- 4. __No FFI__: All algorithms are pure Haskell, enabling portability and
--    auditability. Benchmarks compare performance across massiv representations
--    and parallelism strategies.
--
-- = Internal Architecture: Two-Layer Design
--
-- @linear-massiv@ uses a two-layer architecture that separates the type-safe
-- public API from the performance-critical internal representation:
--
-- * __Public layer__: 'Matrix' and 'Vector' are @newtype@ wrappers around
--   massiv's @Array r Ix2 e@, providing compile-time dimension checking via
--   phantom @Nat@ parameters and representation polymorphism via @r@.
--
-- * __Internal layer__: Performance-critical inner loops (GEMM, QR,
--   tridiagonalisation, SVD, etc.) unwrap the massiv array to a raw
--   @ByteArray#@ \/ @MutableByteArray#@ and operate directly via GHC primops,
--   including @DoubleX4#@ AVX2 SIMD instructions compiled through the LLVM 17
--   backend.  Functions receive @(ByteArray, offset, stride)@ triples, enabling
--   zero-copy submatrix views for panel factorisations.
--
-- This separation is essential for performance.  Benchmarks (Round 3 of the
-- accompanying report) showed that massiv's per-element @M.readM@\/@M.write_@
-- abstraction layer imposed a 240–330× penalty on BLAS operations relative to
-- direct primop access, even though the underlying memory layout is identical.
-- The raw primop layer eliminates this overhead while the @newtype@ wrapper
-- preserves type safety at the API boundary.
--
-- == Why not @vector-sized@ or @linear@'s @V@?
--
-- The @<https://hackage.haskell.org/package/vector-sized vector-sized>@ package
-- provides an @Unbox (Vector n a)@ instance that stores
-- @Vector m (Vector n Double)@ as a contiguous flat @ByteArray@ of @m × n@
-- doubles.  While the __memory layout__ is correct, contiguous memory alone is
-- insufficient for high-performance numerical kernels:
--
-- * __Per-element typeclass dispatch__: Every access goes through
--   @basicUnsafeRead@ \/ @basicUnsafeWrite@ of the @Unbox@ data family.
--   Reading element @(i, j)@ requires indexing the outer vector to obtain a
--   @Vector n Double@ (constructing an intermediate slice), then indexing that.
--   @linear-massiv@ computes @off + i * stride + j@ and issues a single
--   @readDoubleArray#@ primop.
--
-- * __No SIMD access__: The 4×8 GEMM micro-kernel loads 4 consecutive doubles
--   via @indexDoubleArrayAsDoubleX4# ba# (off# +# i#)@—a direct 256-bit AVX2
--   load from a computed byte offset.  The @Unbox@ typeclass does not expose
--   the underlying @ByteArray#@, and GHC cannot optimise through the data
--   family indirection to produce equivalent code.
--
-- * __No mutable primop access__: In-place factorisations (LU, QR,
--   tridiagonalisation, bidiagonalisation) require @writeDoubleArray#@ on
--   @MutableByteArray#@ with computed offsets.  The @MVector@ abstraction
--   interposes allocation and function calls that prevent the tight unboxed
--   loops needed for competitive performance.
--
-- * __No zero-copy submatrix views__: Panel factorisations pass
--   @(ByteArray, offset, stride)@ triples to kernels, enabling zero-copy views
--   into submatrices.  @Vector n a@ does not naturally express "this row starts
--   at byte offset X in a larger backing array."
--
-- The @<https://hackage.haskell.org/package/linear linear>@ library's @V n a@
-- uses @Vector@ from the @vector@ package internally and is designed for small
-- fixed-size vectors (V2–V4) where GHC can fully unbox everything.  At
-- @n = 100–500@, @V n (V m Double)@ would be a vector-of-vectors with per-row
-- indirection—catastrophic for cache locality and SIMD vectorisation.
-- @linear-massiv@ provides conversion functions ('fromLinearV', 'fromV2', etc.)
-- in "Numeric.LinearAlgebra.Massiv.Linear" for interoperability.
--
-- = Quick Start
--
-- @
-- import Numeric.LinearAlgebra.Massiv
-- import qualified Data.Massiv.Array as M
--
-- -- Create a 3x3 matrix (Primitive representation, Double elements)
-- let a = 'makeMatrix' \@3 \@3 \@M.P $ \\i j ->
--           fromIntegral (i * 3 + j + 1) :: Double
--
-- -- QR factorization
-- let (q, r) = 'qr' a
--
-- -- Solve Ax = b via LU
-- let b = 'makeVector' \@3 \@M.P $ \\i -> fromIntegral (i + 1) :: Double
-- let x = 'luSolve' a b
-- @
--
-- = Module Organisation
--
-- == Core types and construction
--
-- * "Numeric.LinearAlgebra.Massiv.Types" — 'Matrix', 'Vector' newtypes with
--   phantom dimension parameters
-- * "Numeric.LinearAlgebra.Massiv.Internal" — Unsafe constructors, dimension
--   reification, array creation helpers
--
-- == BLAS-like operations (GVL4 Ch. 1)
--
-- * "Numeric.LinearAlgebra.Massiv.BLAS.Level1" — Vector–vector: 'dot', 'axpy', 'scal', 'nrm2'
-- * "Numeric.LinearAlgebra.Massiv.BLAS.Level2" — Matrix–vector: 'gemv', 'matvec', 'ger'
-- * "Numeric.LinearAlgebra.Massiv.BLAS.Level3" — Matrix–matrix: 'gemm', 'matMul', 'transpose'
--
-- == Direct solvers (GVL4 Chs. 3–4)
--
-- * "Numeric.LinearAlgebra.Massiv.Solve.Triangular" — Forward\/back substitution
-- * "Numeric.LinearAlgebra.Massiv.Solve.LU" — LU with partial pivoting
-- * "Numeric.LinearAlgebra.Massiv.Solve.Cholesky" — Cholesky for SPD matrices
-- * "Numeric.LinearAlgebra.Massiv.Solve.Banded" — Band LU, band Cholesky, tridiagonal solver
--
-- == Orthogonal factorizations (GVL4 Ch. 5)
--
-- * "Numeric.LinearAlgebra.Massiv.Orthogonal.Householder" — Householder reflections
-- * "Numeric.LinearAlgebra.Massiv.Orthogonal.Givens" — Givens rotations
-- * "Numeric.LinearAlgebra.Massiv.Orthogonal.QR" — QR factorization (Householder and Givens)
-- * "Numeric.LinearAlgebra.Massiv.Orthogonal.LeastSquares" — Least squares via QR
--
-- == Eigenvalue problems and SVD (GVL4 Chs. 7–8)
--
-- * "Numeric.LinearAlgebra.Massiv.Eigen.Power" — Power, inverse, Rayleigh quotient iteration
-- * "Numeric.LinearAlgebra.Massiv.Eigen.Hessenberg" — Hessenberg reduction
-- * "Numeric.LinearAlgebra.Massiv.Eigen.Schur" — Schur decomposition (QR algorithm)
-- * "Numeric.LinearAlgebra.Massiv.Eigen.Symmetric" — Symmetric eigenvalue (tridiagonal QR, Jacobi)
-- * "Numeric.LinearAlgebra.Massiv.Eigen.SVD" — Singular value decomposition
--
-- == Norms and condition numbers (GVL4 Ch. 2)
--
-- * "Numeric.LinearAlgebra.Massiv.Norms" — Frobenius, 1-, \(\infty\)-, and 2-norms
--
-- == Integration with the @linear@ library
--
-- * "Numeric.LinearAlgebra.Massiv.Linear" — Conversions to\/from @linear@'s @V@, @V2@, @V3@, @V4@
module Numeric.LinearAlgebra.Massiv
  ( -- * Core types
    module Numeric.LinearAlgebra.Massiv.Types
    -- * Construction helpers
  , module Numeric.LinearAlgebra.Massiv.Internal
    -- * BLAS operations
  , module Numeric.LinearAlgebra.Massiv.BLAS.Level1
  , module Numeric.LinearAlgebra.Massiv.BLAS.Level2
  , module Numeric.LinearAlgebra.Massiv.BLAS.Level3
    -- * Direct solvers
  , module Numeric.LinearAlgebra.Massiv.Solve.Triangular
  , module Numeric.LinearAlgebra.Massiv.Solve.LU
  , module Numeric.LinearAlgebra.Massiv.Solve.Cholesky
  , module Numeric.LinearAlgebra.Massiv.Solve.Banded
    -- * Orthogonal factorizations
  , module Numeric.LinearAlgebra.Massiv.Orthogonal.Householder
  , module Numeric.LinearAlgebra.Massiv.Orthogonal.Givens
  , module Numeric.LinearAlgebra.Massiv.Orthogonal.QR
  , module Numeric.LinearAlgebra.Massiv.Orthogonal.LeastSquares
    -- * Eigenvalue problems
  , module Numeric.LinearAlgebra.Massiv.Eigen.Power
  , module Numeric.LinearAlgebra.Massiv.Eigen.Hessenberg
  , module Numeric.LinearAlgebra.Massiv.Eigen.Schur
  , module Numeric.LinearAlgebra.Massiv.Eigen.Symmetric
  , module Numeric.LinearAlgebra.Massiv.Eigen.SVD
    -- * Norms
  , module Numeric.LinearAlgebra.Massiv.Norms
    -- * Linear integration
  , module Numeric.LinearAlgebra.Massiv.Linear
  ) where

import Numeric.LinearAlgebra.Massiv.Types
import Numeric.LinearAlgebra.Massiv.Internal
import Numeric.LinearAlgebra.Massiv.BLAS.Level1
import Numeric.LinearAlgebra.Massiv.BLAS.Level2
import Numeric.LinearAlgebra.Massiv.BLAS.Level3
import Numeric.LinearAlgebra.Massiv.Solve.Triangular
import Numeric.LinearAlgebra.Massiv.Solve.LU
import Numeric.LinearAlgebra.Massiv.Solve.Cholesky
import Numeric.LinearAlgebra.Massiv.Solve.Banded
import Numeric.LinearAlgebra.Massiv.Orthogonal.Householder
import Numeric.LinearAlgebra.Massiv.Orthogonal.Givens
import Numeric.LinearAlgebra.Massiv.Orthogonal.QR
import Numeric.LinearAlgebra.Massiv.Orthogonal.LeastSquares
import Numeric.LinearAlgebra.Massiv.Eigen.Power
import Numeric.LinearAlgebra.Massiv.Eigen.Hessenberg
import Numeric.LinearAlgebra.Massiv.Eigen.Schur
import Numeric.LinearAlgebra.Massiv.Eigen.Symmetric
import Numeric.LinearAlgebra.Massiv.Eigen.SVD
import Numeric.LinearAlgebra.Massiv.Norms
import Numeric.LinearAlgebra.Massiv.Linear