我想传递一个"指针"复杂Fortran数组的虚部到BLAS函数,仅对实数进行操作。我的意思是"指针"在C语言意义上,因为我不想涉及任何数据复制。
例如,考虑以下简单代码(我的实际代码稍微复杂一些):
function foo(c1, c2, n) result(r)
complex, dimension(:), intent(in) :: c1, c2
integer, intent(in) :: n
real :: r
real, external :: SDOT
r = SDOT(n, c1(1)%re, 2, c2(1)%im, 2)
end function foo
不幸的是,%re
和%im
仅在Fortran 2008中指定。此外,我不确定标准是否允许将复杂的部分选择器应用于数组的各个元素,因为我的编译器都不支持。
gfortran
抱怨"非衍生类型变量"意外'%'。
还有其他方法可以实现我的需求吗?
答案 0 :(得分:1)
我要做的是首先创建一个具有显式形状或假定大小的实际参数的子例程,其中添加了一个大小为2的等级:
function foo(c1, c2, n) result(r)
complex, dimension(:), intent(in) :: c1, c2
integer, intent(in) :: n
real :: r
real, external :: bar
r = bar(c1, c2, n)
end function foo
function bar(c1, c2, n) result(r)
real, dimension(2,n), intent(in) :: c1, c2
integer, intent(in) :: n
real :: r
r = SDOT(n, c1(1,:), 2, c2(2,:), n)
end function
将bar
保存在不同的源文件中并使用隐式接口,以便编译器不会抱怨。有关此有效性的讨论,请参阅Is the storage of COMPLEX in fortran guaranteed to be two REALs?
不幸的是,它仍然会创建数组的临时副本。只有在SDOT
中使用假定的形状参数并且具有明确的接口时,它才会有助于避免复制。
即使您为实部和虚部创建了Fortran实数指针,如果将其传递给外部函数,仍然会生成临时副本。
答案 1 :(得分:0)
根据suggestion的@Vladimir F,我最终得到了以下代码。
bar.F
档案:
function bar(c1, c2, n) result(r)
real, intent(in) :: c1(*), c2(*)
integer, intent(in) :: n
real :: r
r = SDOT(n, c1(1), 2, c2(2), 2)
end function bar
foo.F
档案:
function foo(c1, c2, n) result(r)
complex, dimension(:), intent(in) :: c1, c2
integer, intent(in) :: n
real :: r
real, external :: bar
r = bar(c1, c2, n)
end function foo
答案 2 :(得分:0)
function foo(c1, c2, n) result(r)
complex, dimension(:), intent(in) :: c1, c2
integer, intent(in) :: n
real :: r
REAL, DIMENSION(n) :: reality, dreamy
real, external :: SDOT
Reality = REAL(c1)
DReamy = IMAG(c2)
r = SDOT(n, Reality, 1, Dreamy, 1)
end function foo
由于AIMAG和REAL是ELEMENTAL,你应该能够将它们放入SDOT调用中,因为它们是堆栈中的临时向量。