initialising array of unknown size (newbie)

A

Adam Chapman

Hi,

Im trying to migrate from programming in Matlab over to C. Im trying
to make a simple function to multiply one matrix by the other. I've
realised that C can't determine the size of a 2d array, so im
inputting the dimensions of those myself.

The problem is that the output array (C=A*B) has as many rows as A and
as many columns as B. I would think of initialising C with:

double C[A_rows][B_cols];

It looks like the compiler doesn't like this at all.

What is the best way to define C? could i use a structure data type
for A and B, or do the dimensions of C need to be defined using
pointers? Perhaps the malloc function comes in somewhere.

I would greatly appreciate any help.

Thanks
Adam
 
B

Ben Bacarisse

Adam Chapman said:
Im trying to migrate from programming in Matlab over to C. Im trying
to make a simple function to multiply one matrix by the other. I've
realised that C can't determine the size of a 2d array, so im
inputting the dimensions of those myself.

The problem is that the output array (C=A*B) has as many rows as A and
as many columns as B. I would think of initialising C with:

double C[A_rows][B_cols];

It looks like the compiler doesn't like this at all.

There is nothing obviously wrong with the above. It would help to see
the code or at least the error message. In particular, the "best"
solution will be different if the dimensions are fixed and know at
compile time, are fixed but known only at run time, or if they are
true arbitrary variables. Also, are the dimensions small?
What is the best way to define C? could i use a structure data type
for A and B, or do the dimensions of C need to be defined using
pointers? Perhaps the malloc function comes in somewhere.

Maybe. It is important to know if you can use C99. C99 (the current
standard) has some features that would make your task simpler. Rather
the talk about both, it would be better to know what version of C you
are using/obliged to use.

Have you seen the comp.lang.c FAQ? http://c-faq.com/
 
A

Adam Chapman

Adam Chapman said:
Im trying to migrate from programming in Matlab over to C. Im trying
to make a simple function to multiply one matrix by the other. I've
realised that C can't determine the size of a 2d array, so im
inputting the dimensions of those myself.
The problem is that the output array (C=A*B) has as many rows as A and
as many columns as B. I would think of initialising C with:
double C[A_rows][B_cols];
It looks like the compiler doesn't like this at all.

There is nothing obviously wrong with the above.  It would help to see
the code or at least the error message.  In particular, the "best"
solution will be different if the dimensions are fixed and know at
compile time, are fixed but known only at run time, or if they are
true arbitrary variables.  Also, are the dimensions small?
What is the best way to define C? could i use a structure data type
for A and B, or do the dimensions of C need to be defined using
pointers? Perhaps the malloc function comes in somewhere.

Maybe.  It is important to know if you can use C99.  C99 (the current
standard) has some features that would make your task simpler.  Rather
the talk about both, it would be better to know what version of C you
are using/obliged to use.
I'm currently using the visual C++ 2008 compiler, but trying to keep
the code as standard as possible so I can use it on embedded
hardwarew, something like gumstix.
Have you seen the comp.lang.c FAQ?  http://c-faq.com/

Thanks for te fast reply. Here is my current code:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>


int Arows=3, Acols=3, Brows=3, Bcols=3, Crows, Ccols;

int A[3][3]={1,2,3,4,5,6,7,8,9};
int B[3][3]={1,0,0,0,1,0,0,0,1};
int C = malloc(Arows * Bcols * sizeof(int));


main()
{
int row, col, i;

if (Acols!=Brows){
printf("Cannot compute; the number of columns of A
equals the number of rows of B");
for(;;);
return 0;
}


// Calculate Product
for(row=0; row<Arows; row++)
{
for(col=0; col<Bcols; col++)
{
C[row][col]=0;
for(i=0; i<Acols; i++)
{
*C[row][col]=C[row][col] + ((A[row])*(B
[col])); }
}
}

for(row=0; row<Arows; row++)
{
for(col=0; col<Bcols; col++)
{
// printf("%1d ", C[row][col]);
}
printf("\n");
}
for(;;);
return 0;
}

I'm getting "error C2099: initializer is not a constant" from the line
"int C = malloc(Arows * Bcols * sizeof(int));"

As for the size of an array, I'd like to make my function capable of
any size (but not huge enough to fill all the memory), this is
requirement for my overall project. I know I haven't made the function
take inputs properly yet, I'm just getting it to work first.

Thanks
Adam
 
B

Ben Bacarisse

Adam Chapman said:
Adam Chapman said:
Im trying to migrate from programming in Matlab over to C. Im trying
to make a simple function to multiply one matrix by the other. I've
realised that C can't determine the size of a 2d array, so im
inputting the dimensions of those myself.
The problem is that the output array (C=A*B) has as many rows as A and
as many columns as B. I would think of initialising C with:
double C[A_rows][B_cols];
It looks like the compiler doesn't like this at all.

There is nothing obviously wrong with the above.  It would help to see
the code or at least the error message.  In particular, the "best"
solution will be different if the dimensions are fixed and know at
compile time, are fixed but known only at run time, or if they are
true arbitrary variables.  Also, are the dimensions small?
What is the best way to define C? could i use a structure data type
for A and B, or do the dimensions of C need to be defined using
pointers? Perhaps the malloc function comes in somewhere.

Maybe.  It is important to know if you can use C99.  C99 (the current
standard) has some features that would make your task simpler.  Rather
the talk about both, it would be better to know what version of C you
are using/obliged to use.
I'm currently using the visual C++ 2008 compiler, but trying to keep
the code as standard as possible so I can use it on embedded
hardwarew, something like gumstix.

OK, then I think C99 is out. The very best portability is to be had
by aiming for the common intersection of C90 and C99. Essentially use
"old C" but avoid anything that interferes with (or is wrong in) the
new standard.

best not to quote sig blocks. In fact, it is best to interleave your
reply with the quoted test so you can comment on specific parts.
Thanks for te fast reply. Here is my current code:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>


int Arows=3, Acols=3, Brows=3, Bcols=3, Crows, Ccols;

It is not a good idea to duplicate information. It is better to
define these in a manner that can be used to define the arrays.
Maybe:

#define AROWS 3
#define ACOLS 3

int A[AROWS][ACOLS] = {/*...*/};
int A[3][3]={1,2,3,4,5,6,7,8,9};
int B[3][3]={1,0,0,0,1,0,0,0,1};
int C = malloc(Arows * Bcols * sizeof(int));

Well there is no need for malloc here. C can be defined thus:

int C[3][3];

but you knew that! I wonder why you thought malloc was needed (I'll
explain the error later).

This makes main and int rerturning function (correct) but in C99 this
"implicit int" declaration is not permitted. It is much better just
to write:

int main(void)
{
int row, col, i;

if (Acols!=Brows){
printf("Cannot compute; the number of columns of A
equals the number of rows of B");
for(;;);

Eh? If you are having the "my message disappears unless this is
there" then try to find the correct way to run your program so you can
see its output (I can't help with that -- I simply don't know).
return 0;
}


// Calculate Product
for(row=0; row<Arows; row++)
{
for(col=0; col<Bcols; col++)
{
C[row][col]=0;
for(i=0; i<Acols; i++)
{
*C[row][col]=C[row][col] + ((A[row])*(B
[col]));


You just want to write C[row][col] = ... (i.e. no *). Also, C has a
+= operator that simplifies this sort of thing.
}
}
}

for(row=0; row<Arows; row++)
{
for(col=0; col<Bcols; col++)
{
// printf("%1d ", C[row][col]);
}
printf("\n");
}

As a general point, I'd break this up into functions. At the very
least, I'd have a print_matrix function, but I would also be tempted
to put the A[X] * B[X] sum calculation into a function.
for(;;);
return 0;
}

I'm getting "error C2099: initializer is not a constant" from the line
"int C = malloc(Arows * Bcols * sizeof(int));"

This is because, at file scope, an object can only be initialised with
a compiler-time constant -- something that the compiler can work out.
A call to malloc is not such a thing. In fact, for simplicity, C
rules out all function calls in such positions, even those that could
be worked out by the compiler.
As for the size of an array, I'd like to make my function capable of
any size (but not huge enough to fill all the memory), this is
requirement for my overall project. I know I haven't made the function
take inputs properly yet, I'm just getting it to work first.

The "any size" is not really enough. The issue is whether the sizes
can be know at compile time. It you need a set of very general array
manipulation functions, be prepared for a lot of learning. Have you
looked to see if there is some free code available to do what you
need?

If you want fully flexible array sizes and C90 code you may well be
better off using arrays of pointers rather than 2D arrays. If there
is any chance that you might have to change the representation of your
arrays from one form to the other (maybe because of performance
issues) it could well pay to start off to use an opaque type right
from the start:

struct matrix *matrix_create(size_t rows, size_t cols);
element_t matrix_get(struct matrix *m, size_t row, size_t col);
void matrix_set(struct matrix *m, size_t row, size_t col, element_t e);

so you can change all the details at will later on.
 
A

Adam Chapman

Adam Chapman said:
Im trying to migrate from programming in Matlab over to C. Im trying
to make a simple function to multiply one matrix by the other. I've
realised that C can't determine the size of a 2d array, so im
inputting the dimensions of those myself.
The problem is that the output array (C=A*B) has as many rows as A and
as many columns as B. I would think of initialising C with:
double C[A_rows][B_cols];
It looks like the compiler doesn't like this at all.
There is nothing obviously wrong with the above.  It would help to see
the code or at least the error message.  In particular, the "best"
solution will be different if the dimensions are fixed and know at
compile time, are fixed but known only at run time, or if they are
true arbitrary variables.  Also, are the dimensions small?
What is the best way to define C? could i use a structure data type
for A and B, or do the dimensions of C need to be defined using
pointers? Perhaps the malloc function comes in somewhere.
Maybe.  It is important to know if you can use C99.  C99 (the current
standard) has some features that would make your task simpler.  Rather
the talk about both, it would be better to know what version of C you
are using/obliged to use.
I'm currently using the visual C++ 2008 compiler, but trying to keep
the code as standard as possible so I can use it on embedded
hardwarew, something like gumstix.

OK, then I think C99 is out.  The very best portability is to be had
by aiming for the common intersection of C90 and C99.  Essentially use
"old C" but avoid anything that interferes with (or is wrong in) the
new standard.

best not to quote sig blocks.  In fact, it is best to interleave your
reply with the quoted test so you can comment on specific parts.
Thanks for te fast reply. Here is my current code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int Arows=3, Acols=3, Brows=3, Bcols=3, Crows, Ccols;

It is not a good idea to duplicate information.  It is better to
define these in a manner that can be used to define the arrays.
Maybe:

#define AROWS 3
#define ACOLS 3

int A[AROWS][ACOLS] = {/*...*/};


int A[3][3]={1,2,3,4,5,6,7,8,9};
int B[3][3]={1,0,0,0,1,0,0,0,1};
int C = malloc(Arows  * Bcols * sizeof(int));

Well there is no need for malloc here.  C can be defined thus:

  int C[3][3];

but you knew that!  I wonder why you thought malloc was needed (I'll
explain the error later).

This makes main and int rerturning function (correct) but in C99 this
"implicit int" declaration is not permitted.  It is much better just
to write:

int main(void)
{
   int row, col, i;
   if (Acols!=Brows){
              printf("Cannot compute; the number of columns of A
equals the number of rows of B");
           for(;;);

Eh?  If you are having the "my message disappears unless this is
there" then try to find the correct way to run your program so you can
see its output (I can't help with that -- I simply don't know).
           return 0;
   }
    // Calculate Product
   for(row=0; row<Arows; row++)
   {
           for(col=0; col<Bcols; col++)
           {
                           C[row][col]=0;
                   for(i=0; i<Acols; i++)
                   {
                     *C[row][col]=C[row][col] + ((A[row])*(B
[col]));


You just want to write C[row][col] = ... (i.e. no *).  Also, C has a
+= operator that simplifies this sort of thing.
                                          }
           }
   }
   for(row=0; row<Arows; row++)
   {
           for(col=0; col<Bcols; col++)
           {
           //      printf("%1d   ", C[row][col]);
           }
           printf("\n");
   }

As a general point, I'd break this up into functions.  At the very
least, I'd have a print_matrix function, but I would also be tempted
to put the A[X] * B[X] sum calculation into a function.
   for(;;);
   return 0;
}
I'm getting "error C2099: initializer is not a constant" from the line
"int C = malloc(Arows  * Bcols * sizeof(int));"

This is because, at file scope, an object can only be initialised with
a compiler-time constant -- something that the compiler can work out.
A call to malloc is not such a thing.  In fact, for simplicity, C
rules out all function calls in such positions, even those that could
be worked out by the compiler.
As for the size of an array, I'd like to make my function capable of
any size (but not huge enough to fill all the memory), this is
requirement for my overall project. I know I haven't made the function
take inputs properly yet, I'm just getting it to work first.

The "any size" is not really enough.  The issue is whether the sizes
can be know at compile time.  It you need a set of very general array
manipulation functions, be prepared for a lot of learning.  Have you
looked to see if there is some free code available to do what you
need?

If you want fully flexible array sizes and C90 code you may well be
better off using arrays of pointers rather than 2D arrays.  If there
is any chance that you might have to change the representation of your
arrays from one form to the other (maybe because of performance
issues) it could well pay to start off to use an opaque type right
from the start:

  struct matrix *matrix_create(size_t rows, size_t cols);
  element_t matrix_get(struct matrix *m, size_t row, size_t col);
  void matrix_set(struct matrix *m, size_t row, size_t col, element_t e);

so you can change all the details at will later on.


Thanks. I want to eventually put the matrix multiplication function
into a header so it can be called from future scripts. The malloc was
for allocating memory for a matrix of size Arows*BCols, where Arows
and Bcols could be any size and are inputs to the function. Very
general I know, but still be useful when it finally works.
Looking at http://cboard.cprogramming.com/archive/index.php/t-57095.html
and http://www.hermetic.ch/cfunlib/arrays/arrays.htm, it looks very
hard. I will need to read about pointers over again (and probably
again and again!) but its all a good learnig experience I suppose.

Thanks for your time,
I appreciate it

Adam
 
B

Ben Bacarisse

Adam Chapman said:
On Oct 9, 1:49 pm, Ben Bacarisse <[email protected]> wrote:

If you intend to post to technical groups like this it will really
help you if you copy the style of posting that is favoured here: snip
lots (but keep enough context so your message makes sense) and
interleave your reply with the quoted text you are replying to.


It will also help if it looks like you are listening to the advice!
Thanks. I want to eventually put the matrix multiplication function
into a header so it can be called from future scripts.

One usually puts function prototypes in header files. The code itself
is usually elsewhere and is said to be "linked" with the code that
calls it. For this sort of program it would be normal to write a
library of matrix functions to link with future programs.
The malloc was
for allocating memory for a matrix of size Arows*BCols, where Arows
and Bcols could be any size and are inputs to the function. Very
general I know, but still be useful when it finally works.

And it would have worked (nearly) if it had been in a function. In C
it does not help to rough things out one way and then wrap it all up
in a function because C has so many special rules. What can be done
in one place is often not allowed elsewhere. It *really* helps to
choose your functions first and sketch them out. If you don't, you
will probably have to rewrite everything when you come to "wrap it up
in a function" later.

Yes it would. That is not good code. The variable names are hopeless
and there are no re-usable functions even for the most obviously
re-used code. The worst fault, though, is that that code does not
check any of the allocations and if you plan to write code for an
embedded device (I think you said this was your eventual target) then
this simply can't ignored.

Try reading:

http://www.eskimo.com/~scs/cclass/int/top.html

and look at Chapter 23. If you need some more basic stuff, try the
introduction to C:

http://www.eskimo.com/~scs/cclass/notes/top.html
I will need to read about pointers over again (and probably
again and again!) but its all a good learnig experience I suppose.

Note also that the code you cited does not really do 2D arrays. It
does arrays of pointers to arrays. This is just one way to represent
your data in "old C". The other is to pretend the array is flat (as
you seemed to be doing with your malloc call) and using a
multiplication to access the elements. Both have advantages and
disadvantages. It is not clear which will be better for you.
 
A

Adam Chapman

Adam Chapman said:
On Oct 9, 1:49 pm, Ben Bacarisse <[email protected]> wrote:

If you intend to post to technical groups like this it will really
help you if you copy the style of posting that is favoured here: snip
lots (but keep enough context so your message makes sense) and
interleave your reply with the quoted text you are replying to.


It will also help if it looks like you are listening to the advice!
Thanks. I want to eventually put the matrix multiplication function
into a header so it can be called from future scripts.

One usually puts function prototypes in header files.  The code itself
is usually elsewhere and is said to be "linked" with the code that
calls it.  For this sort of program it would be normal to write a
library of matrix functions to link with future programs.
The malloc was
for allocating memory for a matrix of size Arows*BCols, where Arows
and Bcols could be any size and are inputs to the function. Very
general I know, but still be useful when it finally works.

And it would have worked (nearly) if it had been in a function.  In C
it does not help to rough things out one way and then wrap it all up
in a function because C has so many special rules.  What can be done
in one place is often not allowed elsewhere.  It *really* helps to
choose your functions first and sketch them out.  If you don't, you
will probably have to rewrite everything when you come to "wrap it up
in a function" later.
Looking athttp://cboard.cprogramming.com/archive/index.php/t-57095.html
andhttp://www.hermetic.ch/cfunlib/arrays/arrays.htm, it looks very
hard.

Yes it would.  That is not good code.  The variable names are hopeless
and there are no re-usable functions even for the most obviously
re-used code.  The worst fault, though, is that that code does not
check any of the allocations and if you plan to write code for an
embedded device (I think you said this was your eventual target) then
this simply can't ignored.

Try reading:

 http://www.eskimo.com/~scs/cclass/int/top.html

and look at Chapter 23.  If you need some more basic stuff, try the
introduction to C:

 http://www.eskimo.com/~scs/cclass/notes/top.html
I will need to read about pointers over again (and probably
again and again!) but its all a good learnig experience I suppose.

Note also that the code you cited does not really do 2D arrays.  It
does arrays of pointers to arrays.  This is just one way to represent
your data in "old C".  The other is to pretend the array is flat (as
you seemed to be doing with your malloc call) and using a
multiplication to access the elements.  Both have advantages and
disadvantages.  It is not clear which will be better for you.

Done it!
For anyone looking this up, here is the code i ended up with:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

//double A[9], B[9];
int Arows=3, Acols=3, Brows=3, Bcols=3;


int A[3][3]={1,2,3,4,5,6,7,8,10};
int B[3][3]={9,8,7,6,5,4,3,2,1};


int **C;
int i, j, k, row, col;
main()
{
C=malloc(Arows * sizeof(int *));

for(i=0; i<Arows; i++)
{
C=malloc(Bcols * sizeof(int));
for(j=0; j<Bcols; j++)
{
C[j]=0;

for(k=0; k<Acols; k++)
{
C[j]+=A[k]*B[k][j];

}
printf("%0d ", C[j]);
}
printf("\n");
}
for(;;);
return C;
}


Now I've got to set it up to take A and B as inputs and make the
function return C. Will post when I've got it

Adam
 
K

Keith Thompson

Adam Chapman said:
Done it!
For anyone looking this up, here is the code i ended up with:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

//double A[9], B[9];
int Arows=3, Acols=3, Brows=3, Bcols=3;


int A[3][3]={1,2,3,4,5,6,7,8,10};
int B[3][3]={9,8,7,6,5,4,3,2,1};

You have 8 different occurences of the number 3 (not counting the two
in the initializers), and the relationship among the various 3s is not
sufficiently obvious. During maintenance, you could easily change one
of them and forget to change another one.

Also, Arows et al should really be constants. As written, you could
legally change their values; to understand your code, a reader has to
verify that you haven't done so.

Here's how I'd write the above. (A side note: "const" doesn't mean
"constant", it means read-only; "const int Arows = 3;" doesn't make
Arows a constant.)

#define AROWS 3
#define ACOLS 3
#define BROWS 3
#define BCOLS 3

int A[AROWS][ACOLS] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
int B[BROWS][BCOLS] = { {9, 8, 7}, {6, 5, 4}, {3, 2, 1} };

Note that the extra braces explicitly show the individual rows of the
array.

(Actually, I might replace the #define's with this:
enum { AROWS=3, ACOLS=3, BROWS=3, BCOLS=3 };
but some consider that an abuse of the enum feature.)
int **C;
int i, j, k, row, col;

Why are all these global? Why not declare them inside main?

Better: int main(void)
{
C=malloc(Arows * sizeof(int *));

malloc() can fail; it indicates this by returning a null pointer. You
should always check for this. If nothing else, you can just abort the
program.

And here's a useful idiom:

C = malloc(Arows * sizeof *C);

Even if the type of C changes (say, if you want arrays of doubles
rather than of ints), the call remains correct.
for(i=0; i<Arows; i++)
{
C=malloc(Bcols * sizeof(int));


Again, you don't check whether the malloc call succeded.

C = malloc(Bcols * sizeof *C);
for(j=0; j<Bcols; j++)
{
C[j]=0;

for(k=0; k<Acols; k++)
{
C[j]+=A[k]*B[k][j];

}
printf("%0d ", C[j]);
}
printf("\n");
}
for(;;);


You know this is an infinite loop, right? Which means ...
return C;

.... that this return statement will never be executed.
 
A

Adam Chapman

Thanks Keith, although your suggestions have brought up a lot of
errors.
Here is my current code:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>


#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}};
float C;


main(){
C=mat_mult();
for(;;); // to stop display closing down (needs proper fix)

}


mat_mult()
{
float **C;
int i, j, k;
C = malloc(Arows * sizeof *C);

for(i=0; i<Arows; i++)
{
C = malloc(Bcols * sizeof *C);
for(j=0; j<Bcols; j++)
{
C[j]=0;

for(k=0; k<Acols; k++)
{
C[j]+=A[k]*B[k][j];

}
printf("%0f ", C[j]);
}
printf("\n");
}

return C;
}

#define AROWS 3
#define ACOLS 3
#define BROWS 3
#define BCOLS 3

int A[AROWS][ACOLS] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
int B[BROWS][BCOLS] = { {9, 8, 7}, {6, 5, 4}, {3, 2, 1} };

gives "error C2143: syntax error : missing ']' before ';' "

Also, I keep getting this warning: "warning C4013: 'mat_mult'
undefined; assuming extern returning int" from the line
C=mat_mult();

Sorry if I sound stupid. This is quite difficult for me to get my head
around

Adam
 
L

Lew Pitcher

Thanks Keith, although your suggestions have brought up a lot of
errors.
Here is my current code:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>


#define Arows 3;
Note what the macro Arows expands to
#define Acols 3;
Note what the macro Acols expands to
#define Brows 3;
Note what the macro Brows expands to
#define Bcols 3;
Note what the macro Bcols expands to
float A[Arows][Acols]={{1,2,3},{4,5,6},{7,8,9}};
Hand expanding the macros, this line reads
float A[3;][3;]={{1,2,3},{4,5,6},{7,8,9}};
Are you sure that you want this?
float B[Brows][Bcols]={{9,8,7},{6,5,4},{3,2,1}};
Hand expanding the macros, this line reads
float B[3;][3;]={{9,8,7},{6,5,4},{3,2,1}};
Again, are you certain that this is what you want?
float C;


main(){

At this point, the function mat_mult() has not been declared or defined. The
compiler will /assume/ that mat_mult() takes an unknown set of arguments,
and returns an integer. Is this what you want?
C=mat_mult();

OK, the integer returned by mat_mult() is now converted to a float.
for(;;); // to stop display closing down (needs proper fix)

}


mat_mult()

This is an error in C99 - you need to tell the compiler what the type is of
the return value. In previous levels of C, the default is an integer. So,
either you have a syntax error (in C99) or you are returning an integer (in
prior levels of C).
{
float **C;

Here, you define an automatic variable with the same name as a file-duration
static variable. /This/ local variable is the one that the function will
use.
int i, j, k;
C = malloc(Arows * sizeof *C);

Hmmmmm.....

I'll leave it to others to comment on the rest of /this code. There's
something very suspicious here, but I don't feel qualified enough to give
it the proper analysis.
for(i=0; i<Arows; i++)
{
C = malloc(Bcols * sizeof *C);
for(j=0; j<Bcols; j++)
{
C[j]=0;

for(k=0; k<Acols; k++)
{
C[j]+=A[k]*B[k][j];

}
printf("%0f ", C[j]);
}
printf("\n");
}

return C;


You defined C as a pointer to a pointer to a float.
However,
a) you defined the function as returning an integer (assuming < C99)
b) you convert the integer to a float in your main() function
Oops. A pointer is neither an integer, nor a float.


}

#define AROWS 3
#define ACOLS 3
#define BROWS 3
#define BCOLS 3

int A[AROWS][ACOLS] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
int B[BROWS][BCOLS] = { {9, 8, 7}, {6, 5, 4}, {3, 2, 1} };

gives "error C2143: syntax error : missing ']' before ';' "

Also, I keep getting this warning: "warning C4013: 'mat_mult'
undefined; assuming extern returning int" from the line
C=mat_mult();

Sorry if I sound stupid. This is quite difficult for me to get my head
around

Adam

--
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. ------
 
A

Adam Chapman

the function mat_mult() has not been declared or defined. The
compiler will /assume/ that mat_mult() takes an unknown set of arguments,
and returns an integer. Is this what you want?

Ah I see, i need

float mat_mult();

declared. This will make the output of mat_mult a float.
Here, you define an automatic variable with the same name as a file-duration
static variable. /This/ local variable is the one that the function will
use.

Ok, so I changed all the "C's" in mat_mult to "d's", and deffined d
within the mat_mult function with "float **d".

So now I have

#include <stdio.h>
#include <stdlib.h>
#include <math.h>


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

float mat_mult();

main(){
float C;
C=mat_mult();
printf("%f",C[0][0]);
for(;;);
}


mat_mult()
{
float **d;
int i, j, k;
d = malloc(Arows * sizeof *d);

for(i=0; i<Arows; i++)
{
d = malloc(Bcols * sizeof *d );
for(j=0; j<Bcols; j++)
{
d[j]=0;

for(k=0; k<Acols; k++)
{
d[j]+=A[k]*B[k][j];

}
printf("%0f ", d[j]);
}
printf("\n");
}
return d;
}

Still need to define the input type for mat_mult, but my main concern
is that I get errors with the printf in main(). It says " error C2109:
subscript requires array or pointer type". Im not sure if main has
seen the output as a 2d array.
 
K

Keith Thompson

Adam Chapman said:
So now I have

#include <stdio.h>
#include <stdlib.h>
#include <math.h>


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

float mat_mult();

This declares that mat_mult takes an unspecified but fixed
number of arguments. If it takes no arguments, say so:

float mat_mult(void);


Make this:

int main(void) {

float C;
C=mat_mult();
Ok.

printf("%f",C[0][0]);

You just declared C as a float. Why are you trying to indix it as if
it were a two-dimensional array?

Why the infinite loop?
}


mat_mult()

Again, make this:

float mat_mult(void)

Incidentally, it usually makes more sense to use double rather than
float.
 
L

Lew Pitcher

(Oops - I mailed instead of posting - Apologies to adam and the rest of
c.l.c)

Posted as per personal dictum ("you post here, you read here")

the function mat_mult() has not been declared or defined. The
compiler will /assume/ that mat_mult() takes an unknown set of arguments,
and returns an integer. Is this what you want?

Ah I see, i need

float mat_mult();

declared. This will make the output of mat_mult a float.
Here, you define an automatic variable with the same name as a
file-duration static variable. /This/ local variable is the one that the
function will use.

Ok, so I changed all the "C's" in mat_mult to "d's", and deffined d
within the mat_mult function with "float **d".

So now I have

#include <stdio.h>
#include <stdlib.h>
#include <math.h>


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

float mat_mult();

main(){
    float C;

Here, C is declared and defined as a float

C=mat_mult();
printf("%f",C[0][0]);

Here, you code as if C were a two-dimensional array (with unknown
dimensions)

No.

Try
  printf("%f\n",C);

    for(;;);
}

Prior to your main() function, you declared mat_mult() as returning a float.
Below, you define mat_mult() as returning an int.
mat_mult()

This should be...
  float mat_mult()


OK, I just don't have the words to explain how wrong this function is.

From your original main(), I presumed that you wanted the function to return
a single floatingpoint value, but on second-read, I see that you really
intend for the function to return an array of floatingpoint values.
However, you /really/ haven't coded that.

First off, in C, you cannot return an array. You can either return a struct
(or union) that /contains/ an array, or you can return a pointer to the
first element of an array. That's it.

Secondly, arrays are contigiously allocated space. Elements of an array of
  type name[size];
can either be referenced by
  name[index]
or
  *(name+index)

A two-dimensional array can be thought of as a one-dimensional array, each
element of which is a one-dimensional array.

So, elements of an array of
  type name[n_rows][n_cols];
can either be referenced as
  name[row][col]
or as
  *(name + (row * n_cols) + col)

See how, as a pointer expression, the compiler /needs/ to know the size of
the inner one-dimensional array?

Similarly, elements of an array of
  type name[n_pages][n_rows][n_cols];
can either be referenced as
  name[page][row][col]
or as
  *(name + (page * n_rows * n_cols) + (row * n_cols) + col)


OK, now in /your/ code below, you don't build a multi-dimensional array..
Instead, you build a *tree* of pointers. Since the dimensions are unknown
at compile time, compile-time shortcuts (like array subscripting) aren't
going to work. You have to dereference each pointer and pointer-to-pointer
to get to the data underneath.

I'm going to ignore a lot of things below (like testing malloc() for
success, and size mismatches, and the like) and try to cut to the heart of
the matter
float **d;

d is an unitialized pointer to a pointer to a float.
    int i, j, k;
d = malloc(Arows * sizeof *d);

d now points to space for three pointers.
*d is permitted to be a pointer to a float
 
for(i=0; i<Arows; i++)
{
d = malloc(Bcols * sizeof *d );


Since you don't have multiple dimensions to contend with, you can get away
with
  d
being equivalent to
  *(d+i)
This works for this code, here, but /will not/ work for your later use as
access to a multi-dimensional array

each of the three spaces that d can access now points to some space. The
size of the space allocated for each of those elements is three times the
size of a pointer-to-float (d is a pointer-to a pointer-to a float, so *d
resolves to be a pointer-to a float. Since *d is the same as *(d+0), and
*(d+0) is the same as d[0], then d[0] resolves to a pointer-to a float, and
consequently so does d.) This is important, because you asked malloc()
to allocate some space for you based on /this size/. You didn't get the
space for three floatingpoint numbers; you got what you asked for - the
space for three pointers.

for(j=0; j<Bcols; j++)
{
d[j]=0;


First off, you can't access your pointer-tree in this manner. It is not a
multi-dimensional array, but is a tree of pointers and
pointers-to-pointers.

Secondly, you haven't allocated space for the floatingpoint values yet, so
trying to assign anything other than a pointer value is futile and an
error.

Thirdly (and not too consequentially), 0 is not a floatingpoint value.
However 0.0 is. The good news is that, had the  left-hand-side of the
statement correctly resolved to a floatingpoint data type, C would have
converted your integer 0 to floatingpoint 0.0 for you.

for(k=0; k<Acols; k++)
{
d[j]+=A[k]*B[k][j];

}
printf("%0f   ", d[j]);
}
printf("\n");
}
return d;


No. You are returning a pointer. A pointer to an automatic variable that
disappears /with/ the return. You don't want to do this.
}

Still need to define the input type for mat_mult, but my main concern
is that I get errors with the printf in main(). It says " error C2109:
subscript requires array or pointer type". Im not sure if main has
seen the output as a 2d array.

See above
--
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. ------
 
B

Ben Bacarisse

Adam Chapman said:
So now I have

#include <stdio.h>
#include <stdlib.h>
#include <math.h>


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

Just so I can improve my style, what was it about Keith Thompson
suggesting this that made you take note when you seemed ignore the
same suggestion from me several messages ago? :)

float **d;
int i, j, k;
d = malloc(Arows * sizeof *d);

You are heading into trouble here. It is very unwise to use both a 2D
array like A and B and an array of pointers like d. You will end up
with code that can't be combined in useful ways. The result of the
matrix multiply is in a different format (in C terms a different type)
to the data that is operates on. You would not, for example, be able
to multiply the result of a multiplication.

You should pick either the contiguous representation used for A and B
or the array of pointers representation used for d and not mix them.
 
L

Lew Pitcher

On October 9, 2008 17:24, in comp.lang.c, Lew Pitcher
([email protected]) wrote:
[snip]
Prior to your main() function, you declared mat_mult() as returning a
float. Below, you define mat_mult() as returning an int.
mat_mult()

This should be...
float mat_mult()
{ [snip]
float **d; [snip]
return d;

No. You are returning a pointer.

Oops... The following is incorrect...
A pointer to an automatic variable that
disappears /with/ the return.

The pointer is pointing to valid malloc()ed memory. It won't disappear when
the function returns.
You don't want to do this.


--
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. ------
 
L

Lew Pitcher

On October 9, 2008 16:36, in comp.lang.c, Adam Chapman
([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} };
[snip]
mat_mult()
{
[snip]
}

OK, let's stop fiddling around and fix this thing.

Let's see if I can state your requirements for the mat_mult() function, and
then let's design and build it properly.

mat_mult() should dynamically allocate space for an array-multiply
resultset, and multiply two static, fixed-sized arrays, placing the results
into the dynamically allocted space. The function should return a pointer
to the results array to the caller, so that the results can be further
manipulated, and the array freed.

Does that sound like it?

If so, then we make some decisions:
1) mat_mult() will take no arguments, as its inputs are all statically
allocated, and of known fixed sizes
2) as C functions cannot return arrays without language trickery, the
function will return a pointer to the first element of the results array.
The caller will be responsible for determining the size of the array (the
size is fixed and known to the caller, so this shouldn't be a problem), and
must dispose of the array by use of a call to free() with the returned
pointer,
3) the function will return NULL on any failure,
3) the function will use malloc() to dynamically allocate space for the
results array. NULL from malloc() constitutes a failure condition.

So, at first try, we have a function like this....

float *mat_mult(void)
{
float *resultset;

/* matrix multiply A and B to result in resultset */
return resultset;
}

Now, let's fill in a bit of the logic. First, to allocate the result set
space

#define Arows 3
#define Acols 3

#include <stdlib.h>

float *mat_mult(void)
{
float *resultset;
/* 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 */

/* matrix multiply A and B to result in resultset */

return resultset;
}


Now, add in some (unnecessary) logic to initialize the result set space

#define Arows 3
#define Acols 3

#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 */

return resultset;
}


Now, add in the matrix multiplication logic

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


Finally, add in your driver (in this case, main())

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

#include <stdio.h>

int main(void)
{
float *Results;
int row, col;

/* try matrix multiplication - exit EXIT_FAILURE on failure */
if ((Results = mat_mult()) == 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;
}

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. ------
 
B

Barry Schwarz

Thanks Keith, although your suggestions have brought up a lot of
errors.
Here is my current code:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>


#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}};
float C;


main(){

This states that main returns int.
C=mat_mult();

There is no prototype in scope for mat_mult. The compiler is required
to assume it returns int. The int value will be converted to match
the float type of C.
for(;;); // to stop display closing down (needs proper fix)

One possible way is to print a message telling the user to press enter
and using getchar to wait until then.

Where is the int that main should return?
}


mat_mult()

This states that mat_mult returns int.
{
float **C;

You do realize that this C hides the global C you defined above.
int i, j, k;
C = malloc(Arows * sizeof *C);

for(i=0; i<Arows; i++)
{
C = malloc(Bcols * sizeof *C);
for(j=0; j<Bcols; j++)
{
C[j]=0;

for(k=0; k<Acols; k++)
{
C[j]+=A[k]*B[k][j];

}
printf("%0f ", C[j]);
}
printf("\n");
}

return C;


Why did you ignore the diagnostic you compiler generated for this
statement? mat_mult is returning an int. C has type float**. The
two are incompatible.
}

#define AROWS 3
#define ACOLS 3
#define BROWS 3
#define BCOLS 3

int A[AROWS][ACOLS] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
int B[BROWS][BCOLS] = { {9, 8, 7}, {6, 5, 4}, {3, 2, 1} };

gives "error C2143: syntax error : missing ']' before ';' "

This message is probably from when your #define included the
semicolon.
Also, I keep getting this warning: "warning C4013: 'mat_mult'
undefined; assuming extern returning int" from the line

Where is the prototype that would tell the compiler what it needed to
know about mat_mult.
 
L

Lew Pitcher

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. ------
 
A

Adam Chapman

Thankyou all. Sorry if it seemed like i was ignoring, Im sure you know
how hard it is to take everything in when you are stressed and
confused!
   #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;
  }

When I try to compile this, i get " error C2440: '=' : cannot convert
from 'void *' to 'float *' " from the line
((resultset = malloc(nRows * nCols * sizeof(float))) == NULL)

The error is surely coming from the
resultset = malloc(nRows * nCols * sizeof(float))

part. My understanding is that before that particular line, resultset
is a pointer to a memory block big enough to hold a float.
The above line tries to make resultset a pointer to a larger memory
block, big enough for the array we are making.
I can't see what would be seen as " void * " in that expression
though. Could it be that malloc returns a void type (i.e. nothing?)
 
J

Joachim Schmitz

Adam said:
Thankyou all. Sorry if it seemed like i was ignoring, Im sure you know
how hard it is to take everything in when you are stressed and
confused!
#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;
}

When I try to compile this, i get " error C2440: '=' : cannot convert
from 'void *' to 'float *' " from the line
((resultset = malloc(nRows * nCols * sizeof(float))) == NULL)

The error is surely coming from the
resultset = malloc(nRows * nCols * sizeof(float))

part. My understanding is that before that particular line, resultset
is a pointer to a memory block big enough to hold a float.
The above line tries to make resultset a pointer to a larger memory
block, big enough for the array we are making.
I can't see what would be seen as " void * " in that expression
though. Could it be that malloc returns a void type (i.e. nothing?)

malloc returns a void * which in C should convert to (alost) everything
automagically. It does not in C++ (it requres a cast, so it seems likely
you're operating your compiler in C++ mode.

Bye, Jojo
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top