행렬의 column-major 및 1차원 처리 (cont.)

Download Report

Transcript 행렬의 column-major 및 1차원 처리 (cont.)

컴퓨터 개론 및 실습
강의 9
Seoul National University
www.msharpmath.com
1
/8
행렬의 column-major 및 1차원 처리
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
C 언어에서 행렬 int A[2][4] = { 1,2,3,4,5,6,7,8 }은 row-major 로 세팅되어
있으므로 i행 j열 원소는 A[i][ j]로 처리된다.
A = [1234]
[5678]
A[0] = [ 1 2 3 4 ]
A[1] = [ 5 6 7 8 ]
Seoul National University
www.msharpmath.com
2
/8
행렬의 column-major 및 1차원 처리
■ 1차원 배열과 행렬
아래에 주어진 1차원 배열 A, B 를 4 x 2 행렬에 column-major 로 초기화시키는 방법으로
대응시키고 싶다. 그러나, C 언어에서 행렬은 row-major 로 처리되므로 사용자가 이러한
직접 처리를 고안해야 한다. 따라서 m x n 행렬에 대한 일반적인 포인터를 고안해보자.
2차원 배열 포인터를 이용하면 i 행 j 열 원소를 사용자가 고안한 함수를 이용하여
*prow [ i ] [ j ] (행-우선) 및 *pcol [ j ] [ i ] (열-우선) 두 가지 방법 모두 가능하게 처리할 수 있다.
double A[] = { 1,2,3,4, 5,6,7,8 };
A=[
[
[
[
1
2
3
4
5
6
7
8
]
]
]
]
double B[] = {2,3,4,5, 6,7,8,1 };
B=[
[
[
[
2
3
4
5
6
7
8
1
]
]
]
]
Seoul National University
www.msharpmath.com
3
/8
행렬의 column-major 및 1차원 처리 (cont.)
void mulAtrB(double*C, int m1,int n1, double*A, int m2,int n2, double*B)
{
// m1 x n1 matrix A
double A[] = { 1,2,3,4, 5,6,7,8 };
// m2 x n2 matrix B
double B[] = { 2,3,4,5, 6,7,8,1 };
// C = A' * B, n1 x n2 matrix
double C[100];
int i,j,k; double *a,*b;
mulAtrB(C, 4,2,A, 4,2,B);
if( m1 != m2 ) { printf(“mulAtrB : inner dimension mismatch\n"); exit(1); }
b = B;
for(j = 0; j < n2; j++) {
a = A;
for(i = 0; i < n1; i++) {
*C = 0;
for(k = 0; k < m1; k++) *C += a[k] * b[k] ;
a += m1;
++C;
}
}
b += m1;
b
a
[ 1 2 3 4 ] [
[ 5 6 7 8 ] [
[
[
2
3
4
5
6
7
8
1
]
]
]
]
[ 40 48 ]
[ 96 136 ]
}
Seoul National University
www.msharpmath.com
4
/8
행렬의 column-major 및 1차원 처리 (cont.)
double ***rowmtrx(int m,int n) {
int i,j,k; double ***A, *pnull = NULL;
double M[] = { 1,2,3,4, 5,6,7,8 };
// pointers to rows
A = (double ***) malloc((size_t) (m*sizeof(double **)));
if(A == NULL) { printf("allocation failure in matrix"); exit(1); }
A[0] = (double **) malloc((size_t)(m*n*sizeof(double*)));
for(i = 1; i < m; i++) A[i] = A[i-1]+n;
row-major
m=4
for(i = 0; i < m; i++)
n=2
for(j = 0; j < n; j++) A[i][j] = pnull+i + m*j; // i,j
return A; // pointer to array of pointers to rows
prow[0]
prow[1]
prow[2]
prow[3]
[
[
[
[
1
2
3
4
5
6
7
8
]
]
]
]
}
위에서 A[0] = (double **) malloc( (size_t) (m * n * sizeof(double*)) ); 인 명령에서 double 형
데이터에 대한 m*n 개의 포인터를 정의하였다. 따라서, m*n 개의 원소에 대한 1차원 처리 가능
하다. 한편, A[0] 다음의 포인터 A[1]은 n 개의 double 형 데이터를 가리킨다.
Seoul National University
www.msharpmath.com
5
/8
행렬의 column-major 및 1차원 처리 (cont.)
double ***colmtrx(int m,int n) {
int i,j,k; double ***A, *pnull = NULL;
double M[] = { 1,2,3,4, 5,6,7,8 };
// pointers to rows
A = (double ***) malloc((size_t) (m*sizeof(double **)));
if(A == NULL) { printf("allocation failure in matrix"); exit(1); }
A[0] = (double **) malloc((size_t)(m*n*sizeof(double*)));
for(j = 1; j < n; j++) A[j] = A[j-1]+m;
for(i = 0; i < m; i++)
for(j = 0; j < n; j++) A[j][i] = pnull+i + m*j; // j,i
return A; // pointer to array of pointers to rows
}
pcol[0]
row-major
m=4
n=2
prow[0]
prow[1]
prow[2]
prow[3]
Seoul National University
[
[
[
[
1
2
3
4
5
6
7
8
]
]
]
]
www.msharpmath.com
[
[
[
[
1
2
3
4
pcol[1]
5
6
7
8
]
]
]
]
column-major
m=2
n=4
6
/8
행렬의 column-major 및 1차원 처리 (cont.)
int i,j, m,n;
double A[] = { 1,2,3,4, 5,6,7,8 };
double ***pcol,***prow;
double A[100] = { 1,2,3,4, 5,6,7,8 };
A =[
[
[
[
m = 4; n = 2;
prow = rowmtrx(m,n); // row-major
pcol = colmtrx(m,n); // column-major
1
2
3
4
5
6
7
8
]
]
]
]
for(i=0;i<m;i++) for(j=0;j<n;j++) printf(" %g", *( (A-NULL)+prow[i][j]) ); printf("\n"); // A[i][j]
for(j=0;j<n;j++) for(i=0;i<m;i++) printf(" %g", *( (A-NULL)+pcol[j][i]) ); printf("\n"); // A[j][i]
위와 같이 행우선, 열우선 포인터를 각각 정의할 수 있다. 결과는
15263748
12345678
pcol[0]
row-major
m=4
n=2
prow[0]
prow[1]
prow[2]
prow[3]
Seoul National University
[
[
[
[
1
2
3
4
5
6
7
8
]
]
]
]
www.msharpmath.com
[
[
[
[
1
2
3
4
pcol[1]
5
6
7
8
]
]
]
]
column-major
m=2
n=4
7
/8
행렬의 column-major 및 1차원 처리 (cont.)
void mulAB(double *C, double *A, double *B, double ***prow, double ***pcol, int n)
{
// C = A * B, n x n matrix
int i,j,k; double **a,**b;
double X[] = { 1,2,3,4 };
b = pcol[0];
double Y[] = { 5,6,7,8 };
for(j = 0; j < n; j++) {
double C[100];
a = prow[0];
for(i = 0; i < n; i++) {
*C = 0;
for(k = 0; k < n; k++) *C += *(a[k]+(A-NULL)) * *(b[k]+(B-NULL));
++C;
a += n;
}
b += n;
[ 1 3 ] [ 5 7 ]
[ 23 31 ]
=
}
[ 2 4 ] [ 6 8 ]
[ 34 46 ]
}
a[k] + A 는 에러인 이유는 두 개의 포인터를 더할 수 없기 때문이다.
포인터 NULL 의 주소값은 0 이므로 (A-NULL)은 두 개의 포인터의 차이로 정수값이 되므로 포
인터에 더할 수 있게 된다.
Seoul National University
www.msharpmath.com
8
/8