10. 배열(Arrays)

과학 분야의 계산에서는 vector나 matrix를 사용한다. Fortran에서 이러한 경우 사용할 수 있는 자료 형태가 배열((EM>array)이다. 일차원 배열로 vector를, 이차원 배열로 matrix를 나타낸다. To fully understand how this works in Fortran 77에서 이것이 어떻게 작동하는가를 완전히 이해하기 위하여는 사용 synatx 뿐만 아니라 Fortran 77에서 이것을 memory에 어떻게 저장하는가도 알아야 한다.

일차원 배열 (One-dimensional arrays)

가장 간단한 배열은 일차원 배열로 해당 원소를 memory에 일차원 순서에 따라 연속적으로 저장되어 있는 것이다. 예를 들어
      real a(20)
는 길이가 20인 실수 배열a를 선언한다. 즉 a는 memory에 연속적으로 저정되어 있는 20 개의 실수를 의미한다. 규정에 의하여 Fortran 배열은 1부터 번호 매겨진다. 따라서 배열의 첫번째 숫자는 a(1)이고 마지막은 a(20)이다. 그러나 다음과 같이 하면 순서의 범위를 마음대로 정의할 수 있다.
      real b(0:19), weird(-162:237)
여기서 b는 순서가 0부터 19까지인 것을 제외하고는 앞의 예의 a와 똑 같다. weird는 길이가 237-(-162)+1 = 400인 배열이다.

배열의 원소의 형태는 다른 기본적인 data의 형식 중의 하나이다. 예:

      integer i(10)
      logical aa(0:1)
      double precision x(100)

한 배열의 다른 원소는 각각 독립적인 변수로 생각할 수 있다. 배열 a의 i번째 원소는 a(i)로 나타낸다. 다음은 배열 sq에 10 개의 숫자의 제곱을 저장하는 프로그램이다.

      integer i, sq(10)

      do 100 i = 1, 10
         sq(i) = i**2
  100 continue

Fortran에서 흔히 범하는 잘못은 범위 밖이거나 정의하지 않은 배열의 원소를 가리키는 일이다. 이는 프로그래머가 알아서 할 일이며 Fortran compiler 는 이런 잘못을 알 수 없다!

이차원 배열(Two-dimensional arrays)

matrix는 선형 대수(linear algebra)에서 매우 중요하다. 보통 이차원 배열로 matrix를 나타낸다. 예를 들어
      real A(3,5)
은 3*5=15 개의 실수를 가리키는 이차원 배열을 정의한다. 처음 숫자는 열(row)를 가리키는 숫자로 두번째는 행(column)을 가리키는 숫자로 생각한다. 이를 그림으로 나타내면 다음과 같다.
   (1,1)  (1,2)  (1,3)  (1,4)  (1,5)
   (2,1)  (2,2)  (2,3)  (2,4)  (2,5)
   (3,1)  (3,2)  (3,3)  (3,4)  (3,5)
이차원 배열도 그 범위를 임의로 정의할 수 있다. 일반적 syntax는 다음과 같다.
     name (low_index1 : hi_index1, low_index2 : hi_index2)
배열의 전체 크기는 다음과 같다.
     size = (hi_index1-low_index1+1)*(hi_index2-low_index2+1)

Fortran에서는 저장하고자하는 matrix보다 큰 배열을 선언하는 것이 보통이다. (이는 Fortran에서는 dynamic storage allocation을 하지 않기 때문이다.) 다음은 잘못되지 않은 것이다. 예:

      real A(3,5)
      integer i,j
c
c     We will only use the upper 3 by 3 part of this array.
c
      do 20 j = 1, 3
         do 10 i = 1, 3
            a(i,j) = real(i)/real(j)
   10    continue
   20 continue
부배열 A(1:3,4:5)의 원소 값은 정의되지 않았다. compiler가 이 원소의 초기값을 0으로 설정할 것이라고 가정하지 말라. (어떤 compiler에서는 0으로 설정하지만 하지만 모든 compiler가 그렇지 않다.).

이차원 배열의 저장 형식(Storage format for 2-dimensional arrays)

Fortran에서는 일차원 이상의 배열도 그 원소를 끊임없이 연속적인(contiguous) 일차원으로 저장한다. 이차원 배열은 행 column에 따라 배열된다는 것을 알면 좋다. 앞의 예에서 배열의 원소 (1,2)가 원소 (3,1) 다음에 저장된다. 그리고 둘째 행의 나머지 그 뒤에 섯째 행이 저장된다.

3 by 5의 배열 A(3,5)의 위쪽 3 by 3 부배열만 사용하는 예를 다시 살펴보면 관심이 있는 9 개의 elements는 처음 9 개의 memory에 저장되고 나머지 6개는 사용하지 않는다. leading dimension은 배열에서나 배열에 저장한 matrix에서나 똑 같다. 그러나 종종 배열의 leading dimension이 matrix의 첫번째 차원보자 클 수 있다. 그 경우에는 배열은 연속적이라 하더라도 matrix는 memory에 연속적으로 저장되지 않는다. 예를 들어 A(5,3)이라고 선언하였다면 한 행의 끝과 다음 행의 시작 사이에 "사용하지 않는" memory가 두 개 있게 된다. (matrix는 3 by 3이라고 가정).

이런 사실은 복잡한 것 같지만 익숙하여지면 대단히 단순하다. 의심스러우면 배열 원소의 주소address를 살펴보면 좋다. 각각의 배열은 배열의 첫번째 즉 원소 (1,1)가 어떤 memory 주소에 배정되어 있다. element (i,j)의 주소는 then given by

      addr[A(i,j)] = addr[A(1,1)] + (j-1)*lda + (i-1)
여기서 lda는 A의 leading (i.e. column) dimension이다. 보통 lda은 실제 matrix 차원과는 다르다는 점에 주의한다. 이런 류의 Fortran의 오류가 대단히 많으며 따라서 이 차이를 이해하여야 한다!

다차원 배열(Multi-dimensional arrays)

Fortran 77에서는 배열의 차원을 7차원까지 할 수 있다. syntax와 저장 형식은 이차원의 경우와 유사하다.

dimension 문(The dimension statement)

Fortran 77에서 배열을 선언하는 다른 방법이 있다.
      real A, x
      dimension x(50)
      dimension A(10,20)
은
      real A(10,20), x(50)
과 같다. 오늘날에는 이 dimension 문은 구식이다.


Exercises

Exercise A
다음의 main 프로그램을 작성하라. matrix A를 다음과 같이 선언하라.
       integer nmax
       parameter (nmax=40)
       real A(nmax, nmax)
알맞는 vector x와 y를 정의하고 1<=i<=m , 1<=j<=n의 범위에서 (단 m=10, n=20) A(i,j) = i+j-2로 초기화하라. 또 1<=j<=n에서 x(j) = 1로 초기화하라. 본문에 주어진 matvec subroutine을 사용하여 y=A*x를 계산하라. 결과 y를 인쇄하라.

Exercise B
scalar product y = A*x를 행하는 subroutine을 써라. 단 가장 안쪽 loop의 index는 j로 하라. Exercise A의 예를 사용하여 code를 검사하고 그 결과를 비교하라.


[Fortran Tutorial]
충남대학교 물리학과 오 병성