fortran66のブログ

fortran について書きます。

関数合成が難しい。

Fortranで、関数合成 f(g(x)) = f.g (x) のような記述ができないかと思ったんですが難しい。
.op.型の自己定義演算子は、関数引数の場合は出来ないし。関数ポインタの配列も出来ないのでまだいい考えが浮かびません。


適当にテストのメモ帳。
Fortranではポインターの配列が定義出来ないので、ポインターを要素として持つ派生型を定義して、派生型の配列を使うという手がよくとられます。
しかし、派生型に関数ポインターを入れると、今度はOOP用途と勘違いされるので、NOPASS指定子が必要になります。関数ポインタのINTERFACEはABSTRACT INTERFACEとして先に定義しておきます。

もう少し、考えてゆきたいです。

■実行結果

SIN,COS,EXPを合成した関数を副プログラムとして作ります。合成する関数は実行時に与えられるようにします。
何故かLOGも混ぜようとしたらコンパイル・エラーがでました。

■ソース・プログラム

MODULE m_func
 IMPLICIT NONE

 ABSTRACT INTERFACE
   REAL FUNCTION a_func(x)
     REAL, INTENT(IN) :: x
   END FUNCTION
 END INTERFACE

 TYPE :: t_pp
  PROCEDURE(a_func), NOPASS, POINTER :: f
 END TYPE t_pp

 CONTAINS
   REAL FUNCTION point( funcs,  x )
     TYPE(t_pp) :: funcs(:)
     REAL, INTENT(IN) :: x
     INTEGER :: i
     point = x
     DO i = 1, SIZE(funcs)
      point = funcs(i)%f( point )
     END DO
     RETURN
   END FUNCTION point

END MODULE m_func
!=================================================
PROGRAM test
 USE m_func
 IMPLICIT NONE
 REAL :: x, y
 PROCEDURE(a_func), POINTER :: f
 TYPE (t_pp) :: pp(10)
 x = 1.0
 pp(1)%f => SIN
 pp(2)%f => COS
 pp(3)%f => EXP

 y = point(pp(1:3), x)
 PRINT *, x, y , EXP(COS(SIN(x)))

 STOP
END PROGRAM test