Linear algebra is heavily used in programming, especially for graphics.
To implement 3D scenes with scaling,
rotations, and transformations, we need to operate on data
presented with mathematical vectors and matrices.
And, if you ever saw a matrix,
you know that it kind of looks like a table of numbers with
a specific amount of rows and columns.
So, let's say that I want to store a matrix in memory,
that looks something like this.
It has two rows and three columns.
Remember that to the computer, everything is just a really long stream of bytes.
The concept of rows and columns is not something that
the computer really cares about.
If we wanted to store this matrix in memory,
each element would be stored in a one‑dimensional sequence,
just like a simple array. I created an array of six integers to
store the numbers from the matrix.
This doesn't really look like a table with rows and columns,
but we can make our own abstraction to pretend that it does.
Let's create four variables.
The first two will define the number of rows and the number of
columns, and the last two will store the indexes of a row and
the column that we want to access.
Our table has two rows and each row has three columns, so
six numbers in total. The required row and column position
will be taken from the terminal.
I want to start counting from 0,
which means that the first row will have an index of 0 and
the second row will have an index of 1,
just like a regular array. Each column will also have
a special index for each number.
So for example,
if I want to get this number, which is placed in the
second column of the second row,
I would say that I want to get an integer at the
position of the row 1 and column 1.
I need a mathematical formula that will provide me with
this abstraction of two dimensions.
And, this is what that formula looks like.
I want to get an array element at the position of a requested row,
multiplied by the number of columns, plus the requested column.
Let's compile this program to see if this works.
I want to get a second number from the second row, so the position that I need
is 1, 1, and it seems that it works, the number 5 is correct.
Let's try one more.
I want to get this number 3 and its position is 0 and 2, and if I
try that position, I get the correct number again.
So, with a little bit of math and imagination, we were able to use this
one‑dimensional array as a matrix with two dimensions.
Let's use this same formula to print this array to the terminal
in a form of a table. To do this, I will use two for loops, one
will be nested inside of the other.
The first loop will go through each row, and the
second loop will go over each column.
Each iteration of this outer loop will complete the whole inner loop.
So first, the row will be 0 and the column will also be 0.
Then the column will be incremented to 1, but the row will still
remain 0. After that, the column will increment once more to 2,
and the row will still remain 0.
So, we are basically looping through all of the numbers in the table,
row by row. Once all of the columns in a row are completed,
the next iteration of the outer loop begins, and this goes
on until we get through all of the rows.
So the actual elements from the array need to be accessed
here, inside of the nested for loop. I will use the same
formula to access these elements.
Let's also add this vertical line character after each number
to make the output look more like a table.
I will also add the same character before each row,
and after each row is finished, I want to print on a new line.
This is a really useful concept, because you can define
special behavior for each row in the outer loop and what to do
with each column in the inner loop.
I will turn this into a comment, because I just want to see the table.
Let's compile and see what happens.
This kind of looks like a table, right?
It looks exactly like the matrix we had in mind, and now we have
a way to store it in memory and work with it.
However,
using the array with this mathematical formula seems a little bit
unnatural and unintuitive, at least for me. There is a reason why we
don't program by typing out a sequence of 1s and 0s, humans need better
abstraction mechanisms to be more productive.
Fortunately, C++ offers us a better way to manage multidimensional arrays.
The syntax is straightforward,
you just use a separate square bracket to define each dimension.
So in this case, I want to create a 2d array with two rows and three columns.
The initialization list can stay, because the memory which contains
these elements will look exactly the same, it will still store all
of these integers next to each other.
The big difference is, of course, the way in which we
can manage this array. However,
to make our intentions more obvious, you can wrap every
dimension in its own curly braces,
and I will even put each one of them on a new line.
This already looks like a table, and now,
instead of utilizing this formula,
I can use two square brackets to specify the
required position of each dimension.
As you can see, this approach is much more intuitive.
Okay,
now I can compile this to see if it still works, and it
does. The output still looks the same, but the code is much cleaner.
If you wanted to have a three‑dimensional array,
you would just add another square brackets with the third dimension and then
access the elements in the same way. You should prefer using this syntax
instead of the implementation with a special formula,
because the code looks cleaner and the performance is exactly the same.
But there is a reason why I started this lesson with that formula,
and we will talk about it in the next lesson,
where we will learn how to allocate multidimensional arrays on the heap.