• C

# Matrix Multiply

Hey, I am writing a 3d engine with glide(who isn't :-)and I need to multiply to matrixs together, because I read that this is the way you combine two matrixs. However, my code is in big trouble. Using my small understanding of matrix math, I wrote this function:

struct matrix { float x1;float y1;float z1;float w1;
float x2;float y2;float z2;float w2;
float x3;float y3;float z3;float w3;
float x4;float y4;float z4;float w4;};matrix matrixmulti(matrix a,matrix b)//Multiply Matrix
{
matrix returnv;
returnv.x1=(a.x1*b.x1)+(a.y1*b.x2)+(a.z1*b.x3)+(a.w1*b.x4);
returnv.x2=(a.x2*b.x1)+(a.y2*b.x2)+(a.z2*b.x3)+(a.w2*b.x4);
returnv.x3=(a.x3*b.x1)+(a.y3*b.x2)+(a.z3*b.x3)+(a.w3*b.x4);
//
returnv.y1=(a.x1*b.y1)+(a.y1*b.y2)+(a.z1*b.y3)+(a.w1*b.x4);
returnv.y2=(a.x2*b.y1)+(a.y2*b.y2)+(a.z2*b.y3)+(a.w2*b.x4);
returnv.y3=(a.x3*b.y1)+(a.y3*b.y2)+(a.z3*b.y3)+(a.w3*b.x4);
//
returnv.z1=(a.x1*b.z1)+(a.y1*b.z2)+(a.z1*b.z3)+(a.w1*b.x4);
returnv.z2=(a.x2*b.z1)+(a.y2*b.z2)+(a.z2*b.z3)+(a.w2*b.x4);
returnv.z3=(a.x3*b.z1)+(a.y3*b.z2)+(a.z3*b.z3)+(a.w3*b.x4);
//
returnv.w1=(a.x1*b.z1)+(a.y1*b.z2)+(a.z1*b.z3)+(a.w1*b.x4);
returnv.w2=(a.x2*b.z1)+(a.y2*b.z2)+(a.z2*b.z3)+(a.w2*b.x4);
returnv.w3=(a.x3*b.z1)+(a.y3*b.z2)+(a.z3*b.z3)+(a.w3*b.x4);
return returnv;
}
I tried roating these two:
matrix Org={50,0,0,500,
0,50,0,500,
0,0,50,100,
0,0,0,1};
matrix roat={50,0,0,500,
0,50,0,500,
0,0,50,100,
but the matrix that came out, was NOT the combination of the two! What do I do? Have I got a bug? Did I goof in my matrix function?
LVL 5
###### Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Commented:

maybe that's the same as your code, but I use the non unrolled version of matrix multiply..

since I store my matrices as an array of 16 floats I do a different addressing.. however, passing the pointer to your first matrix element should work.

this code actually performs a 4x4 matrix multiply, where c = a * b.

maybe it helps you to get startet.

nils

--- code begins here -------

void matrix_mul( float *c, float *a, float *b )
{
int i,j,k;
for ( i=0; i<16; i++) c[i]=0;
for ( i=0; i<4; i++ )
for ( j=0; j<4; j++ )
for ( k=0; k<4; k++ )
c[i+4*j] += a[i+4*k] * b[k+4*j];
}

0
Author Commented:
what is the unrolled version?
0
Commented:
yours is the unrolled version, where you get rid of the 3 loops and do write the exact equation for every matrix element down..

it makes no difference in performance.. it's just, that your code may contain more bugs simply because it's more code :)

my code works.. has been used in a commercial program.

nils
0
Author Commented:
It's a good idea, but my matix implemintaion won't let me do it. I would change it, because now I know it stinks, but I already have a 800+ line program built with the same matrix struct.
0
Commented:
ok.. I'll check your code and compare with mine..

nils
0
Author Commented:
Thanks nils.
0
Commented:
jep. it looks like your code is broken..

you don't multiply the last row for example.. this is the test program i used..

it would be nice if you take my code, put it in your code ( you don't need to change anything.. just do it like i did it) and tell me if it works ...

#include <stdio.h>

struct matrix
{ float x1;float y1;float z1;float w1;
float x2;float y2;float z2;float w2;
float x3;float y3;float z3;float w3;
float x4;float y4;float z4;float w4;};

matrix matrixmulti(matrix a,matrix b)//Multiply Matrix
{
matrix returnv;
returnv.x1=(a.x1*b.x1)+(a.y1*b.x2)+(a.z1*b.x3)+(a.w1*b.x4);
returnv.x2=(a.x2*b.x1)+(a.y2*b.x2)+(a.z2*b.x3)+(a.w2*b.x4);
returnv.x3=(a.x3*b.x1)+(a.y3*b.x2)+(a.z3*b.x3)+(a.w3*b.x4);
//
returnv.y1=(a.x1*b.y1)+(a.y1*b.y2)+(a.z1*b.y3)+(a.w1*b.x4);
returnv.y2=(a.x2*b.y1)+(a.y2*b.y2)+(a.z2*b.y3)+(a.w2*b.x4);
returnv.y3=(a.x3*b.y1)+(a.y3*b.y2)+(a.z3*b.y3)+(a.w3*b.x4);
//
returnv.z1=(a.x1*b.z1)+(a.y1*b.z2)+(a.z1*b.z3)+(a.w1*b.x4);
returnv.z2=(a.x2*b.z1)+(a.y2*b.z2)+(a.z2*b.z3)+(a.w2*b.x4);
returnv.z3=(a.x3*b.z1)+(a.y3*b.z2)+(a.z3*b.z3)+(a.w3*b.x4);
//
returnv.w1=(a.x1*b.z1)+(a.y1*b.z2)+(a.z1*b.z3)+(a.w1*b.x4);
returnv.w2=(a.x2*b.z1)+(a.y2*b.z2)+(a.z2*b.z3)+(a.w2*b.x4);
returnv.w3=(a.x3*b.z1)+(a.y3*b.z2)+(a.z3*b.z3)+(a.w3*b.x4);
return returnv;
}

void matrix_mul( float *c, float *a, float *b )
{
int i,j,k;
for ( i=0; i<16; i++) c[i]=0;
for ( i=0; i<4; i++ )
for ( j=0; j<4; j++ )
for ( k=0; k<4; k++ )
c[i+4*j] += a[i+4*k] * b[k+4*j];
}

void main (void)
{
matrix a = {
1,2,3,4,
5,6,7,8,
9,10,11,12,
13,14,15,16
};

matrix b = {
17,18,19,20,
21,22,23,24,
25,26,27,28,
29,30,31,32
};

matrix n = matrixmulti(a,b);
printf ("%f %f %f %f\n", n.x1, n.y1, n.z1, n.w1);
printf ("%f %f %f %f\n", n.x2, n.y2, n.z2, n.w2);
printf ("%f %f %f %f\n", n.x3, n.y3, n.z3, n.w3);
printf ("%f %f %f %f\n", n.x4, n.y4, n.z4, n.w4);

printf ("my code\n");
matrix_mul( &n.x1, &a.x1, &b.x1);
printf ("%f %f %f %f\n", n.x1, n.y1, n.z1, n.w1);
printf ("%f %f %f %f\n", n.x2, n.y2, n.z2, n.w2);
printf ("%f %f %f %f\n", n.x3, n.y3, n.z3, n.w3);
printf ("%f %f %f %f\n", n.x4, n.y4, n.z4, n.w4);
printf ("---------\n");
}

0
Commented:
that's it:

c.x1 = (a.x1 * b.x1) + (a.x2 * b.y1) + (a.x3 * b.z1) + (a.x4 * b.w1);
c.x2 = (a.x1 * b.x2) + (a.x2 * b.y2) + (a.x3 * b.z2) + (a.x4 * b.w2);
c.x3 = (a.x1 * b.x3) + (a.x2 * b.y3) + (a.x3 * b.z3) + (a.x4 * b.w3);
c.x4 = (a.x1 * b.x4) + (a.x2 * b.y4) + (a.x3 * b.z4) + (a.x4 * b.w4);
c.y1 = (a.y1 * b.x1) + (a.y2 * b.y1) + (a.y3 * b.z1) + (a.y4 * b.w1);
c.y2 = (a.y1 * b.x2) + (a.y2 * b.y2) + (a.y3 * b.z2) + (a.y4 * b.w2);
c.y3 = (a.y1 * b.x3) + (a.y2 * b.y3) + (a.y3 * b.z3) + (a.y4 * b.w3);
c.y4 = (a.y1 * b.x4) + (a.y2 * b.y4) + (a.y3 * b.z4) + (a.y4 * b.w4);
c.z1 = (a.z1 * b.x1) + (a.z2 * b.y1) + (a.z3 * b.z1) + (a.z4 * b.w1);
c.z2 = (a.z1 * b.x2) + (a.z2 * b.y2) + (a.z3 * b.z2) + (a.z4 * b.w2);
c.z3 = (a.z1 * b.x3) + (a.z2 * b.y3) + (a.z3 * b.z3) + (a.z4 * b.w3);
c.z4 = (a.z1 * b.x4) + (a.z2 * b.y4) + (a.z3 * b.z4) + (a.z4 * b.w4);
c.w1 = (a.w1 * b.x1) + (a.w2 * b.y1) + (a.w3 * b.z1) + (a.w4 * b.w1);
c.w2 = (a.w1 * b.x2) + (a.w2 * b.y2) + (a.w3 * b.z2) + (a.w4 * b.w2);
c.w3 = (a.w1 * b.x3) + (a.w2 * b.y3) + (a.w3 * b.z3) + (a.w4 * b.w3);
c.w4 = (a.w1 * b.x4) + (a.w2 * b.y4) + (a.w3 * b.z4) + (a.w4 * b.w4);

have fun..
0

Experts Exchange Solution brought to you by

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Author Commented:
I don't get it. Your code matrix_mul( &n.x1, &a.x1, &b.x1);  how does it multiply all the matrix elements? Also, what did I do wrong in my program?
0
Commented:
first of, you simply forgot to multiply the last row of your matrix.. e.g. the w1 to w4 elements).

if you look at the code I sent you the last time, you notice, that there is a pattern which elements have to be multiplied. that's what the 3 for loops are for.

since your matrice is a structure of 16 floats, and mine is a array of 16 floats I can cheat the compiler and pass a pointer to the first float. in memory mine and your matrices are all the same.

say.. when I index the value a[1] I access element y1.. when I index a[2] I access z1 and so on.. your matrix is just sequential in memory.

nils

0
Author Commented:
so you are saying that your code and my code is the same? If so I will use yours.BTW I didn't multiply the last row, because it has no affect on the 3d points when you multiply them by the matrix. So I didn't have to worry about it.
0
Commented:
tell me if it works... and if not, then please reverse the order of the matrices in my routine..

nils

0
Author Commented:
what is the n.x1? Is that another matix that holds the result?
0
Commented:
ehm... which n.x1?
could you quote the text? I can't find it..

nils
0
Author Commented:
matrix_mul( &n.x1, &a.x1, &b.x1);

0
Commented:
jep. n is the matrix that receives the result of the multiplication.

Nils
0
###### It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.