-3

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;
  }
}
ellilu11
  • 1
  • 1

1 Answers1

0
  1. new is a bad name for pointer
  2. the main difference between both examples is dot_prod(),on the second example you removed that and it works. what is that function?
Elad Hazan
  • 331
  • 2
  • 7
  • I've included the dot_prod() function now. Both examples actually use dot_prod, but in the 2nd one I explicitly pass it the pointers to the row and column vector extracted from the matrices that I multiply. – ellilu11 Nov 13 '17 at 21:17