2016-07-22 9 views
0

逆行列を返すFortranルーチンを作成する必要があります。私がFortranプログラムで以下のコードを実行すると、逆行列は正しいですが、C++コードからサブルーチンを実行すると、最初の値が間違った値になります。これは、データ型やメモリの問題のようです。C++プログラムで呼び出すと、Fortranサブルーチンが間違った結果を返します

私は間違っていますか?ここで

はサブルーチンである:ここでは

subroutine get_inverse_matrix(matrix, rows_matrix, cols_matrix, tmpMatrix, rows_tmpMatrix, cols_tmpMatrix) bind(c) 
     use iso_c_binding 
     integer :: m, n, lda, lwork, info, size_m 
     integer(c_int) :: rows_matrix, cols_matrix, rows_tmpMatrix, cols_tmpMatrix 
     real(c_double) :: matrix(rows_matrix, cols_matrix), tmpMatrix(rows_tmpMatrix, cols_tmpMatrix) 
     integer, dimension(rows_matrix) :: ipiv 
     real, dimension(rows_matrix) :: work 
     size_m = rows_matrix 
     m = size_m 
     n = size_m 
     lda = size_m 
     lwork = size_m 
     write(*,*) "Matrix: ", matrix 
     !tmpMatrix = matrix 
     write(*,*) "Temp matrix: ", tmpMatrix 
     ! LU-Faktorisierung (Dreieckszerlegung) der Matrix 
     call sgetrf(m, n, tmpMatrix, lda, ipiv, info) 
     write(*,*) info 
     ! Inverse der LU-faktorisierten Matrix 
     call sgetri(n, tmpMatrix, lda, ipiv, work, lwork, info) 
     write(*,*) info 
     select case(info) 
      case(0) 
      write(*,*) "SUCCESS" 
      case(:-1) 
      write(*,*) "ILLEGAL VALUE" 
      case(1:) 
      write(*,*) "SINGULAR MATRIX" 
     end select 
    end subroutine get_inverse_matrix 

は、C++コードでの宣言です:ここで

extern "C" 
{ 
void get_inverse_matrix(double *matrix, int *rows_matrix, int *cols_matrix, double *tmpMatrix, int *rows_tmpMatrix, int *cols_tmpMatrix);} 

は私のCからの呼び出しです++プログラム:

get_inverse_matrix(&lhs[0], &sz, &sz, &res[0], &sz, &sz); 

マイプログラム3x3マトリックスのみを使用します。私は単位行列を渡すと結果は以下のようになります。

5.29981e-315 0 0 
0 1 0 
0 0 1 
+1

単精度を期待するlapackルーチンに 'c_double'型として宣言された配列を渡していますが、これは時には問題を引き起こすことがあります。あなたは 'sgetrf'と' sgetri'を 'dgetrf'と' dgetri'で置き換えることができますか?これは助けになりますか?私は、この場合にはどちらも働くことを期待していなかっただろう。おそらく、C++コードの宣言も表示する必要があります。 –

+0

私はC++コードで宣言を追加しました。あなたが呼び出したときにも置き換えられましたが、結果はゼロだけの行列です。値を試しても問題ありません。 – fx88

+2

LAPACKに現代のFortran90 +インターフェース・モジュールを使用するか、少なくともエラーの呼び出しを検査するインターフェース・ブロックを使用する方がはるかに優れています。 –

答えて

4

あなたは親切c_doubleとタイプrealとして、あなたの配列を宣言されていますが、単精度入力(例えばc_floatを)期待しているLAPACKルーチンを使用しています。この問題を解決するには、sgetrfsgetriの呼び出しをdgetrfdgetriに置き換える必要があります。

コメントでVladimir Fが指摘したように、これらの問題は、インターフェイスを提供した方が簡単に見つかる可能性があります。

関連する問題