You are on page 1of 3

# UoR: Applied Linear Algebra, Assignment 1

Victor Liu

## July 10, 2010

1. Complex numbers can be encoded in matrix form so that matrix multiplication corresponds to
multiplication of the complex numbers. Suppose a complex number is of the form z1 = a + ib.
For another complex number z2 = c + id, the product is z1 z2 = (ac − bd) + i(bc + ad). Fill in
the missing elements of the complex number encoding:
 
a ?
z1 =
b ?

Hint: You don’t need to know anything about complex numbers for this problem. Write out a
template for z2 and try to multiply the matrices together to fill in what the missing elements
should be.
Aside: All complex matrices can be written as real matrices using this encoding; their dimen-
sions are just doubled. You will see that the inverse of the matrix corresponds to the complex
reciprocal, and complex division can be carried out like this. If I don’t remind you to check
back here, look out for the special meaning of the determinant in this context!

2. A permutation matrix is a square matrix P ∈ Rm×m , which when multiplying another matrix
A ∈ Rm×n from the left (form the product P A), simply rearranges the rows of A.

(a) Describe the general form of P . Hint: the identity matrix is a trivial permutation matrix.
(b) Suppose you are given a specification of the new order of the rows of A in the form a list
of natural numbers i1 , . . . , im , where A has m rows, and each of the i is a row number.
How do you generate P ? Write a function that takes a specification for the new row
order of A, and generates the matrix P . The function should have the prototype

void roworder_to_permutation_matrix_d(
int m, const int *s,
double *P, int ldP);

## where m is the number of rows of P , s is a length m list of 0-based row indexes of A, P

is the output matrix, assumed to be an array of length ldP×m, and ldP is the leading
dimension of P (which must be at least m).
(c) A permutation matrix is often represented by a sequence of row swaps. The swaps are
represented by a list of natural numbers s1 , . . . , sm . The first number s1 is the row
which should be swapped with the first row of A, the second number s2 is the row which
should be swapped with the second row of A, etc. When sk = k, that means the k-th

1
row should be swapped with itself, which does nothing. Write a function that takes a
sequence of row swaps, and generates the resulting permuted list of row indexes of A.
The function should have the prototype
void rowswaps_to_roworder(
int m, const int *s, int *i);
where m is the number of rows of P , s is a length m list of 0-based row indexes. Element
s[k] should be swapped with row offset k. The parameter i is the output list, assumed
length m, which contains the new list of 0-based row indexes.
(d) If instead we wish to rearrange the columns of A, what should we do?
(e) Every permutation matrix P has an inverse P −1 , which simply undoes the rearrangement
generated by P . Given P , how do we compute P −1 ? Hint: no knowledge of how to
compute inverses is necessary for this problem, just think about the structure of P .
(f) Write a function which, given a sequence of row swaps (as specified above), applies the
row permutation matrix to a given matrix. This function should also be able to apply
the inverse, and it should also be able to apply the swaps to the columns of the given
matrix. The function should have the prototype
void apply_swaps_d(
char side, char inv,
int m, int n,
const int *s,
const double *A, int ldA);
where m and n are the number of rows and columsn, respectively, of the given matrix A,
s is the length m list of 0-based row swaps, A is the pointer to the first element of the
given matrix, and ldA is the leading dimension of A (at least m). If side is L, then the
permutation matrix is applied on the left of the matrix, or if it is R then it is applied on
the right. If inv is I, then the inverse of the permutation matrix is used, otherwise the
permutation matrix is unaltered.
Be careful with the indexes; they are 0-based (1 less than the row numbers when we use math-
speak). Code carefully, for we will use these functions later when we discuss LU decopositions
for solving linear systems.

Using BLAS
Although you don’t strictly need to, you should use the BLAS routine DSWAP. The C declaration
on a 32-bit machine is
void dswap_(
const int *n,
double *x,
const int *incx,
double *y,
const int *incy
);

2
An equivalent C++ definition is

void dswap_(
const int &n,
double *x,
const int &incx,
double *y,
const int &incy
);

which is more convenient due to not needing addresses. Note that one standard convention of
calling Fortran functions appends an underscore to the end of the name. This is the most common
convention (used by GCC) which I assume here. Depending on which precompiled library you use,
there may be no underscores, or a leading underscore, or some other wacky combination. You need
to determine the “name mangling” convention.