Still need to get the hang of pointers in C so I wouldn't be surprised if this has a simple explanation...
I have code to perform matrix multiplication in C. To do this, I've defined a custom matrix struct which encodes the entire matrix in a row major 1D array to avoid passing double pointers:
typedef struct matrix matrix;
struct matrix {
int n_rows;
int n_cols;
double *entries;
};
The problem is when I pass a pointer to this matrix struct as an arg to my matrix multiply function.
matrix *matrix_mult(matrix *m, matrix *n){
if (m->n_cols != n->n_rows){
fprintf(stderr, "dimension mismatch\n");
exit(1);
} else {
int rows = m->n_rows;
int cols = n->n_cols;
matrix *new = (matrix*)malloc(8+rows*cols*sizeof(double));
new->n_rows = rows;
new->n_cols = cols;
new->entries = (double*)malloc(rows*cols*sizeof(double));
for (int i = 0; i < rows*cols; i++) new->entries[i] = dot_prod( row_vec(m, i/cols), col_vec(n, i%cols) );
}
return new;
}
Written this way, certain matrix elements get mysteriously zeroed out when the whole matrix is passed to matrix_mult! For instance, I have a 3x3 matrix *M whose entries are initialized as:
1.000000 0.000000 0.000000 0.250000 1.000000 0.000000 0.062500 0.500000 1.000000
When I pass *M to matrix_mult and ask matrix_mult to printf the entries I find that they are now (this is before the matrix mult is ever performed):
1.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.062500 0.500000 0.000000
However, when I modify matrix_mult as follows, explicitly defining a row and column vector to perform the dot product:
matrix *matrix_mult(matrix *m, matrix *n){
/* code */
for (i = 0; i < rows*cols; i++){
rv = row_vec(m, i/cols);
cv = col_vec(n, i%cols);
new->entries[i] = dot_prod( rv, cv );
matrix_free(rv);
matrix_free(cv);
}
return new;
}
Having matrix_mult printf the entries of M now gives:
1.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.062500 0.500000 1.000000
Thus changing (seemingly unrelated) code has somehow modified the value of the matrix entries! Any clue what's going on?
EDIT: The dot_prod function is as follows:
/* takes the dot product of a row vector with a column vector;
returns error if args are not row or column vectors;
or if the size of the vectors are not equal */
double dot_prod(matrix *rv, matrix *cv){
if ((rv->n_rows != 1) || (cv->n_cols != 1)){
fprintf(stderr, "arg(s) are not row or column vectors\n");
exit(1);
} else if (rv->n_cols != cv->n_rows){
fprintf(stderr, "dimension mismatch\n");
exit(2);
} else {
double n = 0;
int l = rv->n_cols;
for (int i = 0; i < l; i++) n += rv->entries[i]*cv->entries[i];
return n;
}
}