# Recitation 2 ## Topics Today * Writing Matrices in C * Manipulating Matrices in C ## Writing Matrices in C ### Matrix Declaration #### Initialize a matrix a two-dimensional array statically ```c= int matrix1[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; ``` Or you can just use one array to store the whole matrix in a row major style: ```c= #define N 3 #define M 3 #define AT(i,j) (i*N+j) double *matrix = (double*)malloc(N*M*sizeof(double)); int cnt = 0; for(int i = 0; i < N; ++i){ for(int j = 0; j < M; ++j){ matrix[AT(i,j)]=cnt++; } } ``` #### Initialize a matrix using double pointer(wicked way) * Declare a pointer to a pointer (double pointer) for the matrix ```c= int **matrix; ``` * Allocate memory for the matrix dynamically ```c= matrix = (int **)malloc(N * sizeof(int *)); ``` * Check it ```c= if (matrix == NULL) { fprintf(stderr, "Memory allocation failed.\n"); } for (int i = 0; i < N; i++) { matrix[i] = (int *)malloc(M * sizeof(int)); if (matrix[i] == NULL) { fprintf(stderr, "Memory allocation failed.\n"); } } ``` * Populate the matrix with values ```c= int value = 1; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { matrix[i][j] = value; value++; } } ``` * After all the calculation, free dynamically allocated memory ```c= for (int i = 0; i < rows; i++) { free(matrix[i]); } free(matrix); ``` ## Manipulating Matrices in C To incoporate all the information needed for a matrix, we can create a struct Matrix: ```c= typedef struct Matrix{ int rows; int cols; double ** data; } Mat; ``` Define a function to initialize a Matrix to 0 given rows and cols: ```c= Mat * initializeMatrix(int rows, int cols){ Mat * res = (Mat*) malloc(sizeof(Mat)); res->rows = rows; res->cols = cols; res->data = (double**)malloc(sizeof(double*)*res->rows); for(int i = 0; i < res->rows; ++i){ res->data[i] = (double*)malloc(sizeof(double)*res->cols); for(int j = 0; j < res->cols; ++j){ res->data[i][j] = 0.0; } } return res; } ``` Now we can write the add function: ```c= Mat * add(Mat*mat1, Mat*mat2){ // we need to check if the size of the two matrices are the same if(mat1->rows != mat2->rows || mat1->cols != mat2->cols){ printf("The size of two matrices are not the same"); exit(1); } Mat * res = initializeMatrix(mat1->rows, mat2->cols); for(int i = 0; i < res->rows; ++i){ for(int j = 0; j < res->cols; ++j){ res->data[i][j] = mat1->data[i][j] + mat2->data[i][j]; } } return res; } ``` We can also define the multiplication between a matrix and a scalar: ```c= Mat* multiplyScalar(Mat* mat1, double coef){ Mat * res = initializeMatrix(mat1->rows, mat1->cols); for(int i = 0; i < res->rows; ++i){ for(int j = 0; j < res->cols; ++j){ res->data[i][j] = mat1->data[i][j] * coef; } } return res; } ``` Now we have subtract function. We can either do element-wise subtraction or combine `add` function and `multiplyScalar` function: ```c= Mat* subtract(Mat*mat1, Mat*mat2){ // we need to check if the size of the two matrices are the same if(mat1->rows != mat2->rows || mat1->cols != mat2->cols){ printf("The size of two matrices are not the same"); exit(1); } return add(mat1, multiplyScalar(mat2, -1.0)); } ``` Finally we can define matrix multiplication: ```c= Mat* multiply(Mat* mat1, Mat* mat2){ if(mat1->cols != mat2->rows){ printf("A matrix of size (%d, %d) cannot be multiplied with a matrix with size (%d, %d)", mat1->rows, mat1->cols, mat2->rows, mat2->cols); } Mat * res = initializeMatrix(mat1->rows, mat2->cols); for(int i = 0; i < res->rows; ++i){ for(int j = 0; j < res->cols; ++j){ for(int k = 0; k < mat1->cols; ++k){ res->data[i][j] += mat1->data[i][k] * mat2->data[k][j]; } } } return res; } ```