NO

Author Topic: How to handle matrices and using pointer instead ...  (Read 9455 times)

delper

  • Guest
How to handle matrices and using pointer instead ...
« on: June 21, 2008, 05:54:34 PM »
Hi C Wizards,

I have this routine, which work perfectly fine if the matrix is small (5x5), but fails miserably with the matrix is larger (15 x 15).. ... I need to operate with matrices that are at least 500 x 500 (or even 2000 x 2000 and they are float units).  My basic routine is:

float *MatrixMultiply (int r1, int c1, float Array1[][c1], int c2, float Array2[][c2], float Result[r1][c2])   
{
   int i, j, k;
   for (i = 0; i < r1; i++)   
   {
      for (j = 0; j < c2; j++)   
      {
         Result[j] = 0.0;
         for (k = 0; k < c1; k++)     // c1 == r2
         {
            Result[j] += Array1[k] * Array2[k][j];
         }
      }
   }
   return Result[0];
}

If I test this with

float malo [3][3] ={1.0, 0.7, 0.1, 0.56, 1.43, 0.21, 0.56, 0.43, 1.21};
float bueno [3][3] ={2.0, 7.0, 5.1, 5.6, 4.3, 2.1, 6.8, 4.83, 2.1};

it works perfectly, but it fails when I try a larger matrix (15 x 15).  Does any one knows what is going on?   

On the other hand, apparently, I am not doing a good work by sending the matrix as an argument, and instead I should be sending pointers (so the matrices are manipulated directly).   Does anyone knows how I can change this to use pointers???

Thanks in advanced

Regards

JohnF

  • Guest
Re: How to handle matrices and using pointer instead ...
« Reply #1 on: June 22, 2008, 08:32:12 AM »
Try reading the C FAQ

http://c-faq.com/

I'm not sure what your code is trying to do, it doesn't seem like a matrix multiply.

EDIT: I found this, it might help. It's not multiplying the same as yours. You might need different functions to deal with 3*3, 4*4 etc.

Code: [Select]
#include <stdio.h>

void MatrixMultiply3x3(float array1[3][3], float array2[3][3],
float result[3][3])
{
for (int r = 0; r < 3; r++)
{
for (int c = 0; c < 3; c++)
{
result[r][c] = (array1[r][0] * array2[0][c]) +
(array1[r][1] * array2[1][c]) +
(array1[r][2] * array2[2][c]) +
(array1[r][3] * array2[3][c]);
}
}
}

float malo [3][3] ={{1.0, 0.7, 0.1}, {0.56, 1.43, 0.21}, {0.56, 0.43, 1.21}};
float bueno [3][3] ={{2.0, 7.0, 5.1}, {5.6, 4.3, 2.1}, {6.8, 4.83, 2.1}};
float out [3][3];

int main(void)
{
int row = 3;
int col = 3;

MatrixMultiply3x3(malo, bueno, out);

for(int i = 0; i<row; i++){
for(int j = 0; j<col; j++){
printf("%f\n", out[i][j]);
}
}
return 0;
}

This way would be faster however.

Code: [Select]

void MatrixMultiply3x3(float in1[3][3], float in2[3][3], float out[3][3])
{
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
}

John
« Last Edit: June 22, 2008, 10:38:36 AM by JohnF »

delper

  • Guest
Re: How to handle matrices and using pointer instead ...
« Reply #2 on: June 23, 2008, 06:36:02 AM »
Hi JohnF,

     Thanks for answering, but I don't think the problem is the routine.  The functions does the multiplication perfectly but fails with big matrices.  Is there a way to send a pointer to a matrix? (instead of what I am doing which is sending the whole matrix to the function).


JohnF

  • Guest
Re: How to handle matrices and using pointer instead ...
« Reply #3 on: June 23, 2008, 09:16:39 AM »
Hi JohnF,

     Thanks for answering, but I don't think the problem is the routine.  The functions does the multiplication perfectly but fails with big matrices.  Is there a way to send a pointer to a matrix? (instead of what I am doing which is sending the whole matrix to the function).

Well, first off, I can't get your code to compile even, and guess that your routine is not a classic MatrixMultiply but you probably have a good reason for that.

Second, you are not sending the whole matrix, C works with pointers to arrays when they are passed to functions. If you watch in the debugger you will see that the array objects are actually 'float *', which is pointer to float. When using
Code: [Select]
arr[x][y]
this is a convenient way to manage them as the compiler does all the offset calculations for you. There is no reason to change it.

If your routine is failing with bigger mats the problem is most likely with your code. Personally I can't see what you are doing.

For example you have this line that does not compile.

  Result[j] += Array1[k] * Array2[k][j];
 
Shouldn't that be

  Result[k][j] = Array1[k][j] * Array2[k][j];

Anyway, you should post a complete working example or one that uses bigger mats that fails.

John

« Last Edit: June 23, 2008, 09:30:24 AM by JohnF »

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 2115
Re: How to handle matrices and using pointer instead ...
« Reply #4 on: June 23, 2008, 09:30:15 AM »
Modified John's code with pointers
Quote
Is there a way to send a pointer to a matrix?
Code: [Select]
#include <stdio.h>


void MatrixMultiply3x3(float array1[3][3], float array2[3][3], float result[3][3])
{
for (int r = 0; r < 3; r++)
{
for (int c = 0; c < 3; c++)
{
result[r][c] = (array1[r][0] * array2[0][c]) +
(array1[r][1] * array2[1][c]) +
(array1[r][2] * array2[2][c]) +
(array1[r][3] * array2[3][c]);
}
}
}

void MatrixMultiply3x3p(float *array1, float *array2, float *result)
{
for (int r = 0; r < 3; r++)
{
for (int c = 0; c < 3; c++)
{
result[r*3+c] = (array1[r*3] * array2[c]) +
(array1[r*3+1] * array2[1*3+c]) +
(array1[r*3+2] * array2[2*3+c]) +
(array1[r*3+3] * array2[3*3+c]);
}
}
}

float malo [3][3] ={{1.0, 0.7, 0.1}, {0.56, 1.43, 0.21}, {0.56, 0.43, 1.21}};
float bueno [3][3] ={{2.0, 7.0, 5.1}, {5.6, 4.3, 2.1}, {6.8, 4.83, 2.1}};
float out [3][3];

int main(void)
{
int row = 3;
int col = 3;

printf("MatrixMultiply3x3\n");
MatrixMultiply3x3(malo, bueno, out);
for(int i = 0; i<row; i++){
for(int j = 0; j<col; j++){
printf("%f\n", out[i][j]);
}
}
printf("MatrixMultiplyp3x3\n");
MatrixMultiply3x3p(&malo[0][0], &bueno[0][0], &out[0][0]);
for(int i = 0; i<row; i++){
for(int j = 0; j<col; j++){
printf("%f\n", out[i][j]);
}
}
return 0;
}
« Last Edit: June 23, 2008, 09:41:55 AM by timovjl »
May the source be with you

JohnF

  • Guest
Re: How to handle matrices and using pointer instead ...
« Reply #5 on: June 23, 2008, 09:34:00 AM »
Thanks timovjl but it should not be necessary and is messy and prone to errors IMO.

John

delper

  • Guest
Re: How to handle matrices and using pointer instead ...
« Reply #6 on: June 24, 2008, 06:48:01 AM »
Hi John,

    I didn't know what you were talking about until you pointed out the issue that the code was not "copied" correctly.   I do apologize for the error in pasting the code before.   However, I am sure the correct code is OK....

    I am looking at the other matrices subroutines, since I still have an error in my program.   Thanks a lot for confirming that the matrix parameter input is adequate. 

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2113
Re: How to handle matrices and using pointer instead ...
« Reply #7 on: June 24, 2008, 12:28:09 PM »
Delper I don't know why you wan't give the real code, but I think it's not relevent here.
As John have already told you in 'C' passing an array it's equivalent to pass the array address (only structures may sometimes be passed by value, but in the last PellesC release they also are passed by reference). Timovjl gave you routines that perform manually the addressing of array elements, that as John said may be prone to errors, but useful in case you want use some assembler handling.
Anyway if your code fails on large matrices this is undoubtless due to wrong addressing or bad index. When using small matrices you don't access memory so far away to trigger the memory violation, but when using large matrices you'll address very far away memory areas that uncover the error.
If you want to speed up execution try to use SSE instructions to perform parallel calculation using assembly code. In this case you have to be much more carefull to avoid errors.
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

delper

  • Guest
Re: How to handle matrices and using pointer instead ...
« Reply #8 on: June 25, 2008, 05:29:06 AM »
Hi Frankie,

    I didn't mean to "hide" the code, but I pasted it in a wrong way.  I didn't know there were a "code" option to paste the code; anyway, it become irrelevant to my issue. 

    I have quite a few routines handling matrices and I "thought" the multiplication was failing, but as JohnF illustrated to me, the problem was not there. 

    I don't want to use assembler ... no yet.     Time will come for it... Anyway, thanks for your suggestions.

DB

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 2115
Re: How to handle matrices and using pointer instead ...
« Reply #9 on: June 25, 2008, 08:33:50 AM »
Is this enought to test that problem?
Give us that bigger malo and bueno that fails.

Code: [Select]
#include <stdio.h>

float *MatrixMultiply (int r1, int c1, float Array1[][c1], int c2, float Array2[][c2], float Result[r1][c2])
{
   int i, j, k;
   for (i = 0; i < r1; i++)   
   {
      for (j = 0; j < c2; j++)   
      {
         Result[i][j] = 0.0;
         for (k = 0; k < c1; k++)     // c1 == r2
         {
            Result[i][j] += Array1[i][k] * Array2[k][j];
         }
      }
   }
   return Result[0];
}

float malo [3][3] ={{1.0, 0.7, 0.1}, {0.56, 1.43, 0.21}, {0.56, 0.43, 1.21}};
float bueno [3][3] ={{2.0, 7.0, 5.1}, {5.6, 4.3, 2.1}, {6.8, 4.83, 2.1}};
float out [3][3];

int main(void)
{
int row = 3;
int col = 3;

MatrixMultiply(row, col, malo, col, bueno, out);
printf("MatrixMultiply\n");
for(int i = 0; i<row; i++){
for(int j = 0; j<col; j++){
printf("%f\t", out[i][j]);
}
printf("\n");
}

return 0;
}
May the source be with you