SVD
Overview
The SVD function computes the Singular Value Decomposition of a matrix, factorizing it into unitary matrices and and a diagonal matrix of singular values such that the original matrix satisfies . This operation is widely used for dimensionality reduction, signal processing, and numerical analysis. The wrapper exposes the same controls as scipy.linalg.svd while adding a return_type selector so that Excel receives only one component per call.
This example function is provided as-is without any representation of accuracy.
Usage
To use the function in Excel:
=SVD(matrix, [full_matrices], [compute_uv], [overwrite_a], [check_finite], [lapack_driver], [return_type])matrix(2D list of float, required): Matrix to decompose. Provide a rectangular table with at least one row and one column; all rows must have the same number of columns.full_matrices(bool, optional, default=TRUE): Controls whether and are full-sized (TRUE) or reduced (FALSE).compute_uv(bool, optional, default=TRUE): WhenTRUE, returns vectors and singular values; whenFALSE, only singular values are computed.overwrite_a(bool, optional, default=FALSE): Allows overwriting the input matrix to improve performance.check_finite(bool, optional, default=TRUE): Ensures the input matrix contains only finite numbers.lapack_driver(str, optional, default=“gesdd”): LAPACK driver to use. Choose"gesdd"for divide-and-conquer or"gesvd"for the classic algorithm.return_type(str, optional, default=“u”): Component to return —"u","s", or"vh".
The function returns a 2D list containing either the left singular vectors (return_type="u"), the right singular vectors (return_type="vh"), or a single-row 2D list of singular values (return_type="s"). Invalid inputs return an error string.
Examples
Example 1: Left singular vectors of a 2Ă—2 matrix
Inputs:
| matrix | full_matrices | compute_uv | overwrite_a | check_finite | lapack_driver | 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:
| U | |
|---|---|
| -0.405 | -0.915 |
| -0.915 | 0.405 |
Example 2: Singular values of a tall matrix
Inputs:
| matrix | full_matrices | compute_uv | overwrite_a | check_finite | lapack_driver | 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:
| Singular values | |
|---|---|
| 1.732 | 1.000 |
Example 3: Right singular vectors with the gesvd driver
Inputs:
| matrix | full_matrices | compute_uv | overwrite_a | check_finite | lapack_driver | 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:
| Vh | |
|---|---|
| -0.576 | -0.817 |
| 0.817 | -0.576 |
Example 4: Singular values of a wide matrix
Inputs:
| matrix | full_matrices | compute_uv | overwrite_a | check_finite | lapack_driver | 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:
| Singular values | |
|---|---|
| 9.508 | 0.773 |
Python Code
from typing import List, Union
import numpy as np
from scipy.linalg import svd as scipy_svd
ScalarValue = Union[float, int, bool, str, None]
MatrixInput = Union[ScalarValue, List[List[ScalarValue]]]
MatrixOutput = Union[List[List[float]], str]
def svd(
matrix: MatrixInput,
full_matrices: bool = True,
compute_uv: bool = True,
overwrite_a: bool = False,
check_finite: bool = True,
lapack_driver: str = "gesdd",
return_type: str = "u",
) -> MatrixOutput:
"""
Compute the Singular Value Decomposition (SVD) of a matrix using ``scipy.linalg.svd``.
Args:
matrix: 2D list (or scalar interpreted as a 1x1 matrix) containing numeric values to decompose.
full_matrices: If True, U and Vh have full shapes; if False, reduced shapes (default: True).
compute_uv: If True, returns U, S, Vh; if False, returns only singular values (default: True).
overwrite_a: If True, allows overwriting the input matrix to improve performance (default: False).
check_finite: If True, checks that the input matrix contains only finite numbers (default: True).
lapack_driver: LAPACK driver to use ("gesdd" or "gesvd") (default: "gesdd").
return_type: Output selector ("u", "s", or "vh"; default: "u").
Returns:
The requested SVD component as a 2D list (U or Vh) or a single-row 2D list of singular values, or an
error message (str) if input is invalid.
This example function is provided as-is without any representation of accuracy.
"""
# Normalize scalar inputs into a 2D list structure
if not isinstance(matrix, list):
if isinstance(matrix, (int, float, bool)):
matrix = [[float(matrix)]]
elif isinstance(matrix, str):
try:
matrix = [[float(matrix)]]
except Exception:
return "Invalid input: matrix must be a 2D list of numeric values."
else:
return "Invalid input: matrix must be a 2D list of numeric values."
# Validate matrix structure and consistency
if len(matrix) == 0 or any(not isinstance(row, list) for row in matrix):
return "Invalid input: matrix must be a 2D list with at least one row."
column_count = len(matrix[0])
if column_count == 0:
return "Invalid input: matrix rows must contain at least one value."
if any(len(row) != column_count for row in matrix):
return "Invalid input: all rows in matrix must have the same number of columns."
# Convert entries to floats and ensure finiteness
numeric_rows: List[List[float]] = []
for row in matrix:
numeric_row: List[float] = []
for value in row:
try:
numeric_value = float(value)
except Exception:
return "Invalid input: matrix must contain numeric values."
if not np.isfinite(numeric_value):
return "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 "Invalid input: matrix must contain at least one numeric value."
# Validate boolean flags
if not isinstance(full_matrices, bool):
return "Invalid input: full_matrices must be a boolean."
if not isinstance(compute_uv, bool):
return "Invalid input: compute_uv must be a boolean."
if not isinstance(overwrite_a, bool):
return "Invalid input: overwrite_a must be a boolean."
if not isinstance(check_finite, bool):
return "Invalid input: check_finite must be a boolean."
# Normalize lapack_driver and return_type values
if not isinstance(lapack_driver, str):
return "Invalid input: lapack_driver must be 'gesdd' or 'gesvd'."
normalized_driver = lapack_driver.lower()
if normalized_driver not in {"gesdd", "gesvd"}:
return "Invalid input: lapack_driver must be 'gesdd' or 'gesvd'."
if not isinstance(return_type, str):
return "Invalid input: return_type must be 'u', 's', or 'vh'."
normalized_return_type = return_type.lower()
if normalized_return_type not in {"u", "s", "vh"}:
return "Invalid input: 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"scipy.linalg.svd error: {exc}"
# Ensure results are finite before converting back to Python lists
if not np.all(np.isfinite(singular_values)):
return "scipy.linalg.svd error: result contains non-finite values."
if normalized_return_type == "s":
return [np.asarray(singular_values, dtype=float).tolist()]
if not compute_uv:
return "Invalid input: compute_uv must be True when return_type is 'u' or 'vh'."
if normalized_return_type == "u":
if not np.all(np.isfinite(u_matrix)):
return "scipy.linalg.svd error: result contains non-finite values."
return np.asarray(u_matrix, dtype=float).tolist()
if not np.all(np.isfinite(vh_matrix)):
return "scipy.linalg.svd error: result contains non-finite values."
return np.asarray(vh_matrix, dtype=float).tolist()