About this Blog

This is my first blog. Ever.

It is simply going to be about my hobby; playing with computer programming. I do not know much about blogging, but I will use this one to learn a bit more about it.

Programming has always been a bit of a passion for me, as from those early days when I first tapped in a sample BASIC program on my old Sinclair Spectrum back in 1986. I have been through many platforms, languages and OS's since, but always carried the hobby with me. I am not particularly good at it; perfection requires a large time investment and continuous practice. I do not have the luxury of the amount of time required to keep the fire burning constantly, so the hobby has inevitably gone through periods of extreme withering. I have, however, finally settled for C++, as the title of this blog implies, and play around with it for some entertainment when ever I can.

This here will serve me as a written record of what I am up to, and hopefully be a reinforcement to my memory every now and then. That is all there is to it.

So, if you read this blog, please don't expect anything snazzy, but be you welcome just the same!

Friday 20 January 2012

3x3 Matrix Multiplication

Going from 2D matrix (from my previous post) to 3D matrix manipulation is a reasonably large step, and there is no real in between step to ease the transition. It is quite a leap of faith, when it is done the very first time. However, it does make sense, if the procedure is revisited (from our college days?), worked out on paper and studied a little. First, we simply must look at matrix multiplication.

Here's a simple example,


Now a 2 x 2 matrix to matrix multiplication (concatenation of two similar matrices into one)...


...and that constitutes a review.

Before making any attempt at hand made 3D graphics, procedures that multiply matrices in a program must be established. The following is a simple console program, that as usual can be strung together in the presented order and compiled to make the working demo application.

I am going to make three matrices; two that are going to be multiplied together, and a third to hold the output of the multiplication (concatenation) operation. First, it is a good idea to define a type out of the matrix, so that multiple, compatible instances of it can be created, make a function to populate the two matrices to be multiplied together with some values, and a function to display (cout) the contents of any of the matrices. This is simple stuff that anyone with an understanding of C++ just a little greater that "Hello World" can comprehend (which more or less guarantees that I will catch on again from here)...

#include "iostream"

using namespace std;

typedef int matrix[3][3];

void set_matrix(matrix x_mat, matrix y_mat)
{
x_mat[0][0] = 9;
x_mat[0][1] = 8;
x_mat[0][2] = 7;

x_mat[1][0] = 6;
x_mat[1][1] = 5;
x_mat[1][2] = 4;

x_mat[2][0] = 3;
x_mat[2][1] = 2;
x_mat[2][2] = 1;

y_mat[0][0] = 1;
y_mat[0][1] = 2;
y_mat[0][2] = 3;

y_mat[1][0] = 4;
y_mat[1][1] = 5;
y_mat[1][2] = 6;

y_mat[2][0] = 7;
y_mat[2][1] = 8;
y_mat[2][2] = 9;
}

void show_matrix(matrix mat)
{
int i, j;

for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
{
cout << mat[i][j] << " ";
}
cout << endl;
}
cout << endl;
}


Then I will make a function that, in an expanded form, permits the easy following of what is happening during the matrix multiplication. The function accepts all three matrices as parameters, multiplies two of them (rows by columns, added together, in this case mat_1 and mat_2) and puts the results into the third (output matrix, in this case fin_mat)...

void expanded_mult(matrix mat_1, matrix mat_2, matrix fin_mat)
{
fin_mat[0][0] = (mat_1[0][0] * mat_2[0][0]) +
(mat_1[0][1] * mat_2[1][0]) +
(mat_1[0][2] * mat_2[2][0]);

fin_mat[1][0] = (mat_1[1][0] * mat_2[0][0]) +
(mat_1[1][1] * mat_2[1][0]) +
(mat_1[1][2] * mat_2[2][0]);

fin_mat[2][0] = (mat_1[2][0] * mat_2[0][0]) +
(mat_1[2][1] * mat_2[1][0]) +
(mat_1[2][2] * mat_2[2][0]);


fin_mat[0][1] = (mat_1[0][0] * mat_2[0][1]) +
(mat_1[0][1] * mat_2[1][1]) +
(mat_1[0][2] * mat_2[2][1]);

fin_mat[1][1] = (mat_1[1][0] * mat_2[0][1]) +
(mat_1[1][1] * mat_2[1][1]) +
(mat_1[1][2] * mat_2[2][1]);

fin_mat[2][1] = (mat_1[2][0] * mat_2[0][1]) +
(mat_1[2][1] * mat_2[1][1]) +
(mat_1[2][2] * mat_2[2][1]);


fin_mat[0][2] = (mat_1[0][0] * mat_2[0][2]) +
(mat_1[0][1] * mat_2[1][2]) +
(mat_1[0][2] * mat_2[2][2]);

fin_mat[1][2] = (mat_1[1][0] * mat_2[0][2]) +
(mat_1[1][1] * mat_2[1][2]) +
(mat_1[1][2] * mat_2[2][2]);

fin_mat[2][2] = (mat_1[2][0] * mat_2[0][2]) +
(mat_1[2][1] * mat_2[1][2]) +
(mat_1[2][2] * mat_2[2][2]);

}


All that is left to do is create the main() loop of the program now, and we are away with a 3x3 matrix multiplication program...

int main()
{
// locally create our three matrices of type matrix...
matrix x_matrix, y_matrix, final_matrix;

// populate the two matrices to be multiplied...
set_matrix(x_matrix, y_matrix);

// display the two matrices, so we can see they have been populated correctly...
show_matrix(x_matrix);
show_matrix(y_matrix);

// send all three matrices to the multiplier function, so that final_matrix can be populated with the results...
expanded_mult(x_matrix, y_matrix, final_matrix);

// and show the results of final matrix...
show_matrix(final_matrix);

return 0;
}


Does the trick? That's the whole program. Now some modifications to "compress" the code. I want to go after that void expanded_mult(matrix mat_1, matrix mat_2, matrix fin_mat) function to create something that is both a little more generic and less lengthy. for example, note that if you are doing a 4x4 matrix multiplication, that function is going to grow into an unwieldy...

//DEMO EXAMPLE
void expanded_mult(matrix mat_1, matrix mat_2, matrix fin_mat)
{
fin_mat[0][0] = (mat_1[0][0] * mat_2[0][0]) +
(mat_1[0][1] * mat_2[1][0]) +
(mat_1[0][2] * mat_2[2][0]) +
(mat_1[0][3] * mat_2[3][0]);

fin_mat[1][0] = (mat_1[1][0] * mat_2[0][0]) +
(mat_1[1][1] * mat_2[1][0]) +
(mat_1[1][2] * mat_2[2][0]) +
(mat_1[1][3] * mat_2[3][0]);

fin_mat[2][0] = (mat_1[2][0] * mat_2[0][0]) +
(mat_1[2][1] * mat_2[1][0]) +
(mat_1[2][2] * mat_2[2][0]) +
(mat_1[2][3] * mat_2[3][0]);

fin_mat[3][0] = (mat_1[3][0] * mat_2[0][0]) +
(mat_1[3][1] * mat_2[1][0]) +
(mat_1[3][2] * mat_2[2][0]) +
(mat_1[3][3] * mat_2[3][0]);



fin_mat[0][1] = (mat_1[0][0] * mat_2[0][1]) +
(mat_1[0][1] * mat_2[1][1]) +
(mat_1[0][2] * mat_2[2][1]) +
(mat_1[0][3] * mat_2[3][1]);

fin_mat[1][1] = (mat_1[1][0] * mat_2[0][1]) +
(mat_1[1][1] * mat_2[1][1]) +
(mat_1[1][2] * mat_2[2][1]) +
(mat_1[1][3] * mat_2[3][1]);

fin_mat[2][1] = (mat_1[2][0] * mat_2[0][1]) +
(mat_1[2][1] * mat_2[1][1]) +
(mat_1[2][2] * mat_2[2][1]) +
(mat_1[2][3] * mat_2[3][1]);

fin_mat[3][1] = (mat_1[3][0] * mat_2[0][1]) +
(mat_1[3][1] * mat_2[1][1]) +
(mat_1[3][2] * mat_2[2][1]) +
(mat_1[3][3] * mat_2[3][1]);



fin_mat[0][2] = (mat_1[0][0] * mat_2[0][2]) +
(mat_1[0][1] * mat_2[1][2]) +
(mat_1[0][2] * mat_2[2][2]) +
(mat_1[0][3] * mat_2[3][2]);

fin_mat[1][2] = (mat_1[1][0] * mat_2[0][2]) +
(mat_1[1][1] * mat_2[1][2]) +
(mat_1[1][2] * mat_2[2][2]) +
(mat_1[1][3] * mat_2[3][2]);

fin_mat[2][2] = (mat_1[2][0] * mat_2[0][2]) +
(mat_1[2][1] * mat_2[1][2]) +
(mat_1[2][2] * mat_2[2][2]) +
(mat_1[2][3] * mat_2[3][2]);

fin_mat[3][2] = (mat_1[3][0] * mat_2[0][2]) +
(mat_1[3][1] * mat_2[1][2]) +
(mat_1[3][2] * mat_2[2][2]) +
(mat_1[3][3] * mat_2[3][2]);



fin_mat[0][3] = (mat_1[0][0] * mat_2[0][3]) +
(mat_1[0][1] * mat_2[1][3]) +
(mat_1[0][2] * mat_2[2][3]) +
(mat_1[0][3] * mat_2[3][3]);

fin_mat[1][3] = (mat_1[1][0] * mat_2[0][3]) +
(mat_1[1][1] * mat_2[1][3]) +
(mat_1[1][2] * mat_2[2][3]) +
(mat_1[1][3] * mat_2[3][3]);

fin_mat[2][3] = (mat_1[2][0] * mat_2[0][3]) +
(mat_1[2][1] * mat_2[1][3]) +
(mat_1[2][2] * mat_2[2][3]) +
(mat_1[2][3] * mat_2[3][3]);

fin_mat[3][3] = (mat_1[3][0] * mat_2[0][3]) +
(mat_1[3][1] * mat_2[1][3]) +
(mat_1[3][2] * mat_2[2][3]) +
(mat_1[3][3] * mat_2[3][3]);

}


Phew! This function does the same thing, using for loops...

// DEMO EXAMPLE
void mult_matrix(matrix mat_1, matrix mat_2, matrix fin_mat)
{
int temp = 0;
int a, b, c;

for(a = 0; a < 3; a++)
{
for(b = 0; b < 3; b++)
{
for(c = 0; c < 3; c++)
{
temp += mat_1[b][c] * mat_2[c][a];
}
fin_mat[b][a] = temp;
temp = 0;
}
}
}


...for a 3x3 matrix, or...

// DEMO EXAMPLE
void mult_matrix(matrix mat_1, matrix mat_2, matrix fin_mat)
{
int temp = 0;
int a, b, c;

for(a = 0; a < 4; a++)
{
for(b = 0; b < 4; b++)
{
for(c = 0; c < 4; c++)
{
temp += mat_1[b][c] * mat_2[c][a];
}
fin_mat[b][a] = temp;
temp = 0;
}
}
}


...for a 4x4 matrix. Put this function in (the 3x3 version) instead of the expanded_mult() function, and modify main() to look like this...

int main()
{
matrix x_matrix, y_matrix, final_matrix;

set_matrix(x_matrix, y_matrix);
show_matrix(x_matrix);
show_matrix(y_matrix);

mult_matrix(x_matrix, y_matrix, final_matrix);

show_matrix(final_matrix);

return 0;
}


...and you're away.

To wrap up, here's a complete listing of how I am handling 4x4 (or any, symmetrical matrix, depending on the value of SYM_MAT).

#include "iostream"

using namespace std;

const int SYM_MAT = 4;

typedef int matrix[SYM_MAT][SYM_MAT];


void set_matrix(matrix x_mat, matrix y_mat)
{
x_mat[0][0] = 16;
x_mat[0][1] = 15;
x_mat[0][2] = 14;
x_mat[0][3] = 13;

x_mat[1][0] = 12;
x_mat[1][1] = 11;
x_mat[1][2] = 10;
x_mat[1][3] = 9;

x_mat[2][0] = 8;
x_mat[2][1] = 7;
x_mat[2][2] = 6;
x_mat[2][3] = 5;

x_mat[3][0] = 4;
x_mat[3][1] = 3;
x_mat[3][2] = 2;
x_mat[3][3] = 1;


y_mat[0][0] = 1;
y_mat[0][1] = 2;
y_mat[0][2] = 3;
y_mat[0][3] = 4;

y_mat[1][0] = 5;
y_mat[1][1] = 6;
y_mat[1][2] = 7;
y_mat[1][3] = 8;

y_mat[2][0] = 9;
y_mat[2][1] = 10;
y_mat[2][2] = 11;
y_mat[2][3] = 12;

y_mat[3][0] = 13;
y_mat[3][1] = 14;
y_mat[3][2] = 15;
y_mat[3][3] = 16;
}


void show_matrix(matrix mat)
{
int i, j;

for(i = 0; i < SYM_MAT; i++)
{
for(j = 0; j < SYM_MAT; j++)
{
cout << mat[i][j] << " ";
}
cout << endl;
}
cout << endl;
}


void mult_matrix(matrix mat_1, matrix mat_2, matrix fin_mat)
{
int temp = 0;
int a, b, c;

for(a = 0; a < SYM_MAT; a++)
{
for(b = 0; b < SYM_MAT; b++)
{
for(c = 0; c < SYM_MAT; c++)
{
temp += mat_1[b][c] * mat_2[c][a];
}
fin_mat[b][a] = temp;
temp = 0;
}
}
}


int main()
{
matrix x_matrix, y_matrix, final_matrix;

set_matrix(x_matrix, y_matrix);
show_matrix(x_matrix);
show_matrix(y_matrix);

mult_matrix(x_matrix, y_matrix, final_matrix);

show_matrix(final_matrix);

return 0;
}


That's all, for this post.

No comments:

Post a Comment