2010-02-13 3 views
8

'allocate'함수에 대한 래퍼를 쓰려고합니다. 즉, 배열과 차원을 받고, 메모리를 할당하고 할당 된 배열을 반환하는 함수를 작성하려고합니다. 가장 중요한 점은 함수가 다른 순위의 배열에서도 작동해야한다는 것입니다. 하지만 함수 인터페이스에서 배열의 순위를 명시 적으로 지정해야합니다.이 경우 코드는 특정 순위의 배열을 매개 변수로 전달하면 컴파일됩니다. 예를 들어,이 코드는 컴파일되지 않습니다 :'allocate'에 대한 래퍼 작성 방법

module memory_allocator 
contains 

    subroutine memory(array, length) 
    implicit none 

    real(8), allocatable, intent(out), dimension(:) :: array 
    integer, intent(in) :: length 

    integer :: ierr 

    print *, "memory: before: ", allocated(array) 

    allocate(array(length), stat=ierr) 
    if (ierr /= 0) then 
     print *, "error allocating memory: ierr=", ierr 
    end if 

    print *, "memory: after: ", allocated(array) 

    end subroutine memory 

    subroutine freem(array) 
    implicit none 

    real(8), allocatable, dimension(:) :: array 

    print *, "freem: before: ", allocated(array) 
    deallocate(array) 
    print *, "freem: after: ", allocated(array) 

    end subroutine freem 

end module memory_allocator 

program alloc 
    use memory_allocator 
    implicit none 

    integer, parameter :: n = 3 
    real(8), allocatable, dimension(:,:,:) :: foo 
    integer :: i, j, k 

    print *, "main: before memory: ", allocated(foo) 
    call memory(foo, n*n*n) 
    print *, "main: after memory: ", allocated(foo) 

    do i = 1,n 
    do j = 1,n 
     do k = 1, n 
     foo(i, j, k) = real(i*j*k) 
     end do 
    end do 
    end do 

    print *, foo 

    print *, "main: before freem: ", allocated(foo) 
    call freem(foo) 
    print *, "main: after freem: ", allocated(foo) 

end program alloc 

컴파일 오류 :

gfortran -o alloc alloc.f90 -std=f2003 
alloc.f90:46.14: 

    call memory(foo, n*n*n) 
       1 
Error: Rank mismatch in argument 'array' at (1) (1 and 3) 
alloc.f90:60.13: 

    call freem(foo) 
      1 
Error: Rank mismatch in argument 'array' at (1) (1 and 3) 

같은 래퍼 ..

감사를 구현하는 방법은 없나요!

답변

10

일반 인터페이스 블록을 통해 수행 할 수 있습니다. 처리하려는 각 순위에 대한 절차를 만들어야합니다 (예 : memory_1d, memory_2d, ... memory_4d). (분명히 많이 붙여 넣기가 많이 있습니다.) 그런 다음이 모든 절차에 대체 이름 메모리를 일반 프로 시저 이름으로 제공하는 일반 인터페이스 블록을 작성합니다. 메모리를 호출하면 컴파일러는 인수의 순위에 따라 호출해야하는 memory_Xd를 구별합니다. 귀하의 freem 기능에 대해 동일합니다.

이것은 죄와 같은 본질적인 기능이 오랫동안 효과가 있었던 방식입니다. 다양한 법규의 실제 인수 또는 복잡한 인수를 사용하여 죄를 호출 할 수 있으며, 컴파일러는 실제 죄 함수를 호출하여 호출 할 수 있습니다. 정말 오래된 FORTRAN에서는 다른 죄 기능에 대해 다른 이름을 사용해야했습니다. 이제는 현대 Fortran에서 자신의 루틴으로 같은 것을 설정할 수 있습니다.

편집 : 방법 & 구문을 보여주는 코드 예제 추가 :

module double_array_mod 

    implicit none 

    interface double_array 
     module procedure double_vector 
     module procedure double_array_2D 
    end interface double_array 

    private ! hides items not listed on public statement 
    public :: double_array 

contains 

    subroutine double_vector (vector) 
     integer, dimension (:), intent (inout) :: vector 
     vector = 2 * vector 
    end subroutine double_vector 

    subroutine double_array_2D (array) 
     integer, dimension (:,:), intent (inout) :: array 
     array = 2 * array 
    end subroutine double_array_2D 

end module double_array_mod 


program demo_user_generic 

    use double_array_mod 

    implicit none 

    integer, dimension (2) :: A = [1, 2] 
    integer, dimension (2,2) :: B = reshape ([11, 12, 13, 14], [2,2]) 
    integer :: i 

    write (*, '(/ "vector before:",/2(2X, I3))') A 
    call double_array (A) 
    write (*, '(/ "vector after:",/2(2X, I3))') A 

    write (*, '(/ "2D array before:")') 
    do i=1, 2 
     write (*, '(2(2X, I3))') B (i, :) 
    end do 
    call double_array (B) 
    write (*, '(/ "2D array after:")') 
    do i=1, 2 
     write (*, '(2(2X, I3))') B (i, :) 
    end do 

    stop 
end program demo_user_generic 
+0

고마워요! 할당 자 모듈에서 코드 중복이 필요하지만 최소한이 할당 자 함수를 호출 할 때는 공통 이름을 사용할 수 있습니다. 이것이 내가 원했던 것이다. – robusta

1

subroutine memory(array, length)은 그대로 제 1 더미 파라미터 1 차원 배열 (real(8), allocatable, intent(out), dimension(:) :: array)을 갖는다.

3 차원 배열 foo는 (real(8), allocatable, dimension(:,:,:) :: foo) 오류가 분명히으로 메인 프로그램이 서브 루틴을 호출. 그리고 이것은 컴파일러가 실제로 말한 것입니다. , 그런데 등

, 1 차원 배열에 대해 하나의 서브 루틴 쌍, 2 차원 배열에 대한 또 다른 -

당신은 정말 같은 서브 루틴은 다른 차원의 각 배열에 대해 한 쌍의 memory/freem 서브 루틴을 작성해야하는 경우 memory 서브 루틴은 일반적으로 n 차원 배열을 할당하기 위해 위에 언급 된 서브 루틴에 n 개의 범위를 전달해야하기 때문에 서로 다릅니다.

+0

kemiisto을, 나는이 컴파일 오류가 절대적으로 확실한 것을 이해합니다. 또한 내가 원하는 것을 구현하는 한 가지 방법은 다른 순위에 대해 별도의 할당자를 작성하는 것임을 이해합니다. 최후의 수단으로이 작업을 수행해야합니다. :)하지만 제 질문은 - 동일한 기능, 즉 유니버설 wrt 순위를 할당하는 래퍼를 작성하는 합법적 인 포트란 방법이 있습니까? 감사합니다. – robusta

관련 문제