Matrix multiplication in C++

theplebdev

Tristan Elliott

Posted on October 5, 2024

Matrix multiplication in C++

Table of contents

  1. Why use matrix multiplication?
  2. The actual code
  3. Breaking down the key points of the code

Resources

My app on the Google play store

My app's GitHub code

Why use matrix multiplication?

  • Spinning cube UI demonstration
  • So as it turns out, if we look at the documentation for this open gl cube. One major component is matrix multiplication. Well, actually the entire 3d cube animation is basically just matrixes and manipulating them.

The actual code:

  • So here is the code we are going to look at:
/**
 * matrixMultiply
 * // temporary array          array1                    array2  
 * [ 0,  1,   2,  3 ]       [ 1, 0, 0, 0 ]          [ 1, 0, 0, 0 ]
 * [ 4,  5,   6,  7 ]       [ 0, 1, 0, 0 ]          [ 0, 1, 0, 0 ]
 * [ 8,  9,  10, 11 ]       [ 0, 0, 1, 0 ]          [ 0, 0, 1, 0 ]
 * [ 12, 13, 14, 15 ]       [ 0, 0, 0, 1 ]          [ 0, 0, 0, 1 ]
 *
 *
 *
 * */
// [location in temporary array] = index x index + index x index
// [0] = 0*0 + 4*1 + 8*2 + 12*3
// [1] = 1*0 + 5*1 + 9*2 + 13*3
// [2] = 2*0 + 6*1 +10*2 + 14*3

 // [5] = 1*4 + 5*5 + 9*6 + 13*7
void matrixMultiply(float* destination, float* operand1, float* operand2)
{
    float theResult[16]; // Temporary matrix to store the result

    // Perform matrix multiplication for each element in the 4x4 result matrix
    for(int i = 0; i < 4; i++)
    {
        for(int j = 0; j < 4; j++)
        {
            // Calculate the dot product for the (i, j) element in the result matrix
            theResult[4 * i + j] =   operand1[j] * operand2[4 * i]
                                   + operand1[4 + j] * operand2[4 * i + 1]
                                   + operand1[8 + j] * operand2[4 * i + 2]
                                   + operand1[12 + j] * operand2[4 * i + 3];
        }
    }

    // Copy the result into the destination matrix
    for(int i = 0; i < 16; i++)
    {
        destination[i] = theResult[i];
    }
}

Enter fullscreen mode Exit fullscreen mode
  • I won't go into the details of the mathematics of matrix multiplication(you can google that yourself). However, the short answer is that we need to multiply the columns by the rows.
  • This leads us into our first hurdle, of how do we represent a matrix? The answer, is just to use an array (underwhelming but effecting). So the variable of float theResult[16]; is how we represent a 4x4 matrix. Which admittedly is hard to imagine, so I created this visual:
 * [ 0,  1,   2,  3 ]       --------rows
 * [ 4,  5,   6,  7 ]       |
 * [ 8,  9,  10, 11 ]       |
 * [ 12, 13, 14, 15 ]       |columns

Enter fullscreen mode Exit fullscreen mode
  • When dealing with arrays we want to represent a matrix, this is the proper mental model to have. Column one holds the indexes of 0,4,8,12 and row one holds the indexes of 0,1,2,3.

Breaking down the key points of the code

  • We can start with the two parameters: float* operand1 and float* operand2. Which technically are float pointers but for those uninitiated , In C++, pointers and arrays are closely related. The name of an array can be used as a pointer to its initial element. (Stroustrup, Bjarne. The C++ Programming Language. Addison-Wesley, 2013, p. 179.) So those float pointers are actually the two arrays we want to multiply
  • then we have the float theResult[16];, which is another array that holds 16 floats and will temporary hold our array values.
  • next is the nested for loops:
for(int i = 0; i < 4; i++){
        for(int j = 0; j < 4; j++){
        }
    }

Enter fullscreen mode Exit fullscreen mode
  • These loops are how we are navigating around the matrix. If you are curious about the number 4. we are looping from 0-3(4 loops) because the matrix is 4x4. If the matric was 5x5 then we would loop from 0-4.
  • we use j to navigate the columns and i to navigate the rows

  • Inside of the for loops we have 2 problems,

1) navigating the theResult array

  • We have to accurately navigate the row and then make a jump to the column and we do so with this: theResult[4 * i + j]. The 4 is how we accurately navigate the columns. This number would change depending on out matrix

2) doing the actual multiplication

  • This section is a little confusing (I did not do a good job explaining it):
 theResult[4 * i + j] = operand1[j] * operand2[4 * i]
                        + operand1[4 + j] * operand2[4 * i + 1]
                        + operand1[8 + j] * operand2[4 * i + 2]
                        + operand1[12 + j] * operand2[4 * i +3];

Enter fullscreen mode Exit fullscreen mode
  • Now, I want to stress not to memorize this code but instead try to grasp its broader understanding. When doing matrix multiplication we must do these four things:

    • 1) navigate the array: theResult[4 * i + j]
    • 2) navigate the columns: operand1[4 + j]
    • 3) navigate the rows: operand2[4 * i + 1]
    • 4) multiply and add: + operand1[12 + j] * operand2[4 * i +3];
  • Ultimately, what we need to do is to take the results of the first column times the first row and put the results inside of the result array. Know that operand1[4 + j] represent the columns and operand2[4 * i + 1] represents the row

Conclusion

  • Thank you for taking the time out of your day to read this blog post of mine. If you have any questions or concerns please comment below or reach out to me on Twitter.
💖 💪 🙅 🚩
theplebdev
Tristan Elliott

Posted on October 5, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related