Decompositions
Overview
Matrix decomposition is the process of expressing a matrix as a product of structured factors that are easier to analyze, invert, or solve against. In numerical computing, decompositions are the backbone of stable algorithms for linear systems, least-squares fitting, eigenvalue workflows, dimensionality reduction, and matrix function evaluation. Rather than operating directly on a dense matrix A, decomposition methods expose geometric and algebraic structure such as orthogonality, triangular form, or singular directions. This structure improves both computational efficiency and numerical robustness in data science, optimization, and scientific engineering.
The unifying idea is to rewrite A so that expensive operations become cheap on the factors. For example, triangular factors support fast substitution, orthogonal/unitary factors preserve norms and reduce error amplification, and diagonal-like factors reveal spectral content. Common identities include A=PLU, A=QR, and A=U\Sigma V^*, each emphasizing a different property of the same linear map. In practice, factorization choice depends on matrix properties: symmetry, definiteness, conditioning, sparsity, and whether the goal is solving, compression, or eigen-analysis.
These tools are implemented with SciPy Linear Algebra, especially routines from scipy.linalg, with NumPy arrays as the underlying data model. SciPy wraps mature LAPACK/BLAS kernels, providing well-tested, high-performance decompositions suitable for both teaching examples and production numerical pipelines.
For positive-definite and general system solving, CHOLESKY, LDL, and LU provide complementary triangular factorizations. CHOLESKY is typically the fastest and most stable option for symmetric positive-definite matrices because it exploits symmetry and avoids pivoting in well-behaved cases. LDL extends triangular-style factorization to symmetric (or Hermitian) matrices that may be indefinite, separating scaling/sign information into the block-diagonal D. LU is the broad-purpose workhorse for generic square systems via permutation and triangular factors, and it is widely used in direct solvers, determinant workflows, and condition diagnostics.
For orthogonal reductions and eigenvalue-oriented workflows, QR, HESSENBERG, and SCHUR are tightly connected. QR decomposes a matrix into an orthogonal/unitary basis and an upper-triangular factor, making it central to least-squares problems and numerically stable basis construction. HESSENBERG reduces a dense matrix to near-triangular form as a standard preprocessing step before iterative eigenvalue methods. SCHUR then represents a matrix as A=ZTZ^* with quasi-triangular T, giving a numerically robust alternative to explicit diagonalization for spectral computations and matrix functions.
For geometric decomposition and low-rank structure, POLAR and SVD expose complementary views of matrix action. POLAR splits A into a unitary/orthogonal factor and a positive-semidefinite factor, separating pure rotation/reflection from stretch and making it useful in continuum mechanics, computer vision, and shape analysis. SVD provides the canonical decomposition A=U\Sigma V^*, directly ranking latent directions by singular values and enabling denoising, PCA-style compression, pseudoinverse construction, and ill-posed inverse problem regularization. Together, these methods support both interpretable modeling and numerically controlled approximations across modern linear-algebra-heavy applications.
CHOLESKY
The Cholesky decomposition factors a symmetric positive-definite matrix into a product of a lower-triangular matrix and its transpose. It is a numerically efficient method for solving linear systems and for computing matrix square roots.
For a matrix A, the decomposition yields:
A = LL^T \qquad \text{or} \qquad A = U^TU
depending on whether the lower or upper triangular factor is requested.
Excel Usage
=CHOLESKY(matrix, lower)
matrix(list[list], required): Real symmetric positive-definite matrix to factor (must be square)lower(bool, optional, default: false): If TRUE, return lower-triangular factor L; if FALSE, return upper-triangular factor U
Returns (list[list]): 2D Cholesky factor matrix, or error message string.
Example 1: Lower-triangular Cholesky factor of 2x2 matrix
Inputs:
| matrix | lower | |
|---|---|---|
| 4 | 12 | true |
| 12 | 37 |
Excel formula:
=CHOLESKY({4,12;12,37}, TRUE)
Expected output:
| Result | |
|---|---|
| 2 | 0 |
| 6 | 1 |
Example 2: Upper-triangular Cholesky factor of 2x2 matrix
Inputs:
| matrix | lower | |
|---|---|---|
| 4 | 12 | false |
| 12 | 37 |
Excel formula:
=CHOLESKY({4,12;12,37}, FALSE)
Expected output:
| Result | |
|---|---|
| 2 | 6 |
| 0 | 1 |
Example 3: Lower-triangular Cholesky factor of 3x3 matrix
Inputs:
| matrix | lower | ||
|---|---|---|---|
| 25 | 15 | -5 | true |
| 15 | 18 | 0 | |
| -5 | 0 | 11 |
Excel formula:
=CHOLESKY({25,15,-5;15,18,0;-5,0,11}, TRUE)
Expected output:
| Result | ||
|---|---|---|
| 5 | 0 | 0 |
| 3 | 3 | 0 |
| -1 | 1 | 3 |
Example 4: Non-trivial 3x3 matrix with irrational entries
Inputs:
| matrix | lower | ||
|---|---|---|---|
| 9 | -6 | 3 | true |
| -6 | 8 | -2 | |
| 3 | -2 | 3 |
Excel formula:
=CHOLESKY({9,-6,3;-6,8,-2;3,-2,3}, TRUE)
Expected output:
| Result | ||
|---|---|---|
| 3 | 0 | 0 |
| -2 | 2 | 0 |
| 1 | 0 | 1.41421 |
Python Code
Show Code
import numpy as np
from scipy.linalg import cholesky as scipy_cholesky
def cholesky(matrix, lower=False):
"""
Compute the Cholesky decomposition of a real, symmetric positive-definite matrix.
See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.cholesky.html
This example function is provided as-is without any representation of accuracy.
Args:
matrix (list[list]): Real symmetric positive-definite matrix to factor (must be square)
lower (bool, optional): If TRUE, return lower-triangular factor L; if FALSE, return upper-triangular factor U Default is False.
Returns:
list[list]: 2D Cholesky factor matrix, or error message string.
"""
try:
def to2d(x):
return [[x]] if not isinstance(x, list) else x
# Normalize input to ensure it's a 2D list
matrix = to2d(matrix)
# Validate matrix structure: must be a non-empty 2D list
if not isinstance(matrix, list) or not matrix:
return "Error: Invalid input: matrix must be a 2D list with at least one row."
if any(not isinstance(row, list) for row in matrix):
return "Error: Invalid input: matrix must be a 2D list with at least one row."
# Validate matrix is square (n x n)
n = len(matrix)
if any(len(row) != n for row in matrix):
return "Error: Invalid input: matrix must be square (n x n)."
# Convert matrix entries to numeric values
numeric_rows = []
for row in matrix:
numeric_row = []
for value in row:
try:
numeric_row.append(float(value))
except (ValueError, TypeError):
return "Error: Invalid input: matrix entries must be numeric values."
numeric_rows.append(numeric_row)
# Convert to numpy array and validate numeric properties
arr = np.array(numeric_rows, dtype=np.float64)
if not np.isfinite(arr).all():
return "Error: Invalid input: matrix entries must be finite numbers."
# Verify symmetry (required for Cholesky decomposition)
if not np.allclose(arr, arr.T, atol=1e-9):
return "Error: Invalid input: matrix must be symmetric."
real_matrix = arr
# Parse and normalize the 'lower' parameter from Excel-friendly inputs
if isinstance(lower, list):
return "Error: Invalid input: lower must be a scalar value."
if isinstance(lower, str):
lower_normalized = lower.strip().lower()
if lower_normalized in ("true", "1", "yes"):
lower_flag = True
elif lower_normalized in ("false", "0", "no", ""):
lower_flag = False
else:
return "Error: Invalid input: lower must be TRUE or FALSE."
elif isinstance(lower, (bool, int, float)):
lower_flag = bool(lower)
elif lower is None:
lower_flag = False
else:
return "Error: Invalid input: lower must be TRUE or FALSE."
try:
# Perform Cholesky decomposition using SciPy
result = scipy_cholesky(real_matrix, lower=lower_flag)
except np.linalg.LinAlgError:
return "Error: Matrix is not positive-definite."
except Exception:
return "Error: Failed to compute Cholesky decomposition."
# Convert result to Python list format
result_matrix = []
for row in result:
result_row = []
for value in row:
real_value = float(value)
if not np.isfinite(real_value):
return "Error: Result contains non-finite values."
result_row.append(real_value)
result_matrix.append(result_row)
return result_matrix
except Exception as e:
return f"Error: {str(e)}"Online Calculator
HESSENBERG
The Hessenberg decomposition factors a square matrix A into a unitary matrix Q and a Hessenberg matrix H.
Excel Usage
=HESSENBERG(matrix, hess_ret_type)
matrix(list[list], required): Square 2D array of numeric values to decompose.hess_ret_type(str, optional, default: “h”): The component of the decomposition to return.
Returns (list[list]): 2D array representing the requested component (H or Q).
Example 1: Hessenberg form H of 4x4 matrix
Inputs:
| matrix | hess_ret_type | |||
|---|---|---|---|---|
| 2 | 5 | 8 | 7 | h |
| 5 | 2 | 2 | 8 | |
| 7 | 5 | 6 | 6 | |
| 5 | 4 | 4 | 8 |
Excel formula:
=HESSENBERG({2,5,8,7;5,2,2,8;7,5,6,6;5,4,4,8}, "h")
Expected output:
| Result | |||
|---|---|---|---|
| 2 | -11.6584 | 1.42005 | 0.253491 |
| -9.94987 | 14.5354 | -5.31022 | 2.43082 |
| 0 | -1.83299 | 0.3897 | -0.51527 |
| 0 | 0 | -3.8319 | 1.07495 |
Example 2: Transformation matrix Q
Inputs:
| matrix | hess_ret_type | |||
|---|---|---|---|---|
| 2 | 5 | 8 | 7 | q |
| 5 | 2 | 2 | 8 | |
| 7 | 5 | 6 | 6 | |
| 5 | 4 | 4 | 8 |
Excel formula:
=HESSENBERG({2,5,8,7;5,2,2,8;7,5,6,6;5,4,4,8}, "q")
Expected output:
| Result | |||
|---|---|---|---|
| 1 | 0 | 0 | 0 |
| 0 | -0.502519 | -0.475751 | -0.721897 |
| 0 | -0.703526 | -0.260306 | 0.66128 |
| 0 | -0.502519 | 0.84018 | -0.203895 |
Python Code
Show Code
import numpy as np
from scipy.linalg import hessenberg as scipy_hessenberg
def hessenberg(matrix, hess_ret_type='h'):
"""
Compute Hessenberg form of a matrix.
See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.hessenberg.html
This example function is provided as-is without any representation of accuracy.
Args:
matrix (list[list]): Square 2D array of numeric values to decompose.
hess_ret_type (str, optional): The component of the decomposition to return. Valid options: Hessenberg Form (H), Transformation Matrix (Q). Default is 'h'.
Returns:
list[list]: 2D array representing the requested component (H or Q).
"""
try:
def to2d(x):
return [[x]] if not isinstance(x, list) else x
matrix = to2d(matrix)
if not isinstance(matrix, list) or not matrix or not all(isinstance(row, list) for row in matrix):
return "Error: matrix must be a non-empty 2D list"
n = len(matrix)
if any(len(row) != n for row in matrix):
return "Error: matrix must be square (n x n)"
try:
a = np.array(matrix, dtype=float)
except (ValueError, TypeError):
return "Error: matrix must contain numeric values"
if not np.all(np.isfinite(a)):
return "Error: matrix must contain only finite numbers"
try:
if hess_ret_type.lower() == "q":
h, q = scipy_hessenberg(a, calc_q=True)
return q.tolist()
else:
h = scipy_hessenberg(a, calc_q=False)
return h.tolist()
except Exception as e:
return f"Error: {str(e)}"
except Exception as e:
return f"Error: {str(e)}"Online Calculator
LDL
The LDL factorization factors a symmetric matrix A into a unit lower triangular matrix L, a block diagonal matrix D, and a permutation matrix P.
Excel Usage
=LDL(matrix, lower, ldl_ret_type)
matrix(list[list], required): Square symmetric 2D array of numeric values to decompose.lower(bool, optional, default: true): If TRUE, compute the lower triangular factor; if FALSE, use the upper part.ldl_ret_type(str, optional, default: “d”): The component of the decomposition to return.
Returns (list[list]): 2D array representing the requested component (LU, D, or perm).
Example 1: Block diagonal matrix D
Inputs:
| matrix | ldl_ret_type | ||
|---|---|---|---|
| 2 | -1 | 3 | d |
| -1 | 2 | 0 | |
| 3 | 0 | 1 |
Excel formula:
=LDL({2,-1,3;-1,2,0;3,0,1}, "d")
Expected output:
| Result | ||
|---|---|---|
| 2 | 0 | 0 |
| 0 | 1.5 | 0 |
| 0 | 0 | -5 |
Example 2: Triangular factor matrix LU
Inputs:
| matrix | ldl_ret_type | ||
|---|---|---|---|
| 2 | -1 | 3 | lu |
| -1 | 2 | 0 | |
| 3 | 0 | 1 |
Excel formula:
=LDL({2,-1,3;-1,2,0;3,0,1}, "lu")
Expected output:
| Result | ||
|---|---|---|
| 1 | 0 | 0 |
| -0.5 | 1 | 0 |
| 1.5 | 1 | 1 |
Example 3: Permutation indices
Inputs:
| matrix | ldl_ret_type | ||
|---|---|---|---|
| 2 | -1 | 3 | perm |
| -1 | 2 | 0 | |
| 3 | 0 | 1 |
Excel formula:
=LDL({2,-1,3;-1,2,0;3,0,1}, "perm")
Expected output:
| Result | ||
|---|---|---|
| 0 | 1 | 2 |
Python Code
Show Code
import numpy as np
from scipy.linalg import ldl as scipy_ldl
def ldl(matrix, lower=True, ldl_ret_type='d'):
"""
Compute the LDLt or Bunch-Kaufman factorization of a symmetric matrix.
See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.ldl.html
This example function is provided as-is without any representation of accuracy.
Args:
matrix (list[list]): Square symmetric 2D array of numeric values to decompose.
lower (bool, optional): If TRUE, compute the lower triangular factor; if FALSE, use the upper part. Default is True.
ldl_ret_type (str, optional): The component of the decomposition to return. Valid options: Triangular Factor (L/U), Block Diagonal (D), Permutation (perm). Default is 'd'.
Returns:
list[list]: 2D array representing the requested component (LU, D, or perm).
"""
try:
def to2d(x):
return [[x]] if not isinstance(x, list) else x
matrix = to2d(matrix)
if not isinstance(matrix, list) or not matrix or not all(isinstance(row, list) for row in matrix):
return "Error: matrix must be a non-empty 2D list"
n = len(matrix)
if any(len(row) != n for row in matrix):
return "Error: matrix must be square (n x n)"
try:
a = np.array(matrix, dtype=float)
except (ValueError, TypeError):
return "Error: matrix must contain numeric values"
if not np.all(np.isfinite(a)):
return "Error: matrix must contain only finite numbers"
try:
lu, d, perm = scipy_ldl(a, lower=lower)
except Exception as e:
return f"Error: {str(e)}"
rt = ldl_ret_type.lower()
if rt == "lu":
return lu.tolist()
elif rt == "d":
return d.tolist()
else:
return [perm.tolist()]
except Exception as e:
return f"Error: {str(e)}"Online Calculator
LU
The LU decomposition factors a matrix A into the product of a permutation matrix P, a lower triangular matrix L (with unit diagonal), and an upper triangular matrix U:
A = PLU
If permute_l is set to TRUE, the function returns a permuted lower triangular matrix L' such that A = L'U.
Excel Usage
=LU(matrix, permute_l, lu_ret_type)
matrix(list[list], required): 2D array of numeric values to decompose.permute_l(bool, optional, default: false): If TRUE, return a permuted L matrix satisfying A = LU.lu_ret_type(str, optional, default: “u”): The component of the decomposition to return.
Returns (list[list]): 2D array representing the requested component (P, L, U, or PL).
Example 1: Upper triangular matrix of 2x2
Inputs:
| matrix | lu_ret_type | |
|---|---|---|
| 1 | 2 | u |
| 3 | 4 |
Excel formula:
=LU({1,2;3,4}, "u")
Expected output:
| Result | |
|---|---|
| 3 | 4 |
| 0 | 0.666667 |
Example 2: Lower triangular matrix of 2x2
Inputs:
| matrix | lu_ret_type | |
|---|---|---|
| 1 | 2 | l |
| 3 | 4 |
Excel formula:
=LU({1,2;3,4}, "l")
Expected output:
| Result | |
|---|---|
| 1 | 0 |
| 0.333333 | 1 |
Example 3: Permutation matrix of 2x2
Inputs:
| matrix | lu_ret_type | |
|---|---|---|
| 1 | 2 | p |
| 3 | 4 |
Excel formula:
=LU({1,2;3,4}, "p")
Expected output:
| Result | |
|---|---|
| 0 | 1 |
| 1 | 0 |
Example 4: Permuted L matrix
Inputs:
| matrix | permute_l | lu_ret_type | |
|---|---|---|---|
| 1 | 2 | true | pl |
| 3 | 4 |
Excel formula:
=LU({1,2;3,4}, TRUE, "pl")
Expected output:
| Result | |
|---|---|
| 0.333333 | 1 |
| 1 | 0 |
Python Code
Show Code
import numpy as np
from scipy.linalg import lu as scipy_lu
def lu(matrix, permute_l=False, lu_ret_type='u'):
"""
Compute LU decomposition of a matrix with partial pivoting.
See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.lu.html
This example function is provided as-is without any representation of accuracy.
Args:
matrix (list[list]): 2D array of numeric values to decompose.
permute_l (bool, optional): If TRUE, return a permuted L matrix satisfying A = LU. Default is False.
lu_ret_type (str, optional): The component of the decomposition to return. Valid options: Permutation Matrix (P), Lower Triangular (L), Upper Triangular (U), Permuted L (PL). Default is 'u'.
Returns:
list[list]: 2D array representing the requested component (P, L, U, or PL).
"""
try:
def to2d(x):
return [[x]] if not isinstance(x, list) else x
matrix = to2d(matrix)
if not isinstance(matrix, list) or not matrix or not all(isinstance(row, list) for row in matrix):
return "Error: matrix must be a non-empty 2D list"
n_rows = len(matrix)
n_cols = len(matrix[0])
if n_cols == 0 or any(len(row) != n_cols for row in matrix):
return "Error: All rows must have the same non-zero length"
try:
a = np.array(matrix, dtype=float)
except (ValueError, TypeError):
return "Error: matrix must contain numeric values"
if not np.all(np.isfinite(a)):
return "Error: matrix must contain only finite numbers"
try:
if permute_l:
pl, u = scipy_lu(a, permute_l=True)
else:
p, l, u = scipy_lu(a, permute_l=False)
except Exception as e:
return f"Error: {str(e)}"
rt = lu_ret_type.lower()
if permute_l:
if rt == "pl":
return pl.tolist()
elif rt == "u":
return u.tolist()
else:
return "Error: With permute_l=TRUE, return_type must be 'pl' or 'u'"
else:
if rt == "p":
return p.tolist()
elif rt == "l":
return l.tolist()
elif rt == "u":
return u.tolist()
else:
return "Error: With permute_l=FALSE, return_type must be 'p', 'l', or 'u'"
except Exception as e:
return f"Error: {str(e)}"Online Calculator
POLAR
The polar decomposition factors a matrix A into the product of an orthonormal matrix U and a positive semidefinite Hermitian matrix P.
Excel Usage
=POLAR(matrix, polar_side, polar_ret_type)
matrix(list[list], required): 2D array of numeric values to decompose.polar_side(str, optional, default: “right”): Determines whether a right (A=UP) or left (A=PU) polar decomposition is computed.polar_ret_type(str, optional, default: “u”): The component of the decomposition to return.
Returns (list[list]): 2D array representing the requested component (U or P).
Example 1: Unitary matrix U of 2x2
Inputs:
| matrix | polar_ret_type | |
|---|---|---|
| 1 | -1 | u |
| 2 | 4 |
Excel formula:
=POLAR({1,-1;2,4}, "u")
Expected output:
| Result | |
|---|---|
| 0.857493 | -0.514496 |
| 0.514496 | 0.857493 |
Example 2: Positive semidefinite matrix P of 2x2
Inputs:
| matrix | polar_ret_type | |
|---|---|---|
| 1 | -1 | p |
| 2 | 4 |
Excel formula:
=POLAR({1,-1;2,4}, "p")
Expected output:
| Result | |
|---|---|
| 1.88648 | 1.20049 |
| 1.20049 | 3.94447 |
Python Code
Show Code
import numpy as np
from scipy.linalg import polar as scipy_polar
def polar(matrix, polar_side='right', polar_ret_type='u'):
"""
Compute the polar decomposition of a matrix.
See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.polar.html
This example function is provided as-is without any representation of accuracy.
Args:
matrix (list[list]): 2D array of numeric values to decompose.
polar_side (str, optional): Determines whether a right (A=UP) or left (A=PU) polar decomposition is computed. Valid options: Right (A=UP), Left (A=PU). Default is 'right'.
polar_ret_type (str, optional): The component of the decomposition to return. Valid options: Unitary/Orthonormal (U), Positive Semidefinite (P). Default is 'u'.
Returns:
list[list]: 2D array representing the requested component (U or P).
"""
try:
def to2d(x):
return [[x]] if not isinstance(x, list) else x
matrix = to2d(matrix)
if not isinstance(matrix, list) or not matrix or not all(isinstance(row, list) for row in matrix):
return "Error: matrix must be a non-empty 2D list"
try:
a = np.array(matrix, dtype=float)
except (ValueError, TypeError):
return "Error: matrix must contain numeric values"
if not np.all(np.isfinite(a)):
return "Error: matrix must contain only finite numbers"
try:
u_matrix, p_matrix = scipy_polar(a, side=polar_side.lower())
except Exception as e:
return f"Error: {str(e)}"
if polar_ret_type.lower() == "u":
return u_matrix.tolist()
else:
return p_matrix.tolist()
except Exception as e:
return f"Error: {str(e)}"Online Calculator
QR
QR decomposition factors a matrix into an orthogonal (or unitary) component and an upper-triangular component. It is commonly used in least-squares solving and numerical linear algebra workflows.
For a matrix A, the decomposition is:
A = QR
where Q is orthogonal (or unitary) and R is upper triangular.
Excel Usage
=QR(a, return_type)
a(list[list], required): Matrix to decompose. Each row must have the same number of columns, and entries must be finite numeric values.return_type(str, optional, default: “Q”): Which matrix factor to return from the QR decomposition.
Returns (list[list]): 2D Q or R matrix, or error message string.
Example 1: Orthogonal factor of a 2x2 matrix
Inputs:
| a | return_type | |
|---|---|---|
| 1 | 2 | Q |
| 3 | 4 |
Excel formula:
=QR({1,2;3,4}, "Q")
Expected output:
| Result | |
|---|---|
| -0.316228 | -0.948683 |
| -0.948683 | 0.316228 |
Example 2: Upper-triangular factor of a 2x2 matrix
Inputs:
| a | return_type | |
|---|---|---|
| 1 | 2 | R |
| 3 | 4 |
Excel formula:
=QR({1,2;3,4}, "R")
Expected output:
| Result | |
|---|---|
| -3.16228 | -4.42719 |
| 0 | -0.632456 |
Example 3: Orthogonal factor of a 3x2 rectangular matrix
Inputs:
| a | return_type | |
|---|---|---|
| 1 | 2 | Q |
| 3 | 4 | |
| 5 | 6 |
Excel formula:
=QR({1,2;3,4;5,6}, "Q")
Expected output:
| Result | ||
|---|---|---|
| -0.169031 | 0.897085 | 0.408248 |
| -0.507093 | 0.276026 | -0.816497 |
| -0.845154 | -0.345033 | 0.408248 |
Example 4: Upper-triangular factor of a 3x2 rectangular matrix
Inputs:
| a | return_type | |
|---|---|---|
| 1 | 2 | R |
| 3 | 4 | |
| 5 | 6 |
Excel formula:
=QR({1,2;3,4;5,6}, "R")
Expected output:
| Result | |
|---|---|
| -5.91608 | -7.43736 |
| 0 | 0.828079 |
| 0 | 0 |
Python Code
Show Code
import numpy as np
from scipy.linalg import qr as scipy_linalg_qr
def qr(a, return_type='Q'):
"""
Compute the QR decomposition of a matrix and return either Q or R.
See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.qr.html
This example function is provided as-is without any representation of accuracy.
Args:
a (list[list]): Matrix to decompose. Each row must have the same number of columns, and entries must be finite numeric values.
return_type (str, optional): Which matrix factor to return from the QR decomposition. Valid options: Q, R. Default is 'Q'.
Returns:
list[list]: 2D Q or R matrix, or error message string.
"""
try:
def to2d(x):
return [[x]] if not isinstance(x, list) else x
# Normalize scalar inputs into a 2D list structure
a = to2d(a)
if not isinstance(a[0], list):
# Handle case where input was a 1D list like [1, 2, 3]
if all(not isinstance(item, list) for item in a):
try:
a = [[float(item)] for item in a]
except (TypeError, ValueError):
return "Error: Invalid input: a must contain only numeric values."
# Validate the 2D list structure and ensure consistent row lengths
if not a or not all(isinstance(row, list) for row in a):
return "Error: Invalid input: a must be a 2D list with at least one row."
if any(len(row) == 0 for row in a):
return "Error: Invalid input: rows in a must contain at least one value."
column_count = len(a[0])
if any(len(row) != column_count for row in a):
return "Error: Invalid input: all rows in a must have the same length."
# Convert entries to floats and check for finite values
numeric_rows = []
for row in a:
numeric_row = []
for value in row:
try:
numeric_value = float(value)
except Exception:
return "Error: Invalid input: a must contain only numeric values."
if not np.isfinite(numeric_value):
return "Error: Invalid input: a must contain only finite numbers."
numeric_row.append(numeric_value)
numeric_rows.append(numeric_row)
array = np.array(numeric_rows, dtype=float)
# Validate return_type and normalize casing
if not isinstance(return_type, str) or return_type.upper() not in ("Q", "R"):
return "Error: Invalid input: return_type must be 'Q' or 'R'."
normalized_return_type = return_type.upper()
# Compute the QR decomposition
try:
q_matrix, r_matrix = scipy_linalg_qr(array, mode="full")
except Exception as exc:
return f"Error: QR decomposition error: {exc}"
result = q_matrix if normalized_return_type == "Q" else r_matrix
# Ensure the result is finite before returning
if not np.all(np.isfinite(result)):
return "Error: QR decomposition error: result contains non-finite values."
return result.tolist()
except Exception as e:
return f"Error: {str(e)}"Online Calculator
SCHUR
The Schur decomposition factors a square matrix A into a unitary matrix Z and an upper triangular matrix T such that A = ZTZ^H.
Excel Usage
=SCHUR(matrix, schur_output, schur_ret_type)
matrix(list[list], required): Square 2D array of numeric values to decompose.schur_output(str, optional, default: “real”): Construct the real or complex Schur decomposition.schur_ret_type(str, optional, default: “t”): The component of the decomposition to return.
Returns (list[list]): 2D array representing the requested component (T or Z).
Example 1: Schur form T of 3x3 matrix
Inputs:
| matrix | schur_ret_type | ||
|---|---|---|---|
| 0 | 2 | 2 | t |
| 0 | 1 | 2 | |
| 1 | 0 | 1 |
Excel formula:
=SCHUR({0,2,2;0,1,2;1,0,1}, "t")
Expected output:
| Result | ||
|---|---|---|
| 2.65897 | 1.4244 | -1.92933 |
| 0 | -0.329484 | -0.490637 |
| 0 | 1.31179 | -0.329484 |
Example 2: Transformation matrix Z
Inputs:
| matrix | schur_ret_type | ||
|---|---|---|---|
| 0 | 2 | 2 | z |
| 0 | 1 | 2 | |
| 1 | 0 | 1 |
Excel formula:
=SCHUR({0,2,2;0,1,2;1,0,1}, "z")
Expected output:
| Result | ||
|---|---|---|
| 0.727116 | -0.601562 | 0.330796 |
| 0.528394 | 0.798019 | 0.289768 |
| 0.438294 | 0.0359041 | -0.898114 |
Example 3: Complex Schur decomposition (T real part) 2x2
Inputs:
| matrix | schur_output | schur_ret_type | |
|---|---|---|---|
| 0 | 1 | complex | t |
| -1 | 0 |
Excel formula:
=SCHUR({0,1;-1,0}, "complex", "t")
Expected output:
| Result | |
|---|---|
| [object Object] | [object Object] |
| 0 | [object Object] |
Python Code
Show Code
import numpy as np
from scipy.linalg import schur as scipy_schur
def schur(matrix, schur_output='real', schur_ret_type='t'):
"""
Compute Schur decomposition of a matrix.
See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.schur.html
This example function is provided as-is without any representation of accuracy.
Args:
matrix (list[list]): Square 2D array of numeric values to decompose.
schur_output (str, optional): Construct the real or complex Schur decomposition. Valid options: Real, Complex. Default is 'real'.
schur_ret_type (str, optional): The component of the decomposition to return. Valid options: Schur Form (T), Unitary Matrix (Z). Default is 't'.
Returns:
list[list]: 2D array representing the requested component (T or Z).
"""
try:
def to2d(x):
return [[x]] if not isinstance(x, list) else x
matrix = to2d(matrix)
if not isinstance(matrix, list) or not matrix or not all(isinstance(row, list) for row in matrix):
return "Error: matrix must be a non-empty 2D list"
n = len(matrix)
if any(len(row) != n for row in matrix):
return "Error: matrix must be square (n x n)"
try:
a = np.array(matrix, dtype=float)
except (ValueError, TypeError):
return "Error: matrix must contain numeric values"
if not np.all(np.isfinite(a)):
return "Error: matrix must contain only finite numbers"
try:
T, Z = scipy_schur(a, output=schur_output.lower())
except Exception as e:
return f"Error: {str(e)}"
def format_complex(res):
if not np.iscomplexobj(res):
return (res.reshape(1, -1) if res.ndim == 1 else res).tolist()
out = []
for row in (res.reshape(1, -1) if res.ndim == 1 else res):
out_row = []
for val in row:
if val.imag == 0.0:
out_row.append(float(val.real))
else:
out_row.append({
"type": "Double",
"basicValue": float(val.real),
"properties": {
"Real": {"type": "Double", "basicValue": float(val.real)},
"Imaginary": {"type": "Double", "basicValue": float(val.imag)},
"Magnitude": {"type": "Double", "basicValue": float(np.abs(val))},
"Phase": {"type": "Double", "basicValue": float(np.angle(val))}
}
})
out.append(out_row)
return out
if schur_ret_type.lower() == "t":
return format_complex(T)
else:
return format_complex(Z)
except Exception as e:
return f"Error: {str(e)}"Online Calculator
SVD
Singular value decomposition factors a matrix into orthogonal (or unitary) bases and nonnegative singular values. It is fundamental for rank analysis, dimensionality reduction, and stable least-squares methods.
For a matrix A, the factorization is:
A = U\Sigma V^H
where U and V^H are orthogonal/unitary factors and \Sigma contains singular values on its diagonal in non-increasing order.
Excel Usage
=SVD(matrix, full_matrices, compute_uv, overwrite_a, check_finite, lapack_driver, svd_return_type)
matrix(list[list], required): 2D list containing numeric values to decomposefull_matrices(bool, optional, default: true): If True, U and Vh have full shapes; if False, reduced shapescompute_uv(bool, optional, default: true): If True, computes U, S, Vh; if False, returns only singular valuesoverwrite_a(bool, optional, default: false): If True, allows overwriting the input matrix to improve performancecheck_finite(bool, optional, default: true): If True, scipy checks that input contains only finite numberslapack_driver(str, optional, default: “gesdd”): LAPACK driver to use for the computationsvd_return_type(str, optional, default: “u”): Component to return from the decomposition
Returns (list[list]): 2D SVD component, or error message string.
Example 1: Left singular vectors of 2x2 matrix using GESDD
Inputs:
| matrix | full_matrices | compute_uv | overwrite_a | check_finite | lapack_driver | svd_return_type | |
|---|---|---|---|---|---|---|---|
| 1 | 2 | true | true | false | true | gesdd | u |
| 3 | 4 |
Excel formula:
=SVD({1,2;3,4}, TRUE, TRUE, FALSE, TRUE, "gesdd", "u")
Expected output:
| Result | |
|---|---|
| -0.404554 | -0.914514 |
| -0.914514 | 0.404554 |
Example 2: Singular values of 3x2 tall matrix with reduced output
Inputs:
| matrix | full_matrices | compute_uv | overwrite_a | check_finite | lapack_driver | svd_return_type | |
|---|---|---|---|---|---|---|---|
| 1 | 0 | false | true | true | false | gesdd | s |
| 0 | 1 | ||||||
| 1 | 1 |
Excel formula:
=SVD({1,0;0,1;1,1}, FALSE, TRUE, TRUE, FALSE, "gesdd", "s")
Expected output:
| Result | |
|---|---|
| 1.73205 | 1 |
Example 3: Right singular vectors of 2x2 matrix using GESVD
Inputs:
| matrix | full_matrices | compute_uv | overwrite_a | check_finite | lapack_driver | svd_return_type | |
|---|---|---|---|---|---|---|---|
| 1 | 2 | true | true | false | true | gesvd | vh |
| 3 | 4 |
Excel formula:
=SVD({1,2;3,4}, TRUE, TRUE, FALSE, TRUE, "gesvd", "vh")
Expected output:
| Result | |
|---|---|
| -0.576048 | -0.817416 |
| 0.817416 | -0.576048 |
Example 4: Singular values of 2x3 wide matrix
Inputs:
| matrix | full_matrices | compute_uv | overwrite_a | check_finite | lapack_driver | svd_return_type | ||
|---|---|---|---|---|---|---|---|---|
| 1 | 2 | 3 | true | true | false | true | gesdd | s |
| 4 | 5 | 6 |
Excel formula:
=SVD({1,2,3;4,5,6}, TRUE, TRUE, FALSE, TRUE, "gesdd", "s")
Expected output:
| Result | |
|---|---|
| 9.50803 | 0.77287 |
Python Code
Show Code
import numpy as np
from scipy.linalg import svd as scipy_svd
def svd(matrix, full_matrices=True, compute_uv=True, overwrite_a=False, check_finite=True, lapack_driver='gesdd', svd_return_type='u'):
"""
Compute the Singular Value Decomposition (SVD) of a matrix using scipy.linalg.svd.
See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.svd.html
This example function is provided as-is without any representation of accuracy.
Args:
matrix (list[list]): 2D list containing numeric values to decompose
full_matrices (bool, optional): If True, U and Vh have full shapes; if False, reduced shapes Default is True.
compute_uv (bool, optional): If True, computes U, S, Vh; if False, returns only singular values Default is True.
overwrite_a (bool, optional): If True, allows overwriting the input matrix to improve performance Default is False.
check_finite (bool, optional): If True, scipy checks that input contains only finite numbers Default is True.
lapack_driver (str, optional): LAPACK driver to use for the computation Valid options: Divide-and-conquer, Classic. Default is 'gesdd'.
svd_return_type (str, optional): Component to return from the decomposition Valid options: Left singular vectors, Singular values, Right singular vectors. Default is 'u'.
Returns:
list[list]: 2D SVD component, or error message string.
"""
try:
# Helper to normalize scalar/single-element input to 2D list
def to2d(x):
return [[x]] if not isinstance(x, list) else x
# Normalize scalar inputs into a 2D list structure
matrix = to2d(matrix)
# Handle scalar string conversion
if len(matrix) == 1 and len(matrix[0]) == 1:
val = matrix[0][0]
if isinstance(val, str):
try:
matrix = [[float(val)]]
except Exception:
return "Error: Invalid input: matrix must be a 2D list of numeric values."
elif isinstance(val, (int, float, bool)):
matrix = [[float(val)]]
# Validate matrix structure and consistency
if len(matrix) == 0 or any(not isinstance(row, list) for row in matrix):
return "Error: Invalid input: matrix must be a 2D list with at least one row."
column_count = len(matrix[0])
if column_count == 0:
return "Error: Invalid input: matrix rows must contain at least one value."
if any(len(row) != column_count for row in matrix):
return "Error: Invalid input: all rows in matrix must have the same number of columns."
# Convert entries to floats and ensure finiteness
numeric_rows = []
for row in matrix:
numeric_row = []
for value in row:
try:
numeric_value = float(value)
except Exception:
return "Error: Invalid input: matrix must contain numeric values."
if not np.isfinite(numeric_value):
return "Error: Invalid input: matrix must contain only finite numbers."
numeric_row.append(numeric_value)
numeric_rows.append(numeric_row)
array = np.array(numeric_rows, dtype=float)
if array.size == 0:
return "Error: Invalid input: matrix must contain at least one numeric value."
# Validate boolean flags
if not isinstance(full_matrices, bool):
return "Error: Invalid input: full_matrices must be a boolean."
if not isinstance(compute_uv, bool):
return "Error: Invalid input: compute_uv must be a boolean."
if not isinstance(overwrite_a, bool):
return "Error: Invalid input: overwrite_a must be a boolean."
if not isinstance(check_finite, bool):
return "Error: Invalid input: check_finite must be a boolean."
# Normalize lapack_driver and return_type values
if not isinstance(lapack_driver, str):
return "Error: Invalid input: lapack_driver must be 'gesdd' or 'gesvd'."
normalized_driver = lapack_driver.lower()
if normalized_driver not in {"gesdd", "gesvd"}:
return "Error: Invalid input: lapack_driver must be 'gesdd' or 'gesvd'."
if not isinstance(svd_return_type, str):
return "Error: Invalid input: svd_return_type must be 'u', 's', or 'vh'."
normalized_return_type = svd_return_type.lower()
if normalized_return_type not in {"u", "s", "vh"}:
return "Error: Invalid input: svd_return_type must be 'u', 's', or 'vh'."
# Execute the SciPy SVD with the requested options
try:
if compute_uv:
u_matrix, singular_values, vh_matrix = scipy_svd(
array,
full_matrices=full_matrices,
compute_uv=True,
overwrite_a=overwrite_a,
check_finite=check_finite,
lapack_driver=normalized_driver,
)
else:
singular_values = scipy_svd(
array,
compute_uv=False,
overwrite_a=overwrite_a,
check_finite=check_finite,
lapack_driver=normalized_driver,
)
u_matrix = None
vh_matrix = None
except Exception as exc:
return f"Error: scipy.linalg.svd error: {exc}"
# Ensure results are finite before converting back to Python lists
if not np.all(np.isfinite(singular_values)):
return "Error: scipy.linalg.svd error: result contains non-finite values."
if normalized_return_type == "s":
return [singular_values.tolist()]
if not compute_uv:
return "Error: Invalid input: compute_uv must be True when svd_return_type is 'u' or 'vh'."
if normalized_return_type == "u":
if not np.all(np.isfinite(u_matrix)):
return "Error: scipy.linalg.svd error: result contains non-finite values."
return u_matrix.tolist()
if not np.all(np.isfinite(vh_matrix)):
return "Error: scipy.linalg.svd error: result contains non-finite values."
return vh_matrix.tolist()
except Exception as e:
return f"Error: {str(e)}"Online Calculator