mod0
mod0

Reputation: 155

Representing Cell Arrays (from MATLAB) in C

Question: How do I design a better interface between Cell arrays and independent Matrix objects?

I am converting a MATLAB code that uses cell arrays and cell arrays of cell arrays to C. I created a Matrix datatype and a Cell data-type. They are illustrated below.

The Matrix datatype

typedef struct{
  double * array; // row major format
  int rows;
  int cols;
} Matrix;

and the Cell datatype

typedef struct{
  Matrix * array; // row major format
  int rows;
  int cols;
} Cell;

Fortunately, the cell array of cell arrays in the code is a simple one dimensional array of cells which I can represent as an array of cell objects.

In the original code, independent matrix objects and elements of a cell array (another matrix) appear together in expressions. For example:

a = rand(10);
% say, b is a cell array containing other matrices
% c = some expression involving an element of the cell array b and a
c = a + b{1,2};
% assuming dimensions agree

Now, in my representation, when I create a cell object, I have allocated rows * cols of Matrix objects and assigned the pointer to the array of Matrix objects to array (inside cell). Assume the Matrix objects are appropriately initialized later in the code (before using them)

The independent matrix objects that I allocate dynamically are accessed by de-referencing pointers pointing to them and the accessor routines for cell arrays return Matrix objects instead of a pointer to a Matrix object.

// Function signature for accessor routine of cell object 
Matrix get_mat_from_cell(Cell * cell, int row, int col);

// Independent Matrix object - dynamically allocated as size is known
// at run-time
Matrix * matrixA = (Matrix *) malloc(sizeof(Matrix));

Matrix matrixB = get_mat_from_cell(someCell, 1, 2);

add(matrixA, &matrixB, matrixC); // adds matrixA, matrixB and stores in a matrixC

The thing that tickles me is in the add function (for instance), to get a uniform interface that accepts pointers to matrices for all 3 arguments, I have to pass the address of matrixB. It either looks uniform at the function interface level - like add(Matrix *, Matrix *, Matrix *) or uniform at function call level - add(Matrix *, Matrix, Matrix *) and not both ways.

I could achieve uniformity by declaring the array inside the Cell object as a double pointer but I have to de-reference twice before I can get to a Matrix object and wonder if it will be a performance bottleneck as these cells are really large and are frequently accessed.

How can I design this interface better?

Thank you.

Upvotes: 1

Views: 2764

Answers (1)

macduff
macduff

Reputation: 4685

Looks like you already have this figured out, but I'll try to lend a hand anyway. First, I think your Cell structure needs a tweak, unless you know the implementation you have is very specific

/* small set of types as example */
typedef union matlab_fundamental_types_u
{
  CELL,
  MATRIX
} matlab_fundamental_types_t;

typedef struct Cell_s
{
  struct Cell_s * array; // row major format
  matlab_fundamental_types_t fundamental_type; /* what this cell holds, is it a cell of cells, arrays, etc? */
  int rows;
  int cols;
} Cell;

Since a Cell is a super container and can hold anything, including a Cell, it makes sense to implement it this way, although I think it could still use some polish. Also, you mentioned a concern about double pointer dereferencing being a bottleneck. I don't think I'd worry about that. My experience has been that malloc, free, file operations are the real bottleneck, but the only way to know for sure is a profiler. Hope this helps!

Upvotes: 2

Related Questions