// # CS1 u7_matrices_c99.c
// Jonas Altrock <ew20b126@technikum-wien.at>
//
// [To overview](../).
//
// Implementation with `malloc`-allocated arrays:
// [u7_matrices.c](./u7_matrices.html).
//
// [The whole source file `u7_matrices_99.c`.](./u7_matrices_c99.c)
/* Compile with `clang -std=c99 -Wall -o u7_matrices_c99 u7_matrices_c99.c` */

// Include C-libraries for input/output.
#include <stdio.h>
#include <stdlib.h>

// Exercise 7: Arrays
// ==================
//
// For the whole explanation of the exercise task, see [u7_matrices.c](./u7_matrices.html).
//
// Here I am only going to highlight the differences to the `malloc`-based
// implementation.

// ## Forward declarations
// The dimensions of array parameters can reference earlier `int` parameters,
// allowing us to specify that the matrix parameters are `size` by `size`.
// We could also pass width and height separately (or rows and cols).
void read_matrix(int size, int matrix[size][size]);
void print_matrix(int size, int matrix[size][size]);
void matrix_multiply(int size, int m1[size][size], int m2[size][size], int m3[size][size]);

// ## main()
int main() {
    // We use 'dynamically sized arrays' as the type for the matrix variables.
    // This means we have to read in the `size` first, and then declare them.
    int size;
    scanf("%d", &size);

    int matrix1[size][size], matrix2[size][size], matrix3[size][size];

    // Read in both matrices, multiply into the third variable, and print.
    // This looks *exactly the same* as in the malloc-version.
    read_matrix(size, matrix1);
    read_matrix(size, matrix2);
    matrix_multiply(size, matrix1, matrix2, matrix3);
    print_matrix(size, matrix3);

    // **No need for `free` here!**

    // Return code 0 to indicate everything went OK.
    return 0;
}

// ## read_matrix()
// Because we store the matrix in a proper C99 array, we can use the `row`
// and `col` loop variables directly as array indices.
void read_matrix(int size, int matrix[size][size]) {
    int row, col;

    for (row = 0; row < size; row++) {
        for (col = 0; col < size; col++) {
            scanf("%i", &matrix[row][col]);
        }
    }
}

// ## print_matrix()
void print_matrix(int size, int matrix[size][size]) {
    int row, col;

    for (row = 0; row < size; row++) {
        for (col = 0; col < size; col++) {
            printf("% 3i", matrix[row][col]);
        }
        printf("\n");
    }
}

// ## matrix_multiply
void matrix_multiply(int size, int m1[size][size], int m2[size][size], int m3[size][size]) {
    int row, col, i;

    // Here we can see the best readability improvement of the C99 dynamic
    // array syntax:
    for (row = 0; row < size; row++) {
        for (col = 0; col < size; col++) {
            // the scalar product of the row of m1 and column of m2 becomes
            // more obvious by `[row][i]` and `[i][col]` than the multiply
            // and add combo used in the linear storage.
            int sum = 0;

            for (i = 0; i < size; i++) {
                sum += m1[row][i] * m2[i][col];
            }

            m3[row][col] = sum;
        }
    }
}