2016-12-01 63 views
1

我想將複雜Fortran陣列的虛構部分的「指針」傳遞給僅對實數進行操作的BLAS函數。我的意思是C語言意義上的「指針」,因爲我不想涉及任何數據複製。將複雜Fortran陣列的虛構部分的「指針」傳遞給BLAS例程

例如,請考慮下面這個簡單的代碼(我的實際代碼稍微複雜):

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在2008年的Fortran唯一指定。此外,我不確定該標準是否允許將複雜的部件選擇器應用於陣列的各個元素,因爲我的編譯器都不支持這一點。

gfortran抱怨「對於非派生類型變量,意外'%'」。

有沒有其他方法可以實現我所需要的?

+1

Fortran也有指針。但是,您的示例不使用它們。你真的需要一個指針嗎?或者你只是想傳遞一個參數? –

+1

另請參閱http://stackoverflow.com/questions/31590004/is-the-storage-of-complex-in-fortran-guaranteed-to-be-two-reals/和http://stackoverflow.com/questions/ 36874982/equivalent-in-fortran-77-real-and-complex-variable –

+0

'c1(1)%re'是完全有效的,但不是數組,因此我不確定這個問題的部分是什麼意思。 – francescalus

回答

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實型指針,如果將它傳遞給外部函數,仍然會創建一個臨時副本。

+0

是的,實際上它應該可以工作。我試圖避免它,因爲面向矩陣的BLAS例程中的二維複雜陣列複雜化了。 –

+0

@Vladimir F,感謝提示。在'bar()'中,除了'c1'和'c2'作爲'real c1(*),c2(*)'外,因此,我們可以調用'r = SDOT(n,c1(1),2,c2(2),n)'並避免複製。 –

+0

是的,它應該工作。 –

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 
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是元素,你應該能夠把他們在SDOT通話,因爲他們是一個暫時的矢量在堆棧上。