EXPM

The matrix exponential extends the scalar exponential to square matrices and appears in systems of linear differential equations, control theory, and Markov processes.

It is defined by the convergent power series:

e^A = \sum_{k=0}^{\infty} \frac{A^k}{k!}

This function computes e^A for a square input matrix using SciPy’s stable scaling-and-squaring implementation.

Excel Usage

=EXPM(matrix)
  • matrix (list[list], required): Square matrix of values convertible to complex numbers

Returns (list[list]): 2D matrix exponential, or error message string.

Example 1: Matrix exponential of 2x2 zero matrix returns identity

Inputs:

matrix
0 0
0 0

Excel formula:

=EXPM({0,0;0,0})

Expected output:

Result
1 0
0 1
Example 2: Matrix exponential of nilpotent 2x2 matrix

Inputs:

matrix
0 1
0 0

Excel formula:

=EXPM({0,1;0,0})

Expected output:

Result
1 1
0 1
Example 3: Matrix exponential of 3x3 zero matrix returns identity

Inputs:

matrix
0 0 0
0 0 0
0 0 0

Excel formula:

=EXPM({0,0,0;0,0,0;0,0,0})

Expected output:

Result
1 0 0
0 1 0
0 0 1
Example 4: Matrix exponential of arbitrary 2x2 matrix

Inputs:

matrix
1 2
-1 3

Excel formula:

=EXPM({1,2;-1,3})

Expected output:

Result
-2.22535 12.4354
-6.21768 10.21

Python Code

import numpy as np
from scipy.linalg import expm as scipy_expm

def expm(matrix):
    """
    Compute the matrix exponential of a square matrix using scipy.linalg.expm

    See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.expm.html

    This example function is provided as-is without any representation of accuracy.

    Args:
        matrix (list[list]): Square matrix of values convertible to complex numbers

    Returns:
        list[list]: 2D matrix exponential, or error message string.
    """
    try:
        # Threshold for treating values as effectively zero
        EPSILON = 1e-12

        def to2d(x):
            """Normalize single-cell input to 2D list."""
            return [[x]] if not isinstance(x, list) else x

        def format_complex_value(value):
            """Format complex number for output."""
            real_part = float(value.real)
            imag_part = float(value.imag)
            if abs(imag_part) <= EPSILON:
                return real_part
            elif abs(real_part) <= EPSILON:
                return f"{imag_part}j"
            else:
                sign = "+" if imag_part >= 0 else "-"
                imag_value = abs(imag_part)
                return f"{real_part}{sign}{imag_value}j"

        # Normalize input - Excel may provide single-cell 2D range as a scalar
        matrix = to2d(matrix)

        # Validate that matrix is a non-empty 2D list of rows with consistent length
        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."
        size = len(matrix)
        if any(len(row) != size for row in matrix):
            return "Error: Invalid input: matrix must be square."

        # Convert to a numeric numpy array, rejecting values that cannot form complex numbers
        numeric_rows = []
        for row in matrix:
            numeric_row = []
            for value in row:
                try:
                    numeric_row.append(complex(value))
                except Exception:
                    return "Error: Invalid input: matrix entries must be numeric values."
            numeric_rows.append(numeric_row)

        arr = np.array(numeric_rows, dtype=np.complex128)
        if not np.isfinite(arr.real).all() or not np.isfinite(arr.imag).all():
            return "Error: Invalid input: matrix entries must be finite numbers."

        # Delegate matrix exponential to SciPy and capture runtime errors
        try:
            result = scipy_expm(arr)
        except Exception as exc:
            return f"Error: scipy.linalg.expm error: {exc}"

        # Convert result matrix into Excel-friendly values without altering precision
        output = []
        for row in result:
            output_row = []
            for value in row:
                real_part = float(value.real)
                imag_part = float(value.imag)
                if not np.isfinite(real_part) or not np.isfinite(imag_part):
                    return "Error: scipy.linalg.expm error: non-finite result encountered."
                output_row.append(format_complex_value(value))
            output.append(output_row)

        return output
    except Exception as e:
        return f"Error: {str(e)}"

Online Calculator

Square matrix of values convertible to complex numbers