3

この単純な Fortran コード ( stack.f90) があります。

      subroutine fortran_sum(f,xs,nf,nxs)
      integer nf,nxs
      double precision xs,result
      dimension xs(nxs),result(nf)
      external f 
      result = 0.0
      do I = 1,nxs
         result = result + f(xs(I))
         print *,xs(I),f(xs(I))
      enddo
      return
      end 

私が使用してコンパイルしています:

f2py -c --compiler=mingw32 -m stack2 stack2.f90

次に、この Python スクリプトを使用してテストします ( stack.py):

import numpy as np
from numpy import cos, sin , exp
from stack import fortran_sum
def func(x):
    return x**2

if __name__ == '__main__':
    xs = np.linspace(0.,10.,10)
    ans =  fortran_sum(func,xs,1)
    print 'Fortran:',ans
    print 'Python:',func(xs).sum()

それを使用して実行すると、次の"python stack.py"ようになります。

   0.0000000000000000        0.00000000
   1.1111111111111112              Infinity
   2.2222222222222223              Infinity
   3.3333333333333335        9.19089638E-26
   4.4444444444444446              Infinity
   5.5555555555555554        0.00000000
   6.6666666666666670        9.19089638E-26
   7.7777777777777786        1.60398502E+09
   8.8888888888888893              Infinity
   10.000000000000000        0.00000000
Fortran: None
Python: 351.851851852

私の質問は次のとおりです。

  • 関数が正しく評価されないのはなぜですか?

  • resultPythonに戻るには?

  • xsFortranで一度に配列を評価することは可能ですか?

ありがとうございました!


EDIT:@SethMMortonからの素晴らしいヒントで、私は次のようになりました:

      subroutine fortran_sum(f,xs,nxs,result)
      implicit none
      integer :: I
      integer, intent(in) :: nxs
      double precision, intent(in) :: xs(nxs)
      double precision, intent(out) :: result
      double precision :: f
      external :: f 
      ! "FIX" will be added here
      result = 0.0
      do I = 1,nxs
        result = result + f(xs(I))
        print *,xs(I),f(xs(I))
      enddo
      return
      end 

stack.pyこのコマンドを変更して実行: ans = fortran_sum(func,xs); 与えます:

   0.0000000000000000        0.0000000000000000
   1.1111111111111112        3.8883934247189009E+060
   2.2222222222222223        3.8883934247189009E+060
   3.3333333333333335        9.1908962428537221E-026
   4.4444444444444446        3.8883934247189009E+060
   5.5555555555555554        5.1935286092977251E-060
   6.6666666666666670        9.1908962428537221E-026
   7.7777777777777786        1603984978.1728516
   8.8888888888888893        3.8883934247189009E+060
   10.000000000000000        0.0000000000000000
Fortran: 1.55535736989e+61
Python: 351.851851852

これは間違っています。x=x(I)中間変数を追加し、この変数を使用して関数を呼び出すと、この奇妙な動作は発生しませんf(x)。面白いことに、f(x)一度電話すると、目的の電話f(x(I))も機能します。この「FIX」を適用した後:

double precision :: x, f_dummy
x = xs(I)
f_dummy = f(x)

次に、コンパイルして実行すると、正しい結果が得られます。

   0.0000000000000000        0.0000000000000000
   1.1111111111111112        1.2345679012345681
   2.2222222222222223        4.9382716049382722
   3.3333333333333335        11.111111111111112
   4.4444444444444446        19.753086419753089
   5.5555555555555554        30.864197530864196
   6.6666666666666670        44.444444444444450
   7.7777777777777786        60.493827160493836
   8.8888888888888893        79.012345679012356
   10.000000000000000        100.00000000000000
Fortran: 351.851851852
Python: 351.851851852

誰かが理由を説明できればいいのですが?

4

1 に答える 1