QR
Overview
The QR function computes the QR decomposition of a real-valued matrix such that , where is orthogonal and is upper triangular. This factorization underpins linear least-squares solvers, numerical stabilization routines, and eigenvalue algorithms. The implementation calls scipy.linalg.qr in full mode and exposes a streamlined interface that returns either the orthogonal factor or the upper-triangular factor. Advanced SciPy options such as pivoting, overwrite flags, or economy modes are not available in this Excel wrapper. This example function is provided as-is without any representation of accuracy.
Usage
To use the function in Excel:
=QR(a, return_type)a(2D list, required): Matrix to decompose. Each row must have the same number of columns, and entries must be finite numeric values. Scalars are treated as 1x1 matrices.return_type(str, required): Either"Q"to return the orthogonal matrix or"R"to return the upper triangular matrix. The argument is case-insensitive.
The function returns a 2D list of floats representing the requested factor. If validation fails, an error message (string) is returned instead.
Examples
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 (rounded to 3 decimals):
| Result | |
|---|---|
| -0.316 | -0.949 |
| -0.949 | 0.316 |
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 (rounded to 3 decimals):
| Result | |
|---|---|
| -3.162 | -4.427 |
| 0.000 | -0.632 |
Example 3: Orthogonal factor of a 3x2 matrix
Inputs:
| a | return_type | |
|---|---|---|
| 1 | 2 | Q |
| 3 | 4 | |
| 5 | 6 |
Excel formula:
=QR({1,2;3,4;5,6}, "Q")Expected output (rounded to 3 decimals):
| Result | ||
|---|---|---|
| -0.169 | 0.897 | 0.408 |
| -0.507 | 0.276 | -0.816 |
| -0.845 | -0.345 | 0.408 |
Example 4: Upper-triangular factor of a 3x2 matrix
Inputs:
| a | return_type | |
|---|---|---|
| 1 | 2 | R |
| 3 | 4 | |
| 5 | 6 |
Excel formula:
=QR({1,2;3,4;5,6}, "R")Expected output (rounded to 3 decimals):
| Result | |
|---|---|
| -5.916 | -7.437 |
| 0.000 | 0.828 |
| 0.000 | 0.000 |
Python Code
from typing import List, Union
import numpy as np
from scipy.linalg import qr as scipy_qr
ScalarValue = Union[float, int, bool, str, None]
MatrixInput = Union[ScalarValue, List[List[ScalarValue]]]
MatrixOutput = Union[List[List[float]], str]
def qr(a: MatrixInput, return_type: str) -> MatrixOutput:
"""
Compute the QR decomposition of a matrix and return either Q or R.
Args:
a: 2D list (or scalar interpreted as a 1x1 matrix) containing numeric values to decompose.
return_type: 'Q' to return the orthogonal matrix Q, 'R' to return the upper triangular matrix R (case-insensitive).
Returns:
2D list representing the requested matrix (Q or R), 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(a, list):
if isinstance(a, (int, float, bool)):
a = [[float(a)]]
elif isinstance(a, str):
try:
a = [[float(a)]]
except Exception:
return "Invalid input: a must be numeric or a 2D list of numeric values."
else:
return "Invalid input: a must be a 2D list or scalar numeric value."
# Validate the 2D list structure and ensure consistent row lengths
if not a or not all(isinstance(row, list) for row in a):
return "Invalid input: a must be a 2D list with at least one row."
if any(len(row) == 0 for row in a):
return "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 "Invalid input: all rows in a must have the same length."
# Convert entries to floats and check for finite values
numeric_rows: List[List[float]] = []
for row in a:
numeric_row: List[float] = []
for value in row:
try:
numeric_value = float(value)
except Exception:
return "Invalid input: a must contain only numeric values."
if not np.isfinite(numeric_value):
return "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 "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_qr(array, mode="full")
except Exception as exc:
return f"scipy.linalg.qr error: {exc}"
result = q_matrix if normalized_return_type == "Q" else r_matrix
# Ensure the result is finite before returning to Excel
if not np.all(np.isfinite(result)):
return "scipy.linalg.qr error: result contains non-finite values."
return result.tolist()