0

カプセル化された型バインド関数を渡す方法は? Modern Fortran Explained の本 (Metcalf、Reid、Cohen) の例で遊んだところ、次のようになりました。

 module mod_polynoms_abstract

  use mod_geometrics

  implicit none

  type, abstract :: bound_user_polynom
   ! No data
   contains
    procedure(user_polynom_interface), deferred :: eval
  end type bound_user_polynom

  abstract interface
    real function user_polynom_interface(poly, pt)
     import :: bound_user_polynom, point
     class(bound_user_polynom)  :: poly
     type(point), intent(in)    :: pt
   end function user_polynom_interface
  end interface

  contains

 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  !Integral driver/chooser function
  real function integral(userfun, options,status)
   class(bound_user_polynom) :: userfun
   integer, intent(in) :: options
   real, intent(out)   :: status

   select case( options )
    case (1)
     integral = first_integral(userfun)
    case (2)
     integral = second_integral(userfun)
    case default
     integral = def_integral(userfun)
   end select

   end function 
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  !1. integration
  real function first_integral(userfun)
   class(bound_user_polynom),intent(in) :: userfun
    first_integral= 1.0 * userfun%eval(point(x=2.,y=2.,z=0.))
  end function  
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  !2. integration
  real function second_integral(userfun)
   class(bound_user_polynom),intent(in) :: userfun
    second_integral= 2.0 * userfun%eval(point(x=2.,y=2.,z=0.))
  end function  
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  !default integration
  real function def_integral(userfun)
   class(bound_user_polynom) :: userfun
    def_integral= 0.0 * userfun%eval(point(x=2.,y=2.,z=0.))
  end function  
 end module

これはコンパイルされますが、プログラムを実行すると異なる結果が得られます。関数を呼び出すと、おそらく次のようになります。

integral_result = integral(poly, 2 , status)

second_integral(userfun) 関数で計算された正しい結果が得られることがあります。しかし、時には結果が間違っています。関数はuserfun%eval(point(x=2.,y=2.,z=0.))正しく計算できませんが、その理由はわかりません。これはこれを行う正しい方法ですか?

編集:

私が使う :

COLLECT_GCC=gfortran4.8
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-unknown-linux-gnu/4.8.0/lto-wrapper
Ziel: x86_64-unknown-linux-gnu
Konfiguriert mit: ./configure --disable- multilib
スレッド モデル: posix
gcc-Version 4.8.0 (GCC)


userfun%eval(point(x=2.,y=2.,z=0.))の正しい結果は0.962435484です。しかし、プログラムを数回実行すると、次のようになりました。

最初の実行: 1.92487097
2 回目の実行: 54877984.0
...: 1.92487097
...: 2.55142141E+27
...: 4.19146938E+33
...: 1.95548379
など ..

編集2:

型多項式は次のように定義されます。

type, extends(bound_user_polynom) :: polynom
   real(kind=kind(1.0D0)), allocatable, dimension(:)            :: coeff
   type(monomial),allocatable, dimension(:)   :: monom
 contains
   procedure :: eval => poly_eval
   procedure, private :: p_add
   generic   :: operator(+) => p_add
   procedure, private :: p_subs
   generic   :: operator(-) => p_subs
 end type

!constructor
interface polynom
 module procedure construct_poly
end interface

私のメインプログラムでは、次のように呼び出します。

integral_result = integral(p(2), 2 , status)
4

1 に答える 1