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 decompose
  • full_matrices (bool, optional, default: true): If True, U and Vh have full shapes; if False, reduced shapes
  • compute_uv (bool, optional, default: true): If True, computes U, S, Vh; if False, returns only singular values
  • overwrite_a (bool, optional, default: false): If True, allows overwriting the input matrix to improve performance
  • check_finite (bool, optional, default: true): If True, scipy checks that input contains only finite numbers
  • lapack_driver (str, optional, default: “gesdd”): LAPACK driver to use for the computation
  • svd_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

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

2D list containing numeric values to decompose
If True, U and Vh have full shapes; if False, reduced shapes
If True, computes U, S, Vh; if False, returns only singular values
If True, allows overwriting the input matrix to improve performance
If True, scipy checks that input contains only finite numbers
LAPACK driver to use for the computation
Component to return from the decomposition