Previous Section  < Day Day Up >  Next Section

Matrix Multiplication

The preceding section looked at multiplying a scalar and a matrix. The next logical step is to investigate the product of two matrices, or a matrix times another matrix. This process involves the dot product, so you might want to flip back to Chapter 4, "Vector Operations," for a quick review of the dot product before proceeding.

You can multiply matrices by taking a series of dot products. Keep in mind two important aspects of the dot product:

  • The two vectors must have the same number of entries to take the dot product.

  • The dot product returns a scalar quantity (a single number).

Let's start by looking at two 2x2 matrices. Matrices to be multiplied don't have to be square and don't have to be the same size, but there are restrictions, which we'll examine next. For now, I will tell you that you can multiply a 2x2 by a 2x2. Doing so gives you another 2x2.

Multiplying Two 2x2 Matrices

graphics/05equ06.gif



This might look crazy at first glance, but take a closer look at the entry in row 0, column 0. Does it look familiar? It's the dot product of row 0 in A and column 0 in B.

Now look at the entry in row 0, column 1; it's the dot product of row 0 in A and column 1 in B. The same is true for the other two entries.

Each entry is determined by its location. The entry is a single number that you find using the dot product of the corresponding row in the first matrix and the corresponding column of the second matrix.

Example 5.8: Multiplying Two 2x2 Matrices

Given matrices A = graphics/05inl02.gif, find matrix AB.

Solution

graphics/05equ07.gif


This example takes four separate dot products—one for each entry. Remember the first aspect of the dot product? For you to take a dot product, both vectors must have the same number of entries. This means that for a matrix multiplication to be defined, the number of columns in the first matrix must equal the number of rows in the second matrix. That's the only way to ensure that the number of entries in the rows of the first matrix matches the number of entries in the columns of the second matrix.

Is the Product Defined?

For matrix multiplication AB, the number of columns in A must equal the number of rows in B.


If you check, and the product is defined, the next step is to find the size of the answer so that you can go through and take the dot product for each entry. If the matrix multiplication is defined, you can find the size of the answer with this next rule.

The Size of the Product

If AB is defined, the size of matrix AB is the number of rows in A by the number of columns in B.


It's easy to mix up these two rules, but a visual method might help you keep them straight. If you write down the dimensions of each matrix, as shown in Figure 5.15, the two inside numbers must be equal.

Figure 5.15. A visual trick for matrix multiplication.

graphics/05fig15.gif

If the two inside numbers are not equal, stop right there. The product is not defined. If they are equal, you can multiply the two matrices. The next step is to find the size of the answer. Conveniently, the two outside numbers give you the dimensions of the answer. In Figure 5.15 you can see that the two inside numbers are both 3, so the product is defined. The size of the product is 2x1, which was given by the two outside numbers. As soon as you know the size of the answer, the rest is just a series of dot products. In this case, the product has only two entries, so there are only two dot products to calculate. Figure 5.16 shows the final product.

Figure 5.16. The product of matrices A and B.

graphics/05fig16.gif

Example 5.9: Multiplying Two Different-Sized Matrices

Using the two matrices shown in Figure 5.15, is the product BA defined?

Solution
  1. Before you attempt to multiply two matrices, always check to see if the product is defined. To use the new visual trick, write down the dimensions of each matrix. This is done in Figure 5.17.

    Figure 5.17. Product BA.

    graphics/05fig17.gif

  2. Check the two inside numbers. In this case, 2 1, which means that the columns in B the rows in A, so the product is not defined. You can't calculate BA.

Remember that earlier you calculated AB; it was defined, and it returned a 2x1 matrix. However, when you flipped the order and tried to multiply B times A, it was not defined. This tells you that matrix multiplication is not commutative.

Matrix Multiplication Is Not Commutative

AB BA

for any size matrices A and B.


In some cases, when you flip the order, the product is still defined. However, you'll find that in most cases you get a completely different result. For example, let's look back at Example 5.8. When you multiplied A times B, you got the following product:

graphics/05equ08.gif


Notice that when you calculate BA, you get a very different result:

graphics/05equ09.gif


In this case, both AB and BA are defined, but the products are completely different.

Matrix multiplication is definitely more complicated than scalar multiplication. Just remember the three-step process:

  1. Check to see if the product is defined (two inside numbers).

  2. If product is defined, find its dimensions (two outside numbers).

  3. Go through each entry one at a time. Based on the entry's location, take the dot product of the corresponding row in the first matrix and the column in the second matrix.

To get matrices multiplying in code, the same set of rules must apply. The product must be defined. It is the programmer's responsibility to make sure the product is defined before trying to multiply.

Here is a function that allows us to multiply two 3x3 matrices:


Matrix3X3 multiply3X3Matrices(Matrix3X3 a, Matrix3X3 b)

      {

       Matrix3X3 temp = createFixed3X3Matrix(0);



        for(int i = 0;i<3;i++)

           {

           for(int j=0;j<3;j++)

              {

               for(int k=0;k<3;k++)

                  {

                     temp.index[i][j] += (a.index[i][k] * b.index[k][j]);

                  }

               }

            }

        return temp;

       }

Before just accepting this function as a working example, you should make sure you can trace down the values that would be contained inside the matrices each step of the way. This triple for loop will allow us to make sure that each entry is process just like a dot product from the previous chapter. The accuracy of this function is critical when you are trying to limit bugs in calculations.

Multiplications are used in 3D games frequently to allow an object to rotate. Given that this happens often in 3D games, can you think of a faster way to process this multiplication?

This process is only slightly different when multiplying two different sized matrices:


Matrix3X1 multiplyMatrixNxM(Matrix3X3 a, Matrix3X1 b)

    {

        Matrix3X1 temp;

        temp.index[0] = 0.0f;

        temp.index[1] = 0.0f;

        temp.index[2] = 0.0f;



               for(int i=0;i<3;i++)

               {

                for(int j=0;j<3;j++)

                {

                 temp.index[i] += (a.index[i][j] * b.index[j]);

                }

               }



        return temp;

    }

Here, we only need to visit one component of the 3x1 Matrix. Notice the step being taken to initialize the matrix. This step hasn't been listed in earlier code snips to save space, but remember to do this step. Initialize any temporary matrices that you plan to use, especially when working with multiplication. The provided sample code for this chapter contains useful examples of both sets of matrix multiplication in action.

One other really useful function that can be mentioned here is the printMatrix() function. It's a good idea to have a way to print out the information contained in the matrix. These are used throughout the sample code and are great for debugging. Here is an example of how to print out a matrix:


void printMatrix(Matrix4X4 a)

    {

       for(int i = 0;i<4;i++)

            {

            for(int j=0;j<4;j++)

                {

                float temp = a.index[i][j];

                 cout<<temp<<" ";

                }

             cout<<"\n";

            }

    }

This chapter uses generic matrices. Remember that you can attach meaning to each row and column, as you saw with the vectors. The next chapter attaches meaning to the rows and columns of the matrices so that you can use them to move objects around on the screen.

After you have written some basic matrix math programs using some of these methods, be sure to test the work that was done on paper through the new programs. Are the values the same? If not, which one is in error? Don't lose sight of the importance of working the solutions out on paper. In the inevitable situation where you are spending hours bug-hunting, you will need to go back to paper at one point or another to verify calculations. Don't rely completely on the machine for verification.

One key concept is that the computer executes algorithms to solve problems that we are already familiar with. It is important to understand the method before coding anything.

Before moving on to Chapter 6, make sure that you have reviewed the basic functions that are contained in the matrix library in the accompanying source code. That file will be used frequently in the next chapter.

Self-Assessment

For each of the following pairs of matrices, check to see if the product is defined. If it is, calculate the product.

1.

graphics/05inl04.gif

2.

graphics/05inl05.gif

3.

graphics/05inl06.gif

4.

graphics/05inl07.gif

5.

graphics/05inl08.gif

6.

graphics/05inl09.gif


    Previous Section  < Day Day Up >  Next Section