2012-07-02 48 views
1

我正在試圖找到一種方法,將具有可分配組件的派生類型對象傳遞給Fortran過程,而無需知道類型定義的過程。爲了理解我爲什麼要這樣做,背景上的一些信息可能會有用。使用可分配組件鑄造派生類型數據

考慮一個通用程序,它包含一個稀疏矩陣 - 向量乘法,就像一個Lanczos對角化程序。程序本身不使用矩陣,只使用矢量。程序需要處理矩陣的唯一方法是將其與矢量一起傳遞給矩陣 - 矢量乘法程序。稀疏矩陣必須是具有可分配組件的派生類型變量。

我看到它的方式,程序並不需要知道稀疏矩陣的數據類型。它只需要將它傳遞給矩陣向量乘法例程,然後它將對其進行適當的解碼。我試圖做的是使用TRANSFER內部函數將派生類型變量轉換爲可分配的字節數組,然後將其傳遞迴初始派生類型變量。這種遺憾的是不帶可分配組件的派生類型變量的工作方式,請參閱以下兩個環節:Link 1,因此 Link 2

我的問題是下面的,上面說:有沒有一個合理的方式*通過派生類型具有可分配組件的對象到Fortran過程,而程序不知道類型定義? *注意:我知道我可以使用自定義的內部格式化寫入來將派生類型的變量存儲到內部類型的數組中,例如,一個字符數組。這在我看來非常奇怪,但也許我錯了?

編輯::作爲弗拉基米爾F下面說,調用TRANSFER具有可分配組件的派生類型時的行爲是非標準的。然而,我意外地發現,這與最新版本的PGI編譯器一起工作。這是一個測試程序:

module Increments 

    TYPE :: structure 
    real s 
    integer q 
    real, allocatable :: flt1d(:) 
    END TYPE structure 

contains 

    subroutine IncrementAndPrintReal(data) 
    character(len=1) :: data(:) 
    real    :: r 
    r = transfer(data, r) 
    r = r + 1.0 
    print *,r 
    data = transfer(r, data) 
    end subroutine 

    subroutine IncrementAndPrintInteger(data) 
    character(len=1) :: data(:) 
    integer   :: i  
    i = transfer(data, i) 
    i = i + 1 
    print *,i 
    data = transfer(i, data) 
    end subroutine 

    subroutine IncrementTenTimes(incrFunc, data) 
    character(len=1) :: data(:) 
    integer :: i 
    interface 
     subroutine incrFunc(data) 
     character(len=1) :: data(:) 
     end subroutine 
    end interface 
    do i = 1, 10 
     call incrFunc(data) 
    enddo 
    end subroutine 

    subroutine IncrementAndPrintStructure(data) 
    character(len=1) :: data(:) 
    type(structure) :: t0 
    t0 = transfer(data, t0) 
    print *, t0%flt1d 
    t0%flt1d = t0%flt1d(1) + 1 
    print* 
    data = transfer(t0, data) 
    end subroutine 

end module 

program main 
    use Increments 
    character(len=1), allocatable :: data(:) 
    integer      :: lengthData 
    real       :: r = 5.0 
    integer      :: i = 10 
    type(structure)    :: t 

    t%s = 1 
    t%q = 2 
    allocate(t%flt1d(11)) 
    t%flt1d = 3 

    lengthData = size(transfer(r, data)) 
    allocate(data(lengthData)) 
    data = transfer(r, data) 
    call IncrementTenTimes(IncrementAndPrintReal, data) 
    deallocate(data) 

    lengthData = size(transfer(i, data)) 
    allocate(data(lengthData)) 
    data = transfer(i, data) 
    call IncrementTenTimes(IncrementAndPrintInteger, data) 
    deallocate(data) 

    lengthData = size(transfer(t, data)) 
    allocate(data(lengthData)) 
    data = transfer(t, data) 
    call IncrementTenTimes(IncrementAndPrintStructure, data) 
    deallocate(data) 

end program 

而且這裏有不同的編譯器的結果:

ifort (v11.1 and v12.1.5): 
============== 


    6.000000  
    7.000000  
    8.000000  
    9.000000  
    10.00000  
    11.00000  
    12.00000  
    13.00000  
    14.00000  
    15.00000  
      11 
      12 
      13 
      14 
      15 
      16 
      17 
      18 
      19 
      20 
    3.000000  3.000000  3.000000  3.000000  3.000000  
    3.000000  3.000000  3.000000  3.000000  3.000000  
    3.000000  

    0.0000000E+00 0.0000000E+00 4.000000  4.000000  4.000000  
    4.000000  4.000000  4.000000  4.000000  4.000000  
    4.000000  

    0.0000000E+00 0.0000000E+00 1.000000  1.000000  1.000000  
    1.000000  1.000000  1.000000  1.000000  1.000000  
    1.000000  

    0.0000000E+00 0.0000000E+00 1.000000  1.000000  1.000000  
    1.000000  1.000000  1.000000  1.000000  1.000000  
    1.000000  

    0.0000000E+00 0.0000000E+00 1.000000  1.000000  1.000000  
    1.000000  1.000000  1.000000  1.000000  1.000000  
    1.000000  

    0.0000000E+00 0.0000000E+00 1.000000  1.000000  1.000000  
    1.000000  1.000000  1.000000  1.000000  1.000000  
    1.000000  

    0.0000000E+00 0.0000000E+00 1.000000  1.000000  1.000000  
    1.000000  1.000000  1.000000  1.000000  1.000000  
    1.000000  

    0.0000000E+00 0.0000000E+00 1.000000  1.000000  1.000000  
    1.000000  1.000000  1.000000  1.000000  1.000000  
    1.000000  

    0.0000000E+00 0.0000000E+00 1.000000  1.000000  1.000000  
    1.000000  1.000000  1.000000  1.000000  1.000000  
    1.000000  

    0.0000000E+00 0.0000000E+00 1.000000  1.000000  1.000000  
    1.000000  1.000000  1.000000  1.000000  1.000000  
    1.000000  



gfortran (gcc version 4.4.3): 
============================= 


    6.0000000  
    7.0000000  
    8.0000000  
    9.0000000  
    10.000000  
    11.000000  
    12.000000  
    13.000000  
    14.000000  
    15.000000  
      11 
      12 
      13 
      14 
      15 
      16 
      17 
      18 
      19 
      20 
    3.0000000  3.0000000  3.0000000  3.0000000  3.0000000  3.0000000  3.0000000  3.0000000  3.0000000  3.0000000  3.0000000  

    1.82795013E-38 0.0000000  4.0000000  4.0000000  4.0000000  4.0000000  1.54142831E-44 1.12103877E-44 2.80259693E-45 4.0000000  4.0000000  

*** glibc detected *** ./tr: double free or corruption (fasttop): 0x0000000000c70b20 *** 
======= Backtrace: ========= 
/lib/libc.so.6(+0x77806)[0x7f9fb0e59806] 
/lib/libc.so.6(cfree+0x73)[0x7f9fb0e600d3] 
./tr[0x4010af] 
./tr[0x401175] 
./tr[0x40262e] 
./tr[0x4026ea] 
/lib/libc.so.6(__libc_start_main+0xfd)[0x7f9fb0e00c4d] 
./tr[0x400a59] 
======= Memory map: ======== 
00400000-00403000 r-xp 00000000 00:16 123        /home/stefanos/Documents/dig/progs/other/transfer/tr 
00602000-00603000 r--p 00002000 00:16 123        /home/stefanos/Documents/dig/progs/other/transfer/tr 
00603000-00604000 rw-p 00003000 00:16 123        /home/stefanos/Documents/dig/progs/other/transfer/tr 
00c70000-00c91000 rw-p 00000000 00:00 0         [heap] 
7f9fac000000-7f9fac021000 rw-p 00000000 00:00 0 
7f9fac021000-7f9fb0000000 ---p 00000000 00:00 0 
7f9fb0de2000-7f9fb0f5c000 r-xp 00000000 08:01 5512795     /lib/libc-2.11.1.so 
7f9fb0f5c000-7f9fb115b000 ---p 0017a000 08:01 5512795     /lib/libc-2.11.1.so 
7f9fb115b000-7f9fb115f000 r--p 00179000 08:01 5512795     /lib/libc-2.11.1.so 
7f9fb115f000-7f9fb1160000 rw-p 0017d000 08:01 5512795     /lib/libc-2.11.1.so 
7f9fb1160000-7f9fb1165000 rw-p 00000000 00:00 0 
7f9fb1165000-7f9fb117b000 r-xp 00000000 08:01 5505258     /lib/libgcc_s.so.1 
7f9fb117b000-7f9fb137a000 ---p 00016000 08:01 5505258     /lib/libgcc_s.so.1 
7f9fb137a000-7f9fb137b000 r--p 00015000 08:01 5505258     /lib/libgcc_s.so.1 
7f9fb137b000-7f9fb137c000 rw-p 00016000 08:01 5505258     /lib/libgcc_s.so.1 
7f9fb137c000-7f9fb13fe000 r-xp 00000000 08:01 5505028     /lib/libm-2.11.1.so 
7f9fb13fe000-7f9fb15fd000 ---p 00082000 08:01 5505028     /lib/libm-2.11.1.so 
7f9fb15fd000-7f9fb15fe000 r--p 00081000 08:01 5505028     /lib/libm-2.11.1.so 
7f9fb15fe000-7f9fb15ff000 rw-p 00082000 08:01 5505028     /lib/libm-2.11.1.so 
7f9fb15ff000-7f9fb16ea000 r-xp 00000000 08:01 787983      /usr/lib/libgfortran.so.3.0.0 
7f9fb16ea000-7f9fb18e9000 ---p 000eb000 08:01 787983      /usr/lib/libgfortran.so.3.0.0 
7f9fb18e9000-7f9fb18ea000 r--p 000ea000 08:01 787983      /usr/lib/libgfortran.so.3.0.0 
7f9fb18ea000-7f9fb18eb000 rw-p 000eb000 08:01 787983      /usr/lib/libgfortran.so.3.0.0 
7f9fb18eb000-7f9fb18ec000 rw-p 00000000 00:00 0 
7f9fb18ec000-7f9fb190c000 r-xp 00000000 08:01 5512780     /lib/ld-2.11.1.so 
7f9fb1ad9000-7f9fb1add000 rw-p 00000000 00:00 0 
7f9fb1b09000-7f9fb1b0b000 rw-p 00000000 00:00 0 
7f9fb1b0b000-7f9fb1b0c000 r--p 0001f000 08:01 5512780     /lib/ld-2.11.1.so 
7f9fb1b0c000-7f9fb1b0d000 rw-p 00020000 08:01 5512780     /lib/ld-2.11.1.so 
7f9fb1b0d000-7f9fb1b0e000 rw-p 00000000 00:00 0 
7fff5e340000-7fff5e356000 rw-p 00000000 00:00 0       [stack] 
7fff5e396000-7fff5e397000 r-xp 00000000 00:00 0       [vdso] 
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0     [vsyscall] 
Aborted 



pgfortran (v12.5): 
================== 


    6.000000  
    7.000000  
    8.000000  
    9.000000  
    10.00000  
    11.00000  
    12.00000  
    13.00000  
    14.00000  
    15.00000  
      11 
      12 
      13 
      14 
      15 
      16 
      17 
      18 
      19 
      20 
    3.000000  3.000000  3.000000  3.000000  
    3.000000  3.000000  3.000000  3.000000  
    3.000000  3.000000  3.000000  

    4.000000  4.000000  4.000000  4.000000  
    4.000000  4.000000  4.000000  4.000000  
    4.000000  4.000000  4.000000  

    5.000000  5.000000  5.000000  5.000000  
    5.000000  5.000000  5.000000  5.000000  
    5.000000  5.000000  5.000000  

    6.000000  6.000000  6.000000  6.000000  
    6.000000  6.000000  6.000000  6.000000  
    6.000000  6.000000  6.000000  

    7.000000  7.000000  7.000000  7.000000  
    7.000000  7.000000  7.000000  7.000000  
    7.000000  7.000000  7.000000  

    8.000000  8.000000  8.000000  8.000000  
    8.000000  8.000000  8.000000  8.000000  
    8.000000  8.000000  8.000000  

    9.000000  9.000000  9.000000  9.000000  
    9.000000  9.000000  9.000000  9.000000  
    9.000000  9.000000  9.000000  

    10.00000  10.00000  10.00000  10.00000  
    10.00000  10.00000  10.00000  10.00000  
    10.00000  10.00000  10.00000  

    11.00000  11.00000  11.00000  11.00000  
    11.00000  11.00000  11.00000  11.00000  
    11.00000  11.00000  11.00000  

    12.00000  12.00000  12.00000  12.00000  
    12.00000  12.00000  12.00000  12.00000  
    12.00000  12.00000  12.00000  

回答

1

你不能指望可分配組件的任何標準behauvior。在任何情況下,它們都不會被存儲在d中。類型結構,也不是簡單的地址。如果您正在訪問描述符或指針,我不清楚沒有任何代碼。無論如何,對於可靠的泛型編程,您應該使用標準通用接口來處理多個過程,並且可能會使用INCLUDE爲它們使用一個公共體。