C does not technically support multidimensional arrays. However, we can define an array or arrays, which accomplished the same thing.

#define MAX_ROWS 100 #define MAX_COLS 100 double coefficients[MAX_ROWS][MAX_COLS];

Statically sized 1-dimensional arrays are wasteful enough, but the waste increases by an order of magnitude with each dimension we add, so this is generally a bad practice unless the maximum matrix size is small.

The key to conserving memory with matrices is hidden in plain view in the argv[] array received by main();

int main(int argc, char *argv[])

The argv[] array is essentially a 2-dimensional array of characters. We can use the same concept for any 2-dimensional array.

TBD: Graphic of a pointer array

To implement a pointer array, we first allocate a 1-dimensional array of pointers to the data type contained in the matrix.

Each of these pointers will point to a 1-dimensional array of values representing a row in the matrix.

/*************************************************************************** * Description: * Read a matrix into a pointer array and print it out to verify. * * History: * Date Name Modification * 2017-08-25 Jason Bacon Begin ***************************************************************************/ #include <stdio.h> #include <sysexits.h> #include <stdlib.h> typedef double real_t; int main(int argc,char *argv[]) { size_t rows, cols, r, c; real_t **matrix; printf("Rows? "); scanf("%zu", &rows); printf("Cols? "); scanf("%zu", &cols); /* Allocate pointer array */ matrix = (real_t **)malloc(rows * sizeof(real_t *)); /* * Read matrix data separated by whitespace. Well-formatted input * will have a newline after each row. */ for (r = 0; r < rows; ++r) { matrix[r] = (real_t *)malloc(cols * sizeof(real_t)); for (c = 0; c < cols; ++c) scanf("%lf", &matrix[r][c]); } /* Print matrix one row per line. */ for (r = 0; r < rows; ++r) { for (c = 0; c < cols; ++c) printf("%5.2f", matrix[r][c]); putchar('\n'); } /* Free the arrays */ for (r = 0; r < rows; ++r) free(matrix[r]); free(matrix); return EX_OK; }

2 3 2.0 4.3 1.0 9.7 4.7 8.2

In Fortran, we store matrix data in a multidimensional array. Defining multidimensional arrays is done much like one-dimensional arrays. We add more dimensions separated by commas:

double precision :: coefficients(1:MAX_ROWS, 1:MAX_COLS)

Note that as the number of dimensions increases, so does the potential for memory waste if the array size is larger than needed. If we use 50 elements in an array of 100, half the array is wasted. If we store a 50x50 matrix in a 100x100 array, 3/4 of the memory (7,500 elements) is wasted. If we store a 50x50x50 brick in a 100x100x100 array, 7/8 of the memory (875,000 elements) is wasted. Therefore, using dynamic memory allocation becomes increasingly important as the number if dimensions grows.

double precision, allocatable :: coefficients(:, :) integer :: rows, cols read *, rows, cols allocate(matrix(1:rows, 1:cols), stat=allocate_status) if ( allocate_status /= 0 ) then print *, 'Error: Unable to allocate ', rows, ' x ', cols, & ' matrix.' stop endif

Working with multidimensional arrays will always involve
a *nested loop*, i.e. a loop inside a loop.
In Fortran, the outer loop should traverse the columns, and
the inner loop should traverse the rows. The reason for this
is explained in the section called “Importance of Traversal Order”.