# 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;
}
```