Link to home
Start Free TrialLog in
Avatar of laeuchli
laeuchli

asked on

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?
Avatar of nils pipenbrinck
nils pipenbrinck


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];
}

Avatar of laeuchli

ASKER

what is the unrolled version?
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
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.
ok.. I'll check your code and compare with mine..

nils
Thanks nils.
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
  };


  printf ("your code: \n");
  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");
}

ASKER CERTIFIED SOLUTION
Avatar of nils pipenbrinck
nils pipenbrinck

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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?
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

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.
tell me if it works... and if not, then please reverse the order of the matrices in my routine..

nils


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

nils
matrix_mul( &n.x1, &a.x1, &b.x1);
 
jep. n is the matrix that receives the result of the multiplication.

Nils