2010-02-13 16 views
8

के लिए रैपर लिखने के लिए कैसे मैं 'आवंटित' फ़ंक्शन के लिए एक रैपर लिखने की कोशिश कर रहा हूं, यानी फ़ंक्शन जो सरणी और आयाम प्राप्त करता है, स्मृति आवंटित करता है और आवंटित सरणी देता है। सबसे महत्वपूर्ण बात यह है कि फ़ंक्शन को विभिन्न रैंक के सरणी के साथ काम करना चाहिए। लेकिन मुझे स्पष्ट रूप से फ़ंक्शन इंटरफ़ेस में सरणी के रैंक को स्पष्ट करना होगा, और इस मामले में कोड केवल संकलित करता है यदि मैं पैरामीटर के रूप में कुछ रैंक के सरणी पास करता हूं। उदाहरण के लिए, इस कोड को संकलित करता है नहीं:'आवंटित'

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 को कॉल किया जाना चाहिए। आपके फ्रीम कार्यों के लिए वही।

यह है कि पाप जैसे आंतरिक कार्यों ने लंबे समय तक काम किया है - आप पाप को विभिन्न प्रथाओं के वास्तविक तर्कों के साथ या जटिल तर्क के साथ पाप कर सकते हैं, और संकलक वास्तविक कॉल फ़ंक्शन के साथ कॉल कर सकते हैं। वास्तव में पुराने फोरट्रान में आपको विभिन्न पाप कार्यों के लिए अलग-अलग नामों का उपयोग करना पड़ा था। अब आधुनिक फोरट्रान आप अपने ही दिनचर्या के साथ एक ही चीज़ स्थापित कर सकते हैं।

संपादित करें: एक कोड उदाहरण विधि & वाक्य रचना का प्रदर्शन जोड़ने:

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-आयामी सरणी (real(8), allocatable, intent(out), dimension(:) :: array) है।

साथ 3-आयामी सरणी foo (real(8), allocatable, dimension(:,:,:) :: foo) त्रुटि जाहिर है अपने मुख्य कार्यक्रम से इस सबरूटीन कॉलिंग। और यह वास्तव में कंपाइलर ने कहा था। 1-आयामी सरणी के लिए एक सबरूटीन्स जोड़ी, 2-आयामी सरणी के लिए एक और, आदि

वैसे, -

तुम सच में इस तरह के सबरूटीन्स नया आयाम से प्रत्येक सरणी के लिए एक जोड़ी memory/freem सबरूटीन्स लिखने की जरूरत है memory सबराउटिन सामान्य रूप से अलग होंगे क्योंकि एन-आयामी सरणी आवंटित करने के लिए आपको ऊपर उल्लिखित सबराउटिन में एन एक्सेंट्स पास करने की आवश्यकता है।

+0

kemiisto, मैं समझता हूँ कि इस संकलन त्रुटि बिल्कुल स्पष्ट है। मैं यह भी समझता हूं कि जो कुछ मैं चाहता हूं उसे लागू करने का एक तरीका अलग-अलग रैंकों के लिए अलग आवंटकों को लिख रहा है। मुझे इसे अंतिम उपाय के रूप में करना होगा :) लेकिन मेरा सवाल था - क्या समान कार्यक्षमता के साथ आवंटित करने के लिए एक रैपर लिखने का एक वैध किलर तरीका है, यानी सार्वभौमिक wrt रैंक ... वैसे भी धन्यवाद! – robusta

संबंधित मुद्दे