# Implement Hardware-Efficient Complex Partial-Systolic Matrix Solve Using QR Decomposition with Diagonal Loading

This example shows how to implement a hardware-efficient least-squares solution to the complex-valued matrix equation

using the Complex Partial-Systolic Matrix Solve Using QR Decomposition block. This method is known as diagonal loading, and is known as a regularization parameter.

### Diagonal Loading Method

When you set the regularization parameter to a non-zero value in block Complex Partial-Systolic Matrix Solve Using QR Decomposition, then the block computes the the least-squares solution to

where is an n-by-n identity matrix and is an array of zeros of size n-by-p.

This method is known as diagonal loading, and is known as a regularization parameter. The familiar textbook least-squares solution for this equation is the following, which is derived by multiplying both sides of the equation by and taking the inverse of the matrix on the left-hand side.

Complex Partial-Systolic Matrix Solve Using QR Decomposition block computes the solution efficiently without computing an inverse by computing the QR decomposition, transforming

in-place to upper-triangular R, and transforming

in-place to

and solving the transformed equation .

### Define Matrix Dimensions

Specify the number of rows in matrices A and B, the number of columns in matrix A, and the number of columns in matrix B.

m = 300; % Number of rows in matrices A and B n = 10; % Number of columns in matrix A p = 1; % Number of columns in matrix B

### Define the Regularization Parameter

When the regularization parameter is non-zero in block Complex Partial-Systolic Matrix Solve Using QR Decomposition, then the diagonal-loading method is used. When the regularization parameter is zero, then the equations reduce to the regular least-squares formula AX=B.

regularizationParameter = 1e-3;

### Block Parameters

### Generate Random Least-Squares Matrices

For this example, use the helper function `complexRandomLeastSquaresMatrices`

to generate random matrices A and B for the least-squares problem AX=B. The matrices are generated such that the elements of A and B are between -1 and +1, and A has rank r.

rng('default') r = 3; % Rank of matrix A [A,B] = fixed.example.complexRandomLeastSquaresMatrices(m,n,p,r);

### Select Fixed-Point Data Types

Use the helper function `complexQRMatrixSolveFixedpointTypes`

to select fixed-point data types for input matrices A and B, and output X such that there is a low probability of overflow during the computation.

The real and imaginary parts of the elements of A and B are between -1 and 1, so the maximum possible absolute value of any element is sqrt(2).

max_abs_A = sqrt(2); % Upper bound on max(abs(A(:)) max_abs_B = sqrt(2); % Upper bound on max(abs(B(:)) precisionBits = 24; % Number of bits of precision T = fixed.complexQRMatrixSolveFixedpointTypes(m,n,max_abs_A,max_abs_B,precisionBits); A = cast(A,'like',T.A); B = cast(B,'like',T.B); OutputType = fixed.extractNumericType(T.X);

### Open the Model

```
model = 'ComplexPartialSystolicQRDiagonalLoadingMatrixSolveModel';
open_system(model);
```

The Data Handler subsystem in this model takes complex matrices A and B as inputs. The `ready`

port triggers the Data Handler. After sending a true `validIn`

signal, there may be some delay before `ready`

is set to false. When the Data Handler detects the leading edge of the `ready`

signal, the block sets `validIn`

to true and sends the next row of A and B. This protocol allows data to be sent whenever a leading edge of the `ready`

signal is detected, ensuring that all data is processed.

### Set Variables in the Model Workspace

Use the helper function `setModelWorkspace`

to add the variables defined above to the model workspace. These variables correspond to the block parameters for the Complex Partial-Systolic Matrix Solve Using QR Decomposition block.

numSamples = 1; % Number of sample matrices fixed.example.setModelWorkspace(model,'A',A,'B',B,'m',m,'n',n,'p',p,... 'regularizationParameter',regularizationParameter,... 'numSamples',numSamples,'OutputType',OutputType);

### Simulate the Model

out = sim(model);

### Construct the Solution from the Output Data

The Complex Partial-Systolic Matrix Solve Using QR Decomposition block outputs data one row at a time. When a result row is output, the block sets `validOut`

to true. The rows of X are output in the order they are computed, last row first, so you must reconstruct the data to interpret the results. To reconstruct the matrix X from the output data, use the helper function `matrixSolveModelOutputToArray`

.

X = fixed.example.matrixSolveModelOutputToArray(out.X,n,p,numSamples);

### Verify the Accuracy of the Output

To evaluate the accuracy of the Complex Partial-Systolic Matrix Solve Using QR Decomposition block, compute the relative error.

```
A_lambda = [regularizationParameter * eye(n);A];
B_0 = [zeros(n,p);B];
relative_error = norm(double(A_lambda*X - B_0))/norm(double(B_0)) %#ok<NOPTS>
```

relative_error = 1.0386e-04