我试图找到一种方法将具有可分配组件的派生类型对象传递给 Fortran 过程,而过程不知道类型定义。要了解我为什么要这样做,有关背景的一些信息可能会有用。
考虑一个包含稀疏矩阵向量乘法的通用过程,如 Lanczos 对角化例程。该过程本身不使用矩阵,仅使用向量。该过程唯一需要对矩阵做的就是将它与向量一起传递给矩阵向量乘法例程。稀疏矩阵必须是具有可分配组件的派生类型变量。
在我看来,程序不需要知道稀疏矩阵的数据类型。它只需要将它传递给矩阵向量乘法例程,然后它将对其进行适当的解码。我试图做的是使用TRANSFER
内部函数将派生类型变量转换为可分配的字节数组,然后将其传输回初始派生类型变量。不幸的是,这不适用于具有可分配组件的派生类型变量,请参阅以下两个链接:链接 1、
链接 2
因此,如上所述,我的问题如下:是否有一种合理的方法*将具有可分配组件的派生类型对象传递给 Fortran 过程,而过程不知道类型定义?
*注意:我知道我可以使用自定义的内部格式化写入将派生类型变量存储到固有类型数组中,例如字符数组。这在我看来非常奇怪,但也许我错了?
编辑 :: 正如 Vladimir 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