配列の長さを関数に渡す

これが些細な質問であればごめんなさい。私のfortran - fuは貧しいです。

Fortranに配列の長さを渡す方法はありますか? common (私が収集するものは global と同等です)を使うこともオプションです。私が望むのは、メインプログラムで配列を持つ関数を呼び出すことです。たとえば(これは入力されたもので、どこからでも貼り付けはできません)

program prog
integer num
double precision x(num),v
double precision test

....
v=test(x,num)
....


function test(x,num)
double precision test
integer num
double precision x(num)
test=0.0d0
....
return
end

num は定数ではないので、これはコンパイルされません。重要なことは、配列の大きさを知ることです。

編集:私はf95コンパイラを使用しています。

Edit2:私は幸運なしでハイパフォーマンスマークのソリューションを試しました:

  program prog
  integer v
  parameter (v=10)
  double precision x(v),test,k
  k=test(x)
  write (*,*) size(x)
  stop
  end

  function test(x)
  double precision, dimension(:),intent(in) :: x
  double precision test
  write (*,*) size(x)
  test = 0.0d0
  return
  end

出力は10と10が書かれた2行でなければなりません。代わりに私はこれを持っています:

/scpc:niels: #$ f95 err.f
/scpc:niels: #$ ./a.out 
           0
          10
/scpc:niels: #$ 
2
@VladimirFコメントありがとうございます。私はEmacsが使用するのと同じインデントを使用します。 4つのあなたの他のコメントとして、私はあなたのadivsorコードを更新しています。私のfortran-fuは低いです。私はそれを試してやろうとすれば、もっと良いダメージを与えるだろうと思う。
追加された 著者 Yotam,
共通ブロックの横に別のスタイルがコメントしています。 '終了'の前に '停止'または '戻る'を使用する理由はありません。 rp rp = kind(1d.0)のように倍精度を避けて real(rp) code>を使用するか、 selected_real_kind を使用します。また、ツアーコードをインデントします。
追加された 著者 Vladimir F,

2 答え

Fortran配列はどれくらいの長さであるかを「知って」いるので、配列とその長さを別の引数として渡す必要はありません。 (あなたが古いFortranのコードとインターフェースしていない限り)今日、あなたは次のようなものを書くでしょう

function test(arr)
    real, dimension(:), intent(in) :: arr
    ...
    integer :: arrsize
    ...
    arrsize = size(arr)
    ...

配列サイズが渡されている古いコードにインターフェイスする必要がある場合、このような呼び出しを行うことができます

  call old_fortran_subr(array, size(array, 1), other_arguments)

ああ、私が書いている間、最初から書いたコードでは common とは何の関係もなく、70年代以前の(deprecated)機能です。代わりに、モジュール変数を使用します。

9
追加された
私は運がなければこれを試しました。私は自分の質問を編集しました。モジュール変数についてはどこで読むことができますか?
追加された 著者 Yotam,
Fortranのどのバージョンから、サブルーチンのパラメータとして渡された配列次元の明示的宣言が義務付けられている必要があるかは誰が知っていますか?つまり、 "real、dimension(3,5):: arr"ではなく、 "real、dimension(:, :) :: arr"を宣言するだけです。 @HighPerformanceMarkはOLD Fortranのコードと対話する必要があると言ったので、Fortran 77ですか?
追加された 著者 wiswit,
+1最後の文だけです。コモンブロックは、ぼんやりとした現代のFortranの方言でさえも、ペストのように避けなければなりません。
追加された 著者 talonmies,
私のコンパイラ(インテルFortran 13.0)は新しいコードをコンパイルし、 10 を2回書き出します。あなたが掲示したものはコードの忠実なコピーではないか、私は見ることができない問題があります。
追加された 著者 High Performance Mark,
SOのモジュール変数については、他の場所でも読むことができます。
追加された 著者 High Performance Mark,
モジュール変数の主題については、共通変数よりも悪いことはありませんが、可能な限り、それらは避けてください。グローバル変数はコードのメンテナンスと開発を困難にしますが、変数のスコープを可能な限り小さく保つことは実際の習慣であり、長期的には時間とエネルギーを節約します。
追加された 著者 Ian Bush,
@ Yotam:関数の仮引数を仮定した形状配列( dimension(:))があります。これには "明示的なインタフェース"が必要です。これを提供する最も簡単な方法は、関数をプログラムの内部手順、またはプログラムで使用するモジュールの内部手順にすることです。
追加された 著者 sigma,

OK、ここではたくさんのことが起こっています。特に、使用しているFortranスタイルは古風なものです。ステップでそれをやってみましょう...

まず暗黙的にnoneを必ず使用するようにしてください

第2に、配列のサイズを先験的に知っている場合は、シンボル定数を使用してそのサイズを表すことができます。これを行うには、次のパラメータを使用します。

Program prog

  Implicit None ! ALWAYS USE THIS

  Integer, Parameter :: num = 36

  Double Precision x( num )
  Double Precision test
  Double Precision v

  Call Random_number( x )

  v = test( x, num )

  Write( *, * ) v

End Program prog

Function test( x, num )

  Implicit None ! ALWAYS USE THIS

  Double Precision test

  Integer num
  Double Precision x( num )

  Integer i

  test = 0.0d0
  Do i = 1, num
     test = test + x( i ) * x( i )
  End Do

End Function test
[[email protected] stackoverflow]$ gfortran -O -std=f95 -Wall -Wextra -pedantic func.f90
[[email protected] stackoverflow]$ ./a.out
   12.129812171430215     

numが36に設定されていることに注意してください。ただし、パラメータビットは値を変更できないことを意味します。これは定数なので、配列のサイズを設定するために使用できます。

それが1990年までの出来事でした。そして答えを変える言葉にはいくつかのことが入ってきました。あなたの質問に最も直接的に関連しているのは、実行時に配列のサイズを指定できる割り当て可能な配列と、配列をサブプログラムに渡すのを簡単にする形状配列です。しかし、他にもたくさんのものが入ってきました。あなたは本を見て、それらについて学ぶことをお勧めします。新しい言語は、古い言語よりはるかに表現力があり安全です。一例として、私は今、上記のようなものを次のように書いています。

[[email protected] stackoverflow]$ cat func.f90

Module numbers_module

  Integer, Parameter :: wp = Selected_real_kind( 12, 70 )

End Module numbers_module

    Module funcs_module

      Use numbers_module

      Implicit None

      Public :: test

      Private

    Contains

      Function test( x ) Result( sum_sq )

        Implicit None ! ALWAYS USE THIS

        Real( wp ) :: sum_sq

        Real( wp ), Dimension( : ), Intent( In ) :: x

        sum_sq = Sum( x * x )

      End Function test

    End Module funcs_module

    Program prog

      Use numbers_module
      Use funcs_module

      Implicit None ! ALWAYS USE THIS

      Real( wp ), Dimension( : ), Allocatable :: x 

      Real( wp ) :: v

      Integer :: num

      Write( *, * ) 'How many elements ?'
      Read ( *, * ) num
      Allocate( x( 1:num ) )

      Call Random_number( x )

      v = test( x )

      Write( *, * ) v

    End Program prog

    [[email protected] stackoverflow]$ gfortran -O -std=f95 -Wall -Wextra -pedantic func.f90
    [[email protected] stackoverflow]$ ./a.out
     How many elements ?
    39
       14.151818513394156  

この方法を使用する場合は、このメソッドを使用する理由を理解するために、テストするインターフェイスがコールポイントのスコープ内にある必要があります。これを行うには、ブックを読んでください。

ああ。一般。いやだっていうだけだよ。

2
追加された