2016-07-26 54 views
0

我想在Fortran中創建function composition。這個想法是如果我有f(x)和g(x),我想找到f(g(x))。 Python的語法很簡單Better Function Composition in PythonFortran中的函數組合

下面是一個示例Fortran代碼:

module test10 
implicit none 
contains 
    function f5x (x) 
     real :: f5x 
     real, intent (in) :: x 
     f5x = 5.00*x 
    end function f5x 

    function f10x (x) 
     real :: f10x 
     real, intent (in) :: x 
     f10x = 10.00*x 
    end function f10x 


end module test10 


program call_test10 
    use test10 
    implicit none 
    real :: val1, val2, input 


    interface 
    real function fx_new (y) 
     real, intent (in) :: y 
    end function fx_new 
    end interface 


    input=1.0 
    write (*,*) 'Invoking f5x' 
    val1 = f5x(1.0) 
    write (*,*) val1 
    write (*,*) 'Invoking f10x' 
    val1 = f10x(1.0) 
    write (*,*) val1 
    write (*,*) 'Invoking f10x(f5x)' 
    procedure (fx_new), pointer :: ptr1 => f5x 
    procedure (fx_new), pointer :: ptr2 => f10x 
    val2 = ptr2(ptr1) 
    write (*,*) val2 

end program call_test10 

中的陳述和val1 = f5x(1.0)val1 = f10x(1.0)本身運行。但是當涉及到函數組合時,我不知道如何在Fortran中實現這個功能。我想評估f10x(f5x),然後想要給x賦值。有任何想法嗎?

如果我有一個模塊文件和函數返回類型,參數的數目和參數匹配的類型,可以Fortran編譯器決定哪些函數包含的文件來執行?我想知道的另一件事是我可以擺脫界面(通過使用程序指針或其他)?執行外部函數的接口的概念對我來說看起來很混亂,所以如果可能的話,請提供一種無需接口即可執行外部函數的方法。我知道關鍵字external的,但它是爲那些更早版本(雖然它繼續在新標準的工作)。

AS過程指針在新標準(2003年,2008年,...),我會用Fortran標準2008

+0

封鎖在fortran中是不可能的。 – wey273824

+1

我不認爲你可以完成這個任務,而不必訴諸於通過'iso_c_binding'中的過程'c_f_pointer'實現的用戶定義派生數據類型與指針類型綁定過程和C語言風格的轉換。無論如何,函數組合違反了Fortran中如何傳遞參數。請參閱:https://software.intel.com/zh-cn/blogs/2009/03/31/doctor-fortran-in-ive-come-here-here-for-an-argument – jlokimlin

回答

1

我不認爲這是可能的,你希望它的方式。

在我開始之前:即使在允許這種事情的語言中,如果您像輸入ptr2(ptr1)這樣的東西,結果將是一個函數,而不是一個值。您將無法將其存儲在REAL變量中。

你可以寫你自己的功能,如:

function my_func(x) 
    use test10, only: f5x, f10x 
    implicit none 
    real, intent(in) :: x 
    real :: my_func 
    my_func = f10x(f5x(x)) 
end function my_func 
0

這也許是有點看它天真的方式,但Fortran語言允許傳遞函數作爲參數,所以你可以有:

real function f(x, g) 
external g 
real x 
is_g_present = PRESENT(g) 

if is_g_present: 
    ! Do something with g and x 
else: 
    ! Do f(x) normally 
endif 
return 

這將允許您將f稱爲f(x)或f(x,g)。這不正是你所要求的,但是對於Fortran來說,這是一個不錯的和簡單的解決方法。

(僞代碼,因爲我沒有一臺機器來測試我不寫東西完全愚蠢的,現在,我會寫這個只是作爲一個評論,但我缺乏此刻的聲譽,對不起)

+0

「外部」聲明是一場噩夢保持。 – jlokimlin

4

這是我已經在這裏顯示的一個例子Dynamic function creation from another function(你是否搜索過?)。我認爲這個問題不是完全重複的,所以我正在重複使用而不是關閉。其他人可以查看這個。

module ComposeObj 
    !here use modules defining your working kind as you wish 

    implicit none 

    private 
    public Compose 

    abstract interface 
    !declare fce as a function of the type you wish, probably a real function of a real variable  
    end interface 

    type Compose 
    private 
    procedure(fce),pointer,nopass :: f1 => null(),f2=>null() 
    contains 
    procedure,public :: call => helper 
    endtype Compose 

    interface Compose 
    procedure NewCompose 
    end interface 

contains 

    function NewCompose(f,g) 
    procedure(fce) :: f,g 
    type(Compose) :: NewCompose 

    NewCompose%f1 => f 
    NewCompose%f2 => g 
    end function NewCompose 

    pure real(work_kind) function helper(this,x) 
    class(Compose),intent(in) :: this 
    real(work_kind),intent(in) :: x 
    helper = this%f1(this%f2(x)) 
    end function helper 

end module ComposeObj 

基本上你必須預先準備好可以做功能組合的課程。你不能僅僅創建一個閉包。

但是你可以動態分配函數指針到您想要的功能,不具有提前完成。

而你必須使用它,使用%call(x)方法,你不能覆蓋(),因爲它不是Fortran中的運算符(它在C++中)。

type(Compose) :: f1_f2 
    f1_f2 = Compose(f1, f2) 

    val2 = f1_f2%call(x) 

本地,您可以使用內部功能。我和其他人已經多次在這裏展示。這是不值得重複的一切,只是一個代碼示例:

val2 = composed_f1_f2(x) 

contains 

    function composed_f1_f2(x) 
    real :: composed 
    real, intent(in) :: x 
    composed = f1(f2(x)) 
    end function