HiveBrain v1.2.0
Get Started
← Back to all entries
patterncMinor

Matrices in C implementation

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
implementationmatricesstackoverflow

Problem

I recently wrote a C implementation of Matrices with add, subtract, and multiply. I want to expand this out eventually where I can diagonalize, efficiently square, row-reduce, etc...

I was wondering if there are any more efficient ways to do what I'm currently doing (I'm really new to C and pointers/references in general) and without changing too much, getting

*(result.matrix+ i*r  + j)


to work like

result[i][j]


Here's the code below

```
/**
Matrix Multiplication
matrices.c
Matrix data structure in C.

@author Michael Asper
@version 1.0 3/29/17
*/

#include
#include
#include

typedef struct Matrix {
int rowSize;
int columnSize;
long int* matrix;
} Matrix;

/**
Randomizes the elements of a matrix

@param *m pointer to Matrix to randomize;
*/
void randomize(Matrix *m){
int i,j;
for(i = 0; i rowSize ; i++){
for(j = 0; j columnSize; j++){
(m->matrix + im->rowSize + j)= rand() % 5000;
}
}
}

/**
Returns a r x c Matrix with all 0s.

@param r The row size of the matrix
@param c The column size of the matrix
@return r x c Matrix
*/
Matrix createMatrix(int r, int c){
Matrix temp = {r, c, calloc(r c, sizeof(long int ))};
return temp;
}

/**
Returns a r x c Matrix with random numbers.

@param r The row size of the matrix
@param c The column size of the matrix
@return r x c Matrix
*/
Matrix createRandMatrix(int r, int c){
Matrix temp = createMatrix(r,c);
randomize(&temp);
return temp;
}

/**
Prints matrix.

@param *m Pointer to Matrix you want to print
*/
void printMatrix(Matrix *m){

int i,j;
for(i = 0; i rowSize ; i++){
for(j = 0; j columnSize; j++){
printf("%li ", (m->matrix + im->rowSize + j));
}
printf("\n");
}
}

/**
Adds two matrices together

@param *a pointer to first matrix (A);
@param *b pointer to second matrix (B);
@ret

Solution

I just wanted to comment on your question about accessing the array efficiently. You ask:


I was wondering if there are any more efficient ways to do what I'm currently doing (I'm really new to C and pointers/references in general) and without changing too much, getting


(result.matrix+ ir + j)


to work like


result[i][j]

One way is to do as @mdfst13 has recommended and allocate an array of arrays. That's a fine way to do it, but it can be a performance issue when accessing the array element by element in a loop. CPUs generally optimize to access the next few bytes past the last access since you're likely to need bytes near the ones you previously accessed. If you have a separate array per row, this can throw off that optimization when you reach the end of each row. You'd want to first profile to verify that's an issue or not. If it is, another option you have is to leave it as a single allocation and simply write an accessor function. Something like:

long int getElement(const Matrix m, const int r, const int c)
{
    return *(m.matrix + r * m.rowSize + c);
}


This also allows you the opportunity to do some range checking when in debug mode by doing something like:

long int getElement(const Matrix m, const int r, const int c)
{
#if DEBUG
    assert((r >= 0) && (r = 0) && (c < m.colSize));
#endif
    return *(m.matrix + r * m.rowSize + c);
}


(Or if you want to pass a pointer in instead of passing by value, as suggested in mdfst13's answer, you could change the prototype to take a pointer to a Matrix and dereference the fields via pointer.)

Now when you want to access an element of the array, you would write:

long int x = getElement(result, i, j);


It's not as concise as just result[i][j], but it's better than writing out the math every time and potentially getting it wrong in some subtle way.

Code Snippets

long int getElement(const Matrix m, const int r, const int c)
{
    return *(m.matrix + r * m.rowSize + c);
}
long int getElement(const Matrix m, const int r, const int c)
{
#if DEBUG
    assert((r >= 0) && (r < m.rowSize));
    assert((c >= 0) && (c < m.colSize));
#endif
    return *(m.matrix + r * m.rowSize + c);
}
long int x = getElement(result, i, j);

Context

StackExchange Code Review Q#159301, answer score: 6

Revisions (0)

No revisions yet.