2

我想将指向复杂 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抱怨“非派生类型变量的意外'%'”。

还有其他方法可以实现我的需要吗?

4

3 回答 3

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在不同的源文件中并使用隐式接口,以便编译器不会抱怨。有关此有效性的讨论,请参阅Fortran 中 COMPLEX 的存储是否保证为两个 REAL?

不幸的是,它仍然会创建数组的临时副本。仅当您在其中使用假定的形状参数SDOT并具有显式接口时,它实际上有助于避免复制。

即使您为实部和虚部创建了 Fortran 实指针,如果将其传递给外部函数,仍然会生成一个临时副本。

于 2016-12-01T16:56:26.833 回答
0

根据@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
于 2016-12-01T20:13:57.143 回答
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 调用中,因为它们是堆栈上的临时向量。

于 2016-12-02T13:39:26.780 回答