// dyn_matrix_test.c - demo of dynamic matrix with pointers

#include <stdio.h>
#include <stdlib.h>

#define INITIAL_NUM_ROWS 5
#define INITIAL_NUM_COLS 8
#define REALLOC_NUM_ROWS 10
#define REALLOC_NUM_COLS 16

//------------------------------------------------------------
int main()
{
  // indexing of the matrix here is interpreted as the first
  // index being the row, the second index being the column.
  // e.g. test_matrix[2][4] means the element of the
  // 4th column of the second row in the matrix. Allocation
  // of rows and columns has to be done accordingly.

  // allocate the rows (they are pointers! the columns hold
  // the values!)
  int **test_matrix = malloc(INITIAL_NUM_ROWS * sizeof(int*));

  int col_count = 0;
  int row_count = INITIAL_NUM_ROWS;
  // allocate the rows one by one
  while(row_count--)
    test_matrix[row_count] = malloc(INITIAL_NUM_COLS * sizeof(int));

  // assign whatever values to the elements of the matrix
  for (row_count = 0; row_count < INITIAL_NUM_ROWS; row_count++)
  {
    for (col_count = 0; col_count < INITIAL_NUM_COLS; col_count++)
      test_matrix[row_count][col_count] = (row_count + 
                                           col_count) * 2 + 10;
  }

  // now let's have a look what the matrix contains
  for (row_count = 0; row_count < INITIAL_NUM_ROWS; row_count++)
  {
    for (col_count = 0; col_count < INITIAL_NUM_COLS; 
         col_count++)
      printf("%d ",test_matrix[row_count][col_count]);
    printf("\n");
  }

  // ***** now let's make the matrix bigger

  // step 1: reallocate test_matrix (=the array holding the cols)
  test_matrix = realloc(test_matrix,REALLOC_NUM_ROWS * sizeof(int*));

  // step 2: reallocate the existing rows of the matrix
  for (row_count = 0; row_count < INITIAL_NUM_ROWS; row_count++)
    test_matrix[row_count] = realloc(test_matrix[row_count],
                                     REALLOC_NUM_COLS * sizeof(int));

  // step 3: allocate the new rows of the matrix
  for (row_count = INITIAL_NUM_ROWS; 
       row_count < REALLOC_NUM_ROWS; row_count++)
    test_matrix[row_count] = malloc(REALLOC_NUM_COLS * sizeof(int));

  // ***** now assign whatever values to the new elements

  // step 1: fill the rest of the previously existing rows
  for (row_count = 0; row_count < INITIAL_NUM_ROWS; row_count++)
  {
    for (col_count = INITIAL_NUM_COLS;
         col_count < REALLOC_NUM_COLS; col_count++)
      test_matrix[row_count][col_count] = (row_count +
                                           col_count) * 2 + 10;
  }

  // step 2: fill the new rows completely
  for (row_count = INITIAL_NUM_ROWS;
       row_count < REALLOC_NUM_ROWS; row_count++)
  {
    for (col_count = 0; col_count < REALLOC_NUM_COLS; col_count++)
      test_matrix[row_count][col_count] = (row_count + 
                                           col_count) * 2 + 10;
  }

  printf("\n***** matrix after reallocation *****\n");

  // now let's have a look what the matrix contains
  for (row_count = 0; row_count < REALLOC_NUM_ROWS; row_count++)
  {
    for (col_count = 0; col_count < REALLOC_NUM_COLS; col_count++)
      printf("%d ",test_matrix[row_count][col_count]);
    printf("\n");
  }
  
  // **** ok, now we don't need the matrix any more, let's free it
  
  // step 1: free the single rows
  row_count = REALLOC_NUM_ROWS;
  while(row_count--)
    free(test_matrix[row_count]);

  // step 2: free the matrix (pointer) itself
  free(test_matrix);
  test_matrix = NULL;

  return(0);
}
