카테고리 없음
[C/행렬] 동적 메모리 이용해서 행렬곱 함수 구현하기
미친토끼
2021. 3. 3. 00:16
// 행렬곱 구하는 함수: matrixMul.c
// 동적 메모리를 이용해 행렬곱 함수를 모듈화했다.
// 함수에 x 매트릭스, y 매트릭스, 각 매트릭스의 행과 열 shape를 전달해야 한다.
#include <stdio.h>
#include <stdlib.h>
//2차원 배열(행렬)과 그 shape을 입력받아 출력하는 함수.
void printMatrix(int *array[], int row, int col) {
int i, j;
for (i = 0; i < row; i++) {
for (j = 0; j < col; j++)
printf("%d\t", array[i][j]);
printf("\n");
}
}
// 동적 할당 매트릭스 x와 그 쉐입, 동적 할당 매트릭스 y와 그 쉐입을 인자로 주면
// 행렬곱 함수에서 행렬곱을 계산해서 동적 할당 매트릭스에 저장해 그 포인터를 돌려준다.
// main에서 2차원 정적 배열로 함수에 인자로 전달하면 함수 매개변수에 그것을 표시해야 해서 범용적이지 못하다.
// 그래서 번거롭지만 main에서 x와 y 매트릭스를 동적 할당해서 그 주소를 함수에 전달하고
// 함수에서는 동적 매트릭스 z를 생성하여 행렬곱의 계산 결과를 저장해 그 포인터를 전달한다.
// 이 행렬곱 함수는 필자가 짠 전치행렬 함수에서 일부를 가져왔다.
int ** matrixMul(int *x[], int x_row, int x_col, int *y[], int y_row, int y_col) {
if (x_col != y_row) {
printf("Wrong shapes: x의 컬럼수와 y의 행수는 같아야 합니다.\n");
return 0;
}
int **z = (int **)calloc(x_row, sizeof(int *));
for (int i = 0; i < x_row; i++) {
z[i] = (int *)calloc(y_col, sizeof(int));
}
for (int i = 0; i < x_row; i++) { //z의 행
for (int j = 0; j < y_col ; j++) { //z의 열
for (int k = 0; k < x_col; k++) {
z[i][j] += x[i][k] * y[k][j];
}
}
}
//x의 shape이 (2,3)이고 y의 shape은 (3,2)일 때 z의 shape은 (2,2)가 되므로 수동으로 계산하면 아래와 같다.
// 인덱스의 움직임을 잘 보면, i, j, k중 어떤 값을 따라가야할지 감이 잡힌다.
/* z[0][0] = x[0][0]*y[0][0] + x[0][1]*y[1][0] + x[0][2]*y[2][0];
z[0][1] = x[0][0]*y[0][1] + x[0][1]*y[1][1] + x[0][2]*y[2][1];
z[1][0] = x[1][0]*y[0][0] + x[1][1]*y[1][0] + x[1][2]*y[2][0];
z[1][1] = x[1][0]*y[0][1] + x[1][1]*y[1][1] + x[1][2]*y[2][1];*/
return z;
}
int main() {
// 메모리 동적 할당을 해서 x 매트릭스와 y매트릭스를 만들고 그 정보를 행렬곱 함수에 전달한다.
// 원하는 데이터와 shape을, 아래의 한 블럭 6줄을 추가해서 구할 수 있다.
/*
int arr1[2][3] = {{1, 2, 3}, { 4, 5, 6}};
int arr2[3][2] = {{1,2}, {3, 4}, {5, 6}};
int x_row = 2;
int x_col = 3;
int y_row = 3;
int y_col = 2;
*/
/*int arr1[1][4] = {{1,2,3,4}};
int arr2[4][1] = {{1},{2},{3},{4}};
int x_row = 1;
int x_col = 4;
int y_row = 4;
int y_col = 1;*/
// (4 ,1) * (1, 4) = (4 ,4)행렬임
/*int arr1[4][1] = {{1},{2},{3},{4}};
int arr2[1][4] = {{1,2,3,4}};
int x_row = 4;
int x_col = 1;
int y_row = 1;
int y_col = 4;*/
int arr1[4][2] = {{0, 1}, {2, 3}, {4, 5}, {6, 7}};
int arr2[2][4] = {{0, 1, 2, 3}, {4, 5, 6, 7}};
int x_row = 4;
int x_col = 2;
int y_row = 2;
int y_col = 4;
int **x = NULL;
int **y = NULL;
x = (int **)calloc(x_row, sizeof(int *));
for (int i = 0; i < x_row; i++) {
x[i] = (int *) calloc(x_col, sizeof(int));
for (int j = 0; j < x_col; j++) {
x[i][j] = arr1[i][j];
}
}
printMatrix(x, x_row, x_col);
printf("\n");
y = (int **)calloc(y_row, sizeof(int *));
for (int i = 0; i < y_row; i++) {
y[i] = (int *) calloc(y_col, sizeof(int));
for (int j = 0; j < y_col; j++) {
y[i][j] = arr2[i][j];
}
}
printMatrix(y, y_row, y_col);
printf("\n");
int **z = matrixMul(x, x_row, x_col, y, y_row, y_col);
printMatrix(z, x_row, x_row);
//main에서 할당 받은 x 메모리 해제
for (int i = 0; i < x_row; i++)
free(x[i]);
free(x);
//main에서 할당 받은 y 메모리 해제
for (int i = 0; i < y_row; i++)
free(y[i]);
free(y);
//함수에서 할당 받은 z 메모리 해제
//
for (int i = 0; i < x_row; i++)
free(z[i]);
free(z);
return 0;
}
----- 실행 결과 -----
0 1
2 3
4 5
6 7
0 1 2 3
4 5 6 7
4 5 6 7
12 17 22 27
20 29 38 47
28 41 54 67