2013-03-07 6 views
5

Fortran 2003で、疎行列の線形代数を行うコードをいくつか書いています。私は新しい標準のより抽象的な機能のいくつかを悪用しようとしているので、コードをあまり繰り返さずに単純なプログラムを持っています。fortran 2003のランタイム多形性

私はというプロシージャへのポインタを渡しています。これは、行列、いくつかのベクトル、使用される反復メソッドの許容差などを取ります。 matvecは、行列ベクトルの乗算に使用するサブルーチンです。

問題は時々matvecがこの手順に送られた通常のものよりも余分な引数colorlist, color1, color2を取る手順です。私はこれを扱ういくつかの方法を考えることができます。

最初のアイデア:2つの異なる抽象インターフェイスmatvec1,matvec2と2つの異なるソルバーを定義します。これは機能しますが、コードを複製することを意味します。これは私が避けようとしているものです。

もう一つのアイデア:同じ抽象インタフェースmatvecを維持し、余分な引数は、color1color2オプション作ります。これは、すべてのmatvecルーチン(たとえ実際にはオプションではないものであっても)と、まったく使用されていないルーチンではオプションにすることを意味します。もしそうすれば、私は地獄に行くだろうと確信している。

私は他の多くの最適なソリューションよりも少ないと考えることができます。私はこれについていくつかの情報を入力したいと思います - 私はそれを行うためのエレガントな方法があると確信しています、私はそれが何であるか分かりません。

答えて

5

実際には、プロシージャが呼び出されるたびに(2つの呼び出し間で変更されるため)追加の引数を渡す必要があるかどうか、またはある時点で初期化して関数で使用することができますか。後者の場合、必須の引数を持つサブルーチンmatvecを定義する抽象インターフェースを持つクラスを作成することができます。その後、必要な追加オプションを保持できる、より特殊なクラスでクラスを拡張することができます。彼らは(同じ引数リストを持つ)親クラスと同じmatvecインターフェイスを定義する必要がありますが、matvecプロシージャが呼び出されたときにそれらに格納されている追加の値を使用できます。

同様のケースについては、in this answerという詳細な例があります(2番目の例はmodule rechercheRacineです)。代わりに、明示的な引数として手続きポインタを渡すので、あなたは一般的なインターフェースの後ろに様々なmatvecのルーチンを置くことができ

2

interface matvec 
    module procedure matvec1, matvec2 
end interface 

次に、あなたのsolverルーチンはちょうど余分な引数の有無にかかわらず、一般的な名称を使用することができます。

type :: solver 
    real, allocatable :: matrix(:,:), v1(:), v2(:) 
contains 
    procedure, pass :: matvec1 
    procedure, pass :: matvec2 
    generic :: matvec => matvec1, matvec2 
end type 

主な違いは、これは正しい手順を決定するために多型を使用しないことである。同じアプローチはもちろん型結合手順派生型としてsolverを定義するバリントの提案手法を用いた場合に取ることができます呼び出されるのではなく、仮引数の特徴です。

私はプロシージャポインタの意図がわかりません。実行時にターゲットを変更したい場合(または、おそらく '未定義'ステータスに特別な意味を割り当てる)、ポインターが唯一の方法であり、すべてのターゲットが同じ抽象インターフェースに一致する必要があります。代わりに、引数に基づいていくつかのプロシージャの1つを選択するだけであれば、インタフェース(私の例)やオーバーロード(Bálintの例)を利用することができます。ある型の各拡張は、継承されたgenericバインディングを新しいプロシージャで拡張したり、継承した特定のバインディングをオーバーロードすることができます。

関連する問題