OK, now let's improve on the mat_mult() function a bit...
On October 9, 2008 18:16, in comp.lang.c, Lew Pitcher
(
[email protected]) wrote:
[snip]
#define Arows 3
#define Acols 3
#define Brows 3
#define Bcols 3
float A[Arows][Acols]={ {1,2,3}, {4,5,6}, {7,8,9} };
float B[Brows][Bcols]={ {9,8,7}, {6,5,4}, {3,2,1} };
#include <stdlib.h>
float *mat_mult(void)
{
float *resultset;
int row, col;
/* allocate space for the result set, point resultset at the space */
if ((resultset = malloc(Arows * Acols * sizeof(float))) == NULL)
return NULL; /* first error condition */
/* at this point, resultset points at a space big enough for our
entire
results table. Now, let's initialize it */
for (row = 0; row < Arows; ++row)
{
for (col = 0; col < Acols; ++col)
{
*(resultset + (row * Acols) + col) = 0.0;
}
}
/* matrix multiply A and B to result in resultset */
for (row = 0; row < Arows; ++row)
{
for (col = 0; col < Acols; ++col)
{
*(resultset + (row * Acols) + col) = A[row][col]*B[row][col];
}
}
return resultset;
}
[snip]
Let's add in some new constraints/assumptions:
1) Both source matrices will have the same number of rows and columns
(we already have this assumption, but I didn't state it before)
2) The number of rows and columns will be dynamic, so that the matrix
multiply can be used on a variety of matrices
3) The two source matrices will be dynamic, so that we can use the function
on a variety of m*n matrices
So, we'll now change the mat_mult() function so that it takes as arguments
a) a pointer to the first element of the first source matrix,
b) a pointer to the first element of the second source matrix,
c) a count of the number of rows in the matrices, and
d) a count of the number of columns in the matrices
and we'll make the function use these values in its matrix multiply.
First off, we change the function so as to add the four new arguments...
#include <stdlib.h>
float *mat_mult(float *matrixA, float *matrixB, int nRows, int nCols)
{
float *resultset;
int row, col;
/* allocate space for the result set, point resultset at the space */
if ((resultset = malloc(Arows * Acols * sizeof(float))) == NULL)
return NULL; /* first error condition */
/* at this point, resultset points at a space big enough for our
entire
results table. Now, let's initialize it */
for (row = 0; row < Arows; ++row)
{
for (col = 0; col < Acols; ++col)
{
*(resultset + (row * Acols) + col) = 0.0;
}
}
/* matrix multiply A and B to result in resultset */
for (row = 0; row < Arows; ++row)
{
for (col = 0; col < Acols; ++col)
{
*(resultset + (row * Acols) + col) = A[row][col]*B[row][col];
}
}
return resultset;
}
Next, change the code so that it uses the new nRows and nCols arguments
instead of the old Arows and Acols macros.
#include <stdlib.h>
float *mat_mult(float *matrixA, float *matrixB, int nRows, int nCols)
{
float *resultset;
int row, col;
/* allocate space for the result set, point resultset at the space */
if ((resultset = malloc(nRows * nCols * sizeof(float))) == NULL)
return NULL; /* first error condition */
/* at this point, resultset points at a space big enough for our
entire
results table. Now, let's initialize it */
for (row = 0; row < nRows; ++row)
{
for (col = 0; col < nCols; ++col)
{
*(resultset + (row * nCols) + col) = 0.0;
}
}
/* matrix multiply A and B to result in resultset */
for (row = 0; row < nRows; ++row)
{
for (col = 0; col < nCols; ++col)
{
*(resultset + (row * nCols) + col) = A[row][col]*B[row][col];
}
}
return resultset;
}
Next, change the function to use the two argument matrices
#include <stdlib.h>
float *mat_mult(float *matrixA, float *matrixB, int nRows, int nCols)
{
float *resultset;
int row, col;
/* allocate space for the result set, point resultset at the space */
if ((resultset = malloc(nRows * nCols * sizeof(float))) == NULL)
return NULL; /* first error condition */
/* at this point, resultset points at a space big enough for our
entire
results table. Now, let's initialize it */
for (row = 0; row < nRows; ++row)
{
for (col = 0; col < nCols; ++col)
{
*(resultset + (row * nCols) + col) = 0.0;
}
}
/* matrix multiply A and B to result in resultset */
for (row = 0; row < nRows; ++row)
{
for (col = 0; col < nCols; ++col)
{
*(resultset + (row * nCols) + col) =
*(matrixA + (row * nCols) + col) *
*(matrixB + (row * nCols) + col);
}
}
return resultset;
}
Finally, let's add the driver again...
#include <stdlib.h>
float *mat_mult(float *matrixA, float *matrixB, int nRows, int nCols)
{
float *resultset;
int row, col;
/* allocate space for the result set, point resultset at the space */
if ((resultset = malloc(nRows * nCols * sizeof(float))) == NULL)
return NULL; /* first error condition */
/* at this point, resultset points at a space big enough for our
entire
results table. Now, let's initialize it */
for (row = 0; row < nRows; ++row)
{
for (col = 0; col < nCols; ++col)
{
*(resultset + (row * nCols) + col) = 0.0;
}
}
/* matrix multiply A and B to result in resultset */
for (row = 0; row < nRows; ++row)
{
for (col = 0; col < nCols; ++col)
{
*(resultset + (row * nCols) + col) =
*(matrixA + (row * nCols) + col) *
*(matrixB + (row * nCols) + col);
}
}
return resultset;
}
#define Arows 3
#define Acols 3
#define Brows 3
#define Bcols 3
float A[Arows][Acols]={ {1,2,3}, {4,5,6}, {7,8,9} };
float B[Brows][Bcols]={ {9,8,7}, {6,5,4}, {3,2,1} };
#include <stdio.h>
int main(void)
{
float *Results;
int row, col;
/* Sanity check our array bounds */
if ((Arows != Brows) || (Acols != Bcols))
{
printf("Gaak - our arrays aren't of the same size\n");
return EXIT_FAILURE;
}
/* try matrix multiplication - exit EXIT_FAILURE on failure */
if ((Results = mat_mult(&A[0][0],&B[0][0],Arows,Acols)) == NULL)
{
printf("Gaak - we ran into an error\n");
return EXIT_FAILURE;
}
/* Print out the result set */
for (row = 0; row < Arows; ++row)
{
printf("[%d]\t",row);
for (col = 0; col < Acols; ++col)
{
printf("%f\t",*(Results + (row * Acols) + col));
}
printf("*\n");
}
printf("End of results\n");
/* Free the allocated space */
free(Results);
return EXIT_SUCCESS;
}
We could make some further "style" changes (optimizing some common
sub-expressions, making some allocation parameters more robust, etc.), but
we don't really have to. So, we're done this generalization.
Next change: multiply matrices of different sizes
HTH
--
Lew Pitcher
Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------