Matrix
Matrix
Version: 1.2
Contents
I Foreword 3
I.1 General Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
II Introduction 6
II.1 Greek alphabet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
II.2 Graphical Processing Units . . . . . . . . . . . . . . . . . . . . . . . . 7
II.3 Fused Multiply-Accumulate . . . . . . . . . . . . . . . . . . . . . . . . 8
II.4 Vector space . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
II.5 Linear maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
II.6 Composition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
IX Exercise 05 - Cosine 27
IX.0.1 Goal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
IX.0.2 Instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
IX.1 Pearson correlation coefficient . . . . . . . . . . . . . . . . . . . . . . 29
1
Enter the Matrix An introduction to Linear Algebra
X.0.2 Instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
X.1 Wedge product and exterior algebra . . . . . . . . . . . . . . . . . . . 32
2
Chapter I
Foreword
It is the study of vector spaces, which consist of objects called vectors. Tranformations
of vectors, called linear maps, are generally represented as objects called "matrices" in
the most usual (finite-dimensional) case. There also exist other, more complex, kinds
of vector spaces: like real or complex polynomials, and function spaces. Linear algebra
allows us to study these diverse subjects within a unifying framework. This makes the
more complicated cases easier to understand, since their properties are generally the same
as the simple cases, and so you can use the simple cases to mentally visualize what would
happen in the complicated ones. For this reason, we will concentrate on the fundamental
case of finite-dimensional vectors and matrices, with an emphasis on 2D and 3D, which
can easily be visualized.
Also, video games are basically just playful physical simulations: so video games
use linear algebra a lot! Want Mario to jump? You will either need a "jump impulse
vector" to force him upwards, and a "gravity" vector to bring him back down; or you
will need a degree 2 polynomial to make the jump curve. Want to make cinema-level
CGI? Raytracing is just a simulation of how light works, and that’s just bouncing vectors
called "rays". All of these objects are mostly defined through linear algebra. Not only
that, but "2D" and "3D" (ie, the notion of "dimension"), are terms that originate from
linear algebra. Computer graphics are chock-full of vectors, and their transformation
through matrices. Want to rotate a 2D sprite for a fire spell? That’s a matrix. Want
3
Enter the Matrix An introduction to Linear Algebra
to create a 3D camera for an FPS? That’s a matrix. The GPU was basically invented
to handle linear algebra operations well (see below). High Performance Computing and
Numerical Analysis thus depend on linear algebra a lot.
Statistics (and thus data science and machine learning) is also mostly based on linear
algebra. Numerical data is often represented as vectors (a "data point cloud") in large-
dimensional vector spaces. There are important analogies to draw between statistical
concepts (respectively: covariance, variance, standard deviation, Pearson correlation co-
efficient, normalizing a Gaussian curve) and linear algebra operations (respectively: dot
product, quadratic norm, norm, cosine of the angle between two vectors, normalizing a
vector). Understanding the geometry of linear algebra is thus very useful to understand
the geometry underlying statistics.
There are many, many more uses of linear algebra and its variants (in everything from
cryptography to ecology) but what we listed here were the most frequent use cases in
practice. Once you learn it, you will be seeing it more and more around you.
Because of its importance, because of how few prerequisites it actually needs when
learning it (other than basic arithmetic), and because of all the domains of mathematics
and science for which it opens the way, linear algebra has been chosen as the standard
entry point into higher mathematics, all around the world. We hope you will enjoy how
useful it is in practice as much as we do!
4
Enter the Matrix An introduction to Linear Algebra
• We recommend that you use paper if you need to. Drawing visual models, making
notes of technical vocabulary... This way, it will be easier to wrap your head around
the new concepts you will discover, and use them to build your understanding for
more and more related concepts. Also, doing computations by head is really hard
and error-prone, so having all the steps written down helps you figure out where
you made a mistake when you did.
• Don’t stay stuck because you don’t know how to solve an exercise: make use of
peer-learning! You can ask for help on Slack (42 or 42-AI) or Discord (42-AI) for
example.
• You are not allowed to use any mathematical library, even the one included in your
language’s standard library, unless explicitly stated otherwise.
• For every exercise you may have to respect a given time and/or space complexity.
These will be checked during peer review.
• Both have to be calculated against the size of the function’s input (a number,
the length of a string, etc...).
5
Chapter II
Introduction
For this module, we highly recommend the series of videos Essence of linear algrebra by
3blue1brown, which provides a very good, comprehensive and visual explaination of this
topic.
These videos are so good, you will probably want to watch them once before working
on this module, you will be going back to specific parts of them during the module, and
you will want to rewatch them once again after this module, perhaps a couple of months
after. We’re not kidding.
Many people to whom we had recommended these videos before getting into game
physics programming, data science or computer graphics decided not to watch them
until much later. The reaction was UNANIMOUS: those who had watched the videos
had nothing but praise about how incredibly helpful they had been; those who had only
watched the videos later in their learning of linear algebra deeply regretted the time that
they wouldn’t have wasted, had they watched the videos from the start.
Don’t waste your time. WATCH. THE. VIDEOS. Even if you don’t understand
everything at first, the ordered presentation and the geometric visuals will provide you
with a good amount of contextual background and mental models that will prove essential
as you learn the various aspects of linear algebra.
As you may know, mathematics (and physics) use the Greek alphabet a lot. If you want
to learn it, here it is:
6
Enter the Matrix An introduction to Linear Algebra
As stated by the name, GPUs were originally targeted towards graphical computa-
tions, which rely heavily on running linear algebra operations. Because of the ubiquity of
linear algebra in mathematics, the use of GPUs was extended to more than video games
and CGI, and most supercomputing today relies on GPU computation.
Many modern CPUs have also taken inspiration from the SIMD model of computation,
and allow for specific SIMD operations.
The operations of linear algebra consist mostly of: summing vectors (a coordinate-wise
7
Enter the Matrix An introduction to Linear Algebra
addition of two vectors), scaling vectors (multiplying all coordinates of a given vector by
the same real or complex number), and matrix multiplications. Matrix multiplications are
just a repeated succession of an operation called the dot product (or inner product)
of two vectors. All of these operations are very well adapted to SIMD, since they are
just a succession of additions or multiplications over arrays of data (which represent our
vectors). Coding these various operations to understand them is a fundamental exercise.
For this reason, you will get to code them all during this module.
Under the x86 architecture, there exist the instructions called: vfmadd132ps, vfmadd213ps
and vfmadd231ps (welcome to x86 :D), which allow us to compute what’s called the Fused
Multiply-Accumulate operation.
Check what these instructions do, and you will realize that they might become useful.
;)
The standard library of the C language (as well as that of many other languages) has
a function to perform this operation (but we’re not telling you which one, so search by
yourself!).
The following, which is a concise-but-terse list of theoretical info about vector spaces, can
probably be useful for you to visit and revisit as you work on this module. It helps to work
both practical applications and theory together, in order to gradually build up a deeper
understanding. Don’t feel discouraged if you don’t understand everything immediately:
that is obviously normal when approaching a new ecosystem of information.
If you remember the concept of "(algebraic) groups" from the Boolean Algebra module,
this section will be a lot easier to understand (if you haven’t done that module yet,
we recommend you to do it, since sets, logic and algebraic structures are even more
fundamental than linear algebra).
Understanding things from the point of view of algebraic structures can seem difficult
at first, since there is a lot of vocabulary. However, this vocabulary is incredibly useful,
because it transforms the mathematical properties of various sets into something simple,
like knowing the rules of a card game. What you’re allowed to do, and what is forbidden.
If you can remember 4-5 board games’ or card games’ rules, you definitely have what it
takes to learn the language of algebraic structures (often called "abstract algebra", which
is a misleadingly scary name).
Actually, it’s really not that complicated to learn, because it’s basically ONLY a
question of learning vocabulary, and not learning complex algorithmic methods. For
this reason, we thought it was worthwhile to include the following: what follows is the
8
Enter the Matrix An introduction to Linear Algebra
definition of a vector space, the principal type of structure that is studied in linear
algebra, from the point of view of "algebraic structures" (ie, the rules that can be used
over a certain set, in order to make that set become a "vector space").
• A field K (roughly put: an algebraic structure where you can add, subtract, multi-
ply and divide elements under the rules of usual arithmetic). The elements of K are
called "scalars". K is generally chosen to be the real numbers or the complex num-
bers. Real numbers are generally represented as floats; complex numbers as pairs
of floats, with a special multiplication and division. We generally denote scalars
with Greek letters.
The operation of scalar multiplication must also fullfill the following properties:
• Scalar multiplication takes two elements, one in K, one in V , and returns an element
of V :
λ ∈ K, ∀u ∈ V, λu ∈ V
∀λ ∈ K, ∀(u, v) ∈ V 2 , λ(u + v) = λu + λv
∀(λ, µ) ∈ K2 , ∀u ∈ V, (λ + µ)u = λu + µu
9
Enter the Matrix An introduction to Linear Algebra
∀u ∈ V, 1K u = u
For the full, thorough list of the axioms/properties (ie, the "rules of the game") of
vector spaces, do check the wikipedia page for Vector space
Linear algebra also studies a special type of vector space, called a "Euclidean space"
(also called Inner Product Space or IPS) to which we add another operator, the famous
dot product (inner product). This operator takes two vectors and returns a scalar.
Many other objects of study in physics and other domains that depend on linear algebra
are just "vector spaces with some extra structure" (eg: topological vector spaces, met-
ric spaces, manifolds, vector fields, K-algebras, Lie algebras, tensor algebras, geometric
algebras, function spaces of random vectors...)
If these properties are verified, we say that f is mapping values linearly from the
vector space V to a new vector space W . Geometrically, "linearly" means that any two
lines that are parallel in the input space are kept parallel after the transformation (those
who watched 3blue1brown should know that by now).
These are necessary and sufficient conditions: to prove that f is linear, you must
prove that the above two equations are true. See: Necessity and sufficiency. Note that
the second equation implies that the null vector 0V of the input space V (the vector with
only zeros as coefficients) is mapped to the null vector 0W of the output space W .
10
Enter the Matrix An introduction to Linear Algebra
You can also understand what is going on with the following diagrams (called com-
mutative diagrams, in category theory):
(f,f )
(u, v) ∈ V × V (f (u), f (v)) ∈ W × W
+V +W
f
u+v ∈V f (u + v) = f (u) + f (v) ∈ W
(idK ,f )
(λ, u) ∈ K × V (λ, f (u)) ∈ K × W
∗V ∗W
f
λu ∈ V f (λu) = λf (u) = W
(f,f )
V ×V W ×W
+V +W
f
V W
(idK ,f )
K ×V K ×W
∗V ∗W
f
V W
These commutative diagrams, when true, mean that you can take whichever path
from the starting point (two elements of V ) to the end point (a single element of W ), and
you will arrive at the same result. The choice of first "applying f " or "using the vector
space operator" doesn’t matter, so long as the other operation is what follows. Try to stop
for a second to understand how these diagrams are exactly equivalent to the equations
for linearity written above. This will help you unpack what’s happening in more detail.
The set of linear maps from V to W is generally denoted L(V, W ), and the space
of matrices from V to W for given bases B on V , and C on W , is generally denoted
MatB,C (V, W ), or more simply, Kdim(W )×dim(V ) (the output space’s dimension is the left
operand!).
So for example, the space of 2-by-3 matrices with real numbers as coefficients (aka
2-by-3 real matrices) is R2×3 , and corresponds to real linear maps from R3 to R2 , aka
L(R3 , R2 ).
11
Enter the Matrix An introduction to Linear Algebra
A very important fact to note is that spaces of matrices are also vector spaces, since
they abide by the vector space axioms (you can scale matrices, as well as add matrices
of the same shape).
8 2 3 3.73
7 5 0 −1
17 −32.3 −4 5
f (u) = v ⇔ Au = v
Thus:
and
A(λu) = λ(Au) = (λA)u, 1-homogeneity means matrices commute with scalar multi-
plication of vectors.
The identity matrix (often denoted In ), is a square matrix of size n × n which has no
effect on the vector when multiplied with that vector.
Where δ is the Kronecker delta. This means that the identity matrix has 1s along
its principal diagonal, and 0s everywhere else.
For a given matrix A, the element of the matrix at the line i and column j is denoted
Aij .
1 0 0
0 1 0
0 0 1
When you’ve got a handle on matrix multiplication, try to work out how ∀v ∈
R , I3 v = vI3 = v.
3
12
Enter the Matrix An introduction to Linear Algebra
II.6 Composition
When working on matrices, the composition operator for linear maps can be under-
stood simply as successive matrix multiplications. This means that matrix multipli-
cation AB between matrices A and B works if, and only if, the number of
columns of A matches the number of rows of B.
(f ◦ g ◦ h)(u) = A × B × C × u = ABCu
13
Chapter III
Code constraints
struct Vector::<K> {
// ...
}
struct Matrix::<K> {
// ...
}
The above structures are declared in Rust, and correspond to a store of data, with
no method. Feel free to adapt them to your language’s most appropriate syntax (and to
add your methods to them if that’s the design choice you go for).
In what follows, the prototypes of the function will define generic arguments for each
functions. However, you only have to implement it for real numbers, which will be defined
as the type f32, which is what you should understand when you see K. Do note, however,
that there is a bonus at the end of this module which is to re-do every exercise with the
field K being implemented as your own Complex number type, rather than f32. If you’ve
done your work in a nice and generic way, this shouldn’t prove too much fixing.
14
Enter the Matrix An introduction to Linear Algebra
Some of the prototypes given in Rust are more "pseudocode" than actual code: a good
linear algebra library in Rust would leverage the Rust trait system, and you would thus
need to specify the traits implemented by your generics in the signatures. Generally,
it should even be expected that the generic types provided would actually have some
form of type constraint in a real implementation (for example, making a Field type, and
having the generic K extend Field; this is especially the case for functional languages).
It is thus expected that the examples in some exercises, as they are, may not compile.
Also, in most of the exercises in this module, we may generally decide for V to be
any sort of vector space, of finite dimension, over its scalar field K. So V , as a generic,
means a set that may contain scalars, or vectors, or matrices, or tensors, etc...
Finally, many of the exercises’ functions store their result within one of their inputs.
This is a choice. This type of function can be much faster when using your object as an
accumulator, but you might want to have the inputs be immutable instead (ie, a "pure
function"), and simply return your value. If your language of choice does not permit such
object-oriented constructs, or if you simply prefer the pure function syntax, you are of
course allowed to instead have a function that returns a scalar/vector/matrix as output,
but keeps its inputs immutable. You may also implement both versions, if you find it
worthwhile: the pure function, and the accumulating function. We do ask some amount
of coherence though: if you choose to implement only one version, stick to your choice
throughout the module.
Conclusion: there is thus some level of freedom of interpretation left to the student
and their evaluator as to verify if the function signature is valid. What is really important
is that the underlying mathematical function is implemented in a way that is:
• generic, so that the overall library of code written during this module may work
with other fields than the real numbers;
15
Chapter IV
Exercise : 00
IV.0.1 Goal
You must write functions that can add and subtract two vectors, or two matrices, of the
same size; and a function to multiply a vector, or a matrix, by a scalar (ie, "scaling").
You must also turn in a main function in order to test your functions, ready to be
compiled (if necessary) and run.
IV.0.2 Instructions
- The second one must compute the subtraction of a vector by another vector.
16
Enter the Matrix An introduction to Linear Algebra
impl<K> Vector<K> {
fn add(&mut self, v: &Vector<K>);
fn sub(&mut self, v: &Vector<K>);
fn scl(&mut self, a: K);
}
impl<K> Matrix<K> {
fn add(&mut self, v: &Matrix<K>);
fn sub(&mut self, v: &Matrix<K>);
fn scl(&mut self, a: K);
}
Examples:
17
Enter the Matrix An introduction to Linear Algebra
println!("{}", u);
// [8.0, 6.0]
// [1.0, 6.0]
18
Chapter V
Exercise : 01
Linear combination
Allowed mathematical functions : fused multiply-add function
Maximum time complexity : O(n)
Maximum space complexity : O(n)
V.0.1 Goal
You must write a function that computes a linear combination of the vectors provided,
using the corresponding scalar coefficients.
You must also turn in a main function in order to test your function, ready to be
compiled (if necessary) and run.
V.0.2 Instructions
• Let u = (u1 , ..., uk ) ∈ V k be a list of size k, containing vectors (V is a vector space).
You must calculate the linear combination of the vectors of u scaled by their respective
19
Enter the Matrix An introduction to Linear Algebra
coefficients in λ.
If the two arrays provided as input are not of the same size, or if the array’s contents
are incoherent, the result is undefined.
Examples:
20
Chapter VI
Exercise : 02
Linear interpolation
Allowed mathematical functions : fused multiply-add function
Maximum time complexity : O(n)
Maximum space complexity : O(n)
VI.0.1 Goal
You must write a function that computes a linear interpolation between two objects of
the same type.
You must also turn in a main function in order to test your function, ready to be
compiled (if necessary) and run.
VI.0.2 Instructions
• Let t ∈ [0; 1](⊂ R) (ie, t is real, and 0 ≤ t ≤ 1) be a scalar.
• Let f : (V × V × [0; 1]) → V be the function to implement.
21
Enter the Matrix An introduction to Linear Algebra
• If t = 0, then f (u, v, t) = u.
• If t = 1, then f (u, v, t) = v.
• If t = 0.5, then the function returns a value at the exact middle in between of u
and v (the isobarycenter, which can be understood as the center of gravity, of the
two points).
Examples:
22
Chapter VII
Exercise : 03
Dot product
Allowed mathematical functions : fused multiply-add function
Maximum time complexity : O(n)
Maximum space complexity : O(n)
VII.0.1 Goal
You must write a function that computes the dot product of two vectors of the same
dimension.
You must also turn in a main function in order to test your function, ready to be
compiled (if necessary) and run.
VII.0.2 Instructions
Let u, v ∈ V , where V is a vector space of finite dimension over the real numbers R
(represented as the type f32).
The function must compute and return the scalar ⟨u|v⟩ = u·v, called the dot product,
or inner product, of u and v.
23
Enter the Matrix An introduction to Linear Algebra
impl<K> Vector::<K> {
fn dot::<K>(&self, v: Vector::<K>) -> K;
}
Examples:
If you’re curious about vector spaces of complex numbers, and already know enough
about complex numbers, you might want to look up the terms conjugate transpose,
sesquilinear algebra, and Pre-Hilbert space.
24
Chapter VIII
Exercise 04 - Norm
Exercise : 04
Norm
Allowed mathematical functions : fused multiply-add function, pow, max
Maximum time complexity : O(n)
Maximum space complexity : O(n)
VIII.0.1 Goal
You must also turn in a main function in order to test your functions, ready to be
compiled (if necessary) and run.
VIII.0.2 Instructions
25
Enter the Matrix An introduction to Linear Algebra
impl<V> Vector::<V> {
fn norm_1::<V>(&mut self) -> f32;
fn norm::<V>(&mut self) -> f32;
fn norm_inf::<V>(&mut self) -> f32;
}
Examples:
Now would be a good time to get interested in what’s called the Triangle inequality for
Euclidean norms. If you’re curious about infinite-dimensional vector spaces (like spaces of
sequences or function), you might want to look at Hölder norms, and the Minkowski
inequality.
You might also want to check out norms specific to vector spaces of matrices, like the
Frobenius norm.
You might also want to check out the "cousin" of norms which can be negative for
a given coordinate. These are called pseudonorms and are important, for example, in
special relativity (also see Lorentz transform, split-complex numbers, hyperbolic geometry).
26
Chapter IX
Exercise 05 - Cosine
Exercise : 05
Cosine
Allowed mathematical functions : fused multiply-add function
Maximum time complexity : O(n)
Maximum space complexity : O(n)
IX.0.1 Goal
You must write functions that compute the cosine of the angle between two given vectors.
You must also turn in a main function in order to test your function, ready to be
compiled (if necessary) and run.
You should use the functions you wrote during the two previous
exercises.
IX.0.2 Instructions
Let u, v ∈ Kn be vectors.
You must compute cos(u, v), the cosine of the angle between the two vectors u and v.
27
Enter the Matrix An introduction to Linear Algebra
Examples:
28
Enter the Matrix An introduction to Linear Algebra
There are a lot of analogies between linear algebra and statistics. The "vector" of proba-
bility and statistics is generally taken to be a random variable. A random variable is a
numerical function. Its input space is a set of possible outcomes, like Ω = {1, 2, 3, 4, 5, 6}
for what a dice can roll, with each outcome having a distinct probability (for example, a
fair dice would have each possible outcome be a probability of 16 ). Such an input space
is called a probabilitity space. The output space of a random variables is a space of
values, generally taken to be R (for example, you gain 3€ for every even roll of the dice,
and lose 3€ for every odd roll).
With this setup, the covariance is the dot product for spaces of random variables,
the variance is their quadratic norm (a squared norm, the dot product of a vector with
itself), and the standard deviation is their norm (the square root of a quadratic norm).
The random variable’s analogue for the cosine is called the Pearson correlation
coefficient. This coefficient is calculated from two random variables using covariance as
your dot product, and then normalizing, like in the usual vector cosine formula.
- If this coefficient is close to 1 (the cosine is close to 1, so the angle is small, and
the two vectors are close to being colinear, with the same orientation), the two random
variables are highly correlated.
- If this coefficient is close to 0 (the cosine is close to 0, so the angle is close to a right
angle, and the two vectors are close to being perpendicular), the two random variables
are not correlated.
- If this coefficient is close to −1 (the cosine is close to −1, so the angle is a large
(almost flat) angle, and the two vectors are close to being colinear, but with opposite
orientation), the two random variables are highly anticorrelated.
This is one of the many examples that highlight how linear algebra can explain the
geometry underlying statistics.
More generally, data science and statistics study data point clouds, which act like
"having only a bunch of samples of the output values taken by a random variable, but no
info about the random variable’s set of events/outcomes (inputs), nor their probabilities".
For this very frequent case, we instead use a concept called a "probability distribution",
which is a way to infer information about the set of possible outcomes Ω and its prob-
abilities, without actually knowing this space, simply based on the prevalence of some
values over others. This is most often how data science is done, since we mostly have ob-
servations, but would like to figure out the underlying model (a hidden random variable),
which should explain how these observations came to be.
Finally, note that there exist random variables that can give multiple output values
(for example, if you roll a 3, you gain 2€, but lose 5 candy bars: that’s a 2D vector
of real values as output). These can be equivalently understood as vectors of random
variables, and are called multivariate random variables, or random vectors. They
are very important in data science since, generally, we’re dealing with multiple different
29
Enter the Matrix An introduction to Linear Algebra
observations - for example, looking at the distribution of size, weight and income (3
different values) over a population of individuals.
30
Chapter X
Exercise : 06
Cross product
Allowed mathematical functions : fused multiply-add function
Maximum time complexity : N/A
Maximum space complexity : N/A
X.0.1 Goal
You must write a function that computes the cross product of two 3-dimensional vectors.
You must also turn in a main function in order to test your function, ready to be
compiled (if necessary) and run.
X.0.2 Instructions
Let u, v ∈ V = R3 be vectors.
31
Enter the Matrix An introduction to Linear Algebra
Examples:
There exists a very important, anticommutative product of two vectors, called the wedge
product (or exterior product, or outer product) which returns an object called a
bivector. Whereas a vector (or 1-vector) is a 1D geometric object (a line with a certain
magnitude and orientation: visualized as a little arrow with a certain length and arrow-
head), a bivector (or 2-vector) is a 2D geometric object (a plane with a certain magnitude
and orientation: visualized as a little parallelogram with a certain area and a direction of
rotation). This parallelogram corresponds precisely to the parallelogram formed by the
two input vectors.
The outer product extends to bivectors and vectors, giving trivectors (3-vectors, which
correspond to a 3D oriented volume), etc. The vector space of all k-vectors up to a
maximal dimension n is called the n-dimensional exterior algebra over a vector
space V and is denoted Λn (V ). These exterior algebras are extremely important in
theories of calculus over higher dimensions, and calculus on curved spaces (a field of
mathematics called differential geometry). If you are interested in advanced physics
in any way, you will probably be dealing with these whether you know it or not.
The cross product is technically the dual (which you can understand as the orthogonal
complement, here, the vector perpendicular to the parallelogram) of the wedge product
of two vectors (bivector/parallelogram). The dual of a k-vector in an n-dimensional is
always an (n − k)-vector. This is why the cross product only makes sense in 3D (and
32
Enter the Matrix An introduction to Linear Algebra
is thus a pretty poor mathematical construct). The wedge product, however, is always
consistent.
Note that in the context of geometric algebras, a kind of vector space whose objects
are called "multivectors", and are sums of k-vectors of various ranks (various values for
k) there is a fundamental construct called the geometric product, which is the sum of
the inner/dot product and the outer/wedge product. Geometric algebras, while complex
to approach at first, offer a profound and beautiful framework that goes beyond linear
algebra and often makes higher mathematics that rely on linear algebra much more
intuitive and natural. Geometric algebra is, so to speak, "the best way" to extend the
objects of linear algebra, and make it an improved system.
33
Chapter XI
Exercise : 07
XI.0.1 Goal
You must write functions that multiply a matrix by a vector or a matrix by a matrix.
You must also turn in a main function in order to test your functions, ready to be
compiled (if necessary) and run.
XI.0.2 Instructions
• Au (which returns a vector in Rm ) (max time complexity O(nm), max space com-
plexity O(nm))
34
Enter the Matrix An introduction to Linear Algebra
• AB (which returns a matrix in Rm×p ) (max time complexity O(nmp), max space
complexity O(nm + mp + np))
impl<K> Matrix::<K> {
fn mul_vec::<K>(&mut self, vec: Vector::<K>) -> Vector::<K>;
fn mul_mat::<K>(&mut self, mat: Matrix::<K>) -> Matrix::<K>;
}
Examples:
let u = Matrix::from([
[1., 0.],
[0., 1.],
]);
let v = Vector::from([4., 2.]);
println!("{}", u.mul_vec(&v));
// [4.]
// [2.]
let u = Matrix::from([
[2., 0.],
[0., 2.],
]);
let v = Vector::from([4., 2.]);
println!("{}", u.mul_vec(&v));
// [8.]
// [4.]
let u = Matrix::from([
[2., -2.],
[-2., 2.],
]);
let v = Vector::from([4., 2.]);
println!("{}", u.mul_vec(&v));
// [4.]
// [-4.]
let u = Matrix::from([
[1., 0.],
[0., 1.],
]);
let v = Matrix::from([
[1., 0.],
[0., 1.],
35
Enter the Matrix An introduction to Linear Algebra
]);
println!("{}", u.mul_mat(&v));
// [1., 0.]
// [0., 1.]
let u = Matrix::from([
[1., 0.],
[0., 1.],
]);
let v = Matrix::from([
[2., 1.],
[4., 2.],
]);
println!("{}", u.mul_mat(&v));
// [2., 1.]
// [4., 2.]
let u = Matrix::from([
[3., -5.],
[6., 8.],
]);
let v = Matrix::from([
[2., 1.],
[4., 2.],
]);
println!("{}", u.mul_mat(&v));
// [-14., -7.]
// [44., 22.]
Here, you might be interested in learning about the different types of "special" square
matrices:
• matrices of the form λIn , which act like a scaling by the value λ
• diagonal matrices, which scale each vector component independently, and are easy
to raise to an integer power.
• orthogonal matrices, which conserve angles and lengths, and represent a combina-
tion of rotations and (bilateral-symmetric, ie, mirror) reflexions.
There are other special matrices, like those used to represent translations in raytracing
(homogeneous model), or those used in diagonalization or SVD, but the above kinds of
matrices are the ones that are most important, since you will see them most often.
36
Enter the Matrix An introduction to Linear Algebra
They also make special stable groups (in the "algebraic structure" sense of the term),
called Lie Groups, which are very important in physics, since they conserve some math-
ematical quantity (something called a generalized "symmetry"), which translates into a
conservation of some physical quantity (see Noether’s theorem).
37
Chapter XII
Exercise 08 - Trace
Exercise : 08
Trace
Allowed mathematical functions : None
Maximum time complexity : O(n)
Maximum space complexity : N/A
XII.0.1 Goal
You must write a function that computes the trace of the given matrix.
You must also turn in a main function in order to test your function, ready to be
compiled (if necessary) and run.
XII.0.2 Instructions
Let A ∈ Kn×n be a square matrix, where K is the real numbers (represented as the type
f32) and (m, n) ∈ N2 (represented as two variables of type u32).
impl<K> Matrix::<K> {
fn trace::<K>(&mut self) -> K;
}
38
Enter the Matrix An introduction to Linear Algebra
Examples:
let u = Matrix::from([
[1., 0.],
[0., 1.],
]);
println!("{}", u.trace());
// 2.0
let u = Matrix::from([
[2., -5., 0.],
[4., 3., 7.],
[-2., 3., 4.],
]);
println!("{}", u.trace());
// 9.0
let u = Matrix::from([
[-2., -8., 4.],
[1., -23., 4.],
[0., 6., 4.],
]);
println!("{}", u.trace());
// -21.0
39
Chapter XIII
Exercise 09 - Transpose
Exercise : 09
Transpose
Allowed mathematical functions : None
Maximum time complexity : O(nm)
Maximum space complexity : O(nm)
XIII.0.1 Goal
You must write a function that computes the transpose matrix of a given matrix.
You must also turn in a main function in order to test your function, ready to be
compiled (if necessary) and run.
XIII.0.2 Instructions
Let A ∈ Km×n where K is the real numbers (represented as the type f32) and (m, n) ∈ N2
(represented as values of the type u32).
impl<K> Matrix::<K> {
fn transpose::<K>(&mut self) -> Matrix::<K>;
}
40
Enter the Matrix An introduction to Linear Algebra
Here, you might want to know that the transposition of complex matrices uses something
called the conjugate transpose, using the conjugation operation of the complex num-
bers.
The reason why this is different is linked to the fact that every complex number
z = a + ib can be represented uniquely as a 2-by-2 real matrix of the form:
" #
a −b
b a
If you imagine replacing every 1-by-1 coordinate in an n-by-m complex matrix by its
corresponding 2-by-2 rotation-scaling matrix, then run a simple transpose over this 2n-by-
2m matrix, you will get a 2m-by-2n real matrix. If you change the order of operations,
and do the transpose first, before expanding the coefficients into 2-by-2 blocks, you’ll
realize that you need to use the conjugate transpose, rather than a simple transpose, to
get to the same final 2m-by-2n matrix.
41
Chapter XIV
Linear systems of equations are systems of equations where you only have linear com-
binations of variables (a linear combination is a sum of scaled variables, where there are
no exponents on the variables). You may have already used linear systems of equations.
Here is an example:
2x + 3y=8
−7x + 4y = 2
If you’ve now understood matrix multiplication, it’s easy to see that you can represent
the above system in matrix form:
2 3 8
" #" # " #
x
=
−7 4 y 2
Ab = c
2 3 8
" #
−7 4 2
Now, to solve the system, we want to compute the coordinate values of the unknown
vector b, so we need to find some way to "pass it to the other side of the equal sign", like we
did for usual equations in a single variable. Since matrix multiplication isn’t commutative,
and there are matrices that reduce spatial information available (these matrices are called
42
Enter the Matrix An introduction to Linear Algebra
singular and have no inverse), matrix division is particular. In matrix form, we use the
inverse matrix of a given matrix to divide. But the sides to which you multiply the
inverse, and whether a specific matrix’s inverse exists, are both very important questions
which deserve careful consideration.
The inverse of the square matrix A of size n-by-n, if it exists, is denoted A−1 and is
defined such as:
A−1 A = AA−1 = In
Thus, if it exists, you can use the inverse matrix to solve the system (compute the
desired values for the vector b containing all the unknowns):
4 3
29 − 29
A−1 =
7 2
29 29
26
29
b=
60
29
Also, the inverse matrix is not necessarily easy, nor fast, to compute. But you’ll figure
this out in the following exercises. ;)
43
Chapter XV
Exercise : 10
row-echelon form
Allowed mathematical functions : None
Maximum time complexity : O(n3 )
Maximum space complexity : O(n2 )
XV.0.1 Goal
You must write a function that computes the row-echelon form of the given matrix.
You must also turn in a main function in order to test your function, ready to be
compiled (if necessary) and run.
XV.0.2 Instructions
Let A ∈ Km×n , where K is the real numbers (represented as the type f32) and (m, n) ∈ N2
(represented as two values of type u32).
The results may be a bit approximate (within reason) since making the
algorithm numerically stable can sometimes be difficult.
44
Enter the Matrix An introduction to Linear Algebra
impl<K> Matrix::<K> {
fn row_echelon::<K>(&mut self) -> Matrix::<K>;
}
Examples:
let u = Matrix::from([
[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.],
]);
println!("{}", u.row_echelon());
// [1.0, 0.0, 0.0]
// [0.0, 1.0, 0.0]
// [0.0, 0.0, 1.0]
let u = Matrix::from([
[1., 2.],
[3., 4.],
]);
println!("{}", u.row_echelon());
// [1.0, 0.0]
// [0.0, 1.0]
let u = Matrix::from([
[1., 2.],
[2., 4.],
]);
println!("{}", u.row_echelon());
// [1.0, 2.0]
// [0.0, 0.0]
let u = Matrix::from([
[8., 5., -2., 4., 28.],
[4., 2.5, 20., 4., -4.],
[8., 5., 1., 4., 17.],
]);
println!("{}", u.row_echelon());
// [1.0, 0.625, 0.0, 0.0, -12.1666667]
// [0.0, 0.0, 1.0, 0.0, -3.6666667]
// [0.0, 0.0, 0.0, 1.0, 29.5 ]
45
Chapter XVI
Exercise 11 - Determinant
Exercise : 11
Determinant
Allowed mathematical functions : fused multiply-add function
Maximum time complexity : O(n3 )
Maximum space complexity : O(n2 )
XVI.0.1 Goal
You must write a function that computes the determinant of the given matrix.
You must also turn in a main function in order to test your function, ready to be
compiled (if necessary) and run.
XVI.0.2 Instructions
Let A ∈ Kn×n where K is the real numbers (represented as the type f32) and n ∈ N and
n ≤ 4 (represented as a value of the type u32).
Since algorithms to compute the determinant fast and accurately for higher dimensions
tend to be pretty complex, we have limited the required cases for which you must compute
the determinant to dimensions 4 and below.
46
Enter the Matrix An introduction to Linear Algebra
For the simpler methods, you will want to use one specific method per
dimension, and perhaps "recycle" the technique from lower dimensions
when nothing seems to be available...
The results may be a bit approximate (within reason) since making the
algorithm numerically stable can be difficult.
impl<K> Matrix::<K> {
fn determinant::<K>(&mut self) -> K;
}
Examples:
let u = Matrix::from([
[ 1., -1.],
[-1., 1.],
]);
println!("{}", u.determinant());
// 0.0
let u = Matrix::from([
[2., 0., 0.],
[0., 2., 0.],
[0., 0., 2.],
]);
println!("{}", u.determinant());
// 8.0
let u = Matrix::from([
47
Enter the Matrix An introduction to Linear Algebra
let u = Matrix::from([
[ 8., 5., -2., 4.],
[ 4., 2.5, 20., 4.],
[ 8., 5., 1., 4.],
[28., -4., 17., 1.],
]);
println!("{}", u.determinant());
// 1032
If you remember the aside on the exterior algebra from before, you might want to know
that n-vectors inside an n-dimensional exterior algebra tend to behave a lot like scalars,
and are referred to as "pseudoscalars" for this reason.
The determinant is actually the magnitude of the pseudoscalar (the measure of the
n-parallelepiped) which is created by the successive wedge product of all the columns
vectors of a square matrix. Read that again, slowly.
This should make sense to you if you understand the geometric nature of the deter-
minant.
48
Chapter XVII
Exercise 12 - Inverse
Exercise : 12
Inverse
Allowed mathematical functions : fused multiply-add function
Maximum time complexity : O(n3 )
Maximum space complexity : O(n2 )
XVII.0.1 Goal
You must write a function that computes the inverse matrix of a given matrix.
You must also turn in a main function in order to test your function, ready to be
compiled (if necessary) and run.
XVII.0.2 Instructions
Let A ∈ Kn×n where K is the real numbers (represented as the type f32) and n ∈ N
(represented as a value of the type u32).
The function must return the inverse matrix A−1 ∈ Kn×n such that A−1 A = In , where
In is the identity matrix.
49
Enter the Matrix An introduction to Linear Algebra
impl<K> Matrix::<K> {
fn inverse::<K>(&mut self) -> Result<Matrix::<K>>;
}
Examples:
let u = Matrix::from([
[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.],
]);
println!("{}", u.inverse());
// [1.0, 0.0, 0.0]
// [0.0, 1.0, 0.0]
// [0.0, 0.0, 1.0]
let u = Matrix::from([
[2., 0., 0.],
[0., 2., 0.],
[0., 0., 2.],
]);
println!("{}", u.inverse());
// [0.5, 0.0, 0.0]
// [0.0, 0.5, 0.0]
// [0.0, 0.0, 0.5]
let u = Matrix::from([
[8., 5., -2.],
[4., 7., 20.],
[7., 6., 1.],
]);
println!("{}", u.inverse());
// [0.649425287, 0.097701149, -0.655172414]
// [-0.781609195, -0.126436782, 0.965517241]
// [0.143678161, 0.074712644, -0.206896552]
50
Enter the Matrix An introduction to Linear Algebra
51
Chapter XVIII
Let E and F be two vector spaces and let f ∈ L(E, F ) be a linear map. Then:
Where,
• rank(f ) is the rank of the linear transformation’s matrix (dimension of the image
of f )
Let f be a function defined as: f : E → F (mapping values from the set E to the set F )
The image of the function f , which respects im(f ) ⊆ F , is defined as the set of all
the values y ∈ F such that:
∀y ∈ im(f ), ∃x ∈ E, f (x) = y
Simply put, the image of a function is the set of points reached by function f in the
output space.
The kernel of the function f , which respects ker(f ) ⊆ E, is defined as the set of all
the values x ∈ E such that:
52
Enter the Matrix An introduction to Linear Algebra
∀x ∈ ker(f ), f (x) = 0F
In linear algebra, the kernel is commonly called the nullspace and it represents the
space of all points that get squished at the origin of the vector space after the linear
transformation.
53
Chapter XIX
Exercise 13 - Rank
Exercise : 13
Rank
Allowed mathematical functions : None
Maximum time complexity : O(n3 )
Maximum space complexity : N/A
XIX.0.1 Goal
You must also turn in a main function in order to test your function, ready to be
compiled (if necessary) and run.
XIX.0.2 Instructions
Let A ∈ Kn×m where K is the real numbers (represented as the type f32) and (m, n) ∈ N2
(represented as two values of type u32).
54
Enter the Matrix An introduction to Linear Algebra
impl<K> Matrix::<K> {
fn rank::<K>(&mut self) -> usize;
}
Examples:
let u = Matrix::from([
[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.],
]);
println!("{}", u.rank());
// 3
let u = Matrix::from([
[ 1., 2., 0., 0.],
[ 2., 4., 0., 0.],
[-1., 2., 1., 1.],
]);
println!("{}", u.rank());
// 2
let u = Matrix::from([
[ 8., 5., -2.],
[ 4., 7., 20.],
[ 7., 6., 1.],
[21., 18., 7.],
]);
println!("{}", u.rank());
// 3
55
Chapter XX
Exercise : 14
XX.0.1 Goal
You must write a function that computes a projection matrix to be used to render 3D
objects.
You must also turn in a main function in order to test your function, ready to be
compiled (if necessary) and run.
A display software is provided with the subject. It’ll allow you to test this exercise.
XX.0.2 Instructions
Let M, V, P ∈ R4×4 be the model, view and projection matrices (these are some-
56
Enter the Matrix An introduction to Linear Algebra
s = P V Mp
V = RT
1 0 0 −px
0 1 0 −py
T =
0 0 1 −pz
0 0 0 1
Xx Yx Zx 0
X Y Zy 0
R= y y
Xz Yz Zz 0
0 0 0 1
Where:
• T is a translation matrix, placing the camera at the origin of the vector space.
• R is a rotation matrix, rotating the vector space according to the camera’s angle.
• p is the vector representing the camera’s position
• (X, Y, Z) is the vector space’s basis after transformation.
In this exercise, we will only build the Projection matrix. To do so, the function will
take the following arguments:
57
Enter the Matrix An introduction to Linear Algebra
far
y near
z x
Eye position
fn projection(fov: f32, ratio: f32, near: f32, far: f32) -> Matrix::<f32>;
To test your projection matrix, you can plug it in the display software like so:
Example:
$ cat proj
1., 0., 0., 0.
0., 1., 0., 0.
0., 0., 1., -1.
0., 0., 0., 0.
$ ./display
A projection matrix made for the wrong NDC and in the wrong major
order may appear to work at first glance, but will fail under careful
scrutiny. Try playing around with different near and far planes, and
justify the changes that you observe.
58
Enter the Matrix An introduction to Linear Algebra
59
Chapter XXI
Exercise : 15
XXI.0.1 Goal
You’ve now succeeded in coming to grips with all the fundamental constructs of linear
algebra.
But you’ve only ever used one field of scalars: the real numbers. Sure it’s the most
used, but it’s certainly not the only one.
Do all the previous exercises again, this time interpreting K in the function signatures,
not as the field R of real numbers, but as the field C of complex numbers. Vector spaces
over complex numbers are notoriously hard to visualize. However they are essential in
much of electronics, signal analysis, quantum mechanics, and have even seen applications
in machine learning (with complex-valued tensors).
You must also turn in a main function in order to test your function, ready to be
compiled (if necessary) and run.
If you’re feeling frisky, you might want to look into finite fields, try to build a finite
field type, and build your vector spaces over that. These are easier to visualize than
vector spaces over complex numbers. You can for example represent any vector space of
60
Enter the Matrix An introduction to Linear Algebra
dimension 2, based on a finite field, as a space of tiles over the surface of a donut! :D
61
Chapter XXII
Turn in your assignment in your Git repository as usual. Only the work inside your
repository will be evaluated during the defense. Don’t hesitate to double check the
names of your files to ensure they are correct.
62