我正在試圖找到一種方法,將具有可分配組件的派生類型對象傳遞給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