2016-07-22 14 views
0

Ich muss eine Fortran-Routine schreiben, die die inverse Matrix zurückgibt. Wenn ich den folgenden Code in einem Fortran-Programm ausführe, ist die inverse Matrix korrekt, aber wenn ich die Subroutine von C++ Code aus führe, ist mein erster Wert ein falscher Wert. Es scheint ein Problem mit den Datentypen oder dem Speicher zu sein.Fortran-Subroutine liefert falsches Ergebnis, wenn in C++ - Programm aufgerufen

Was mache ich falsch? Hier

ist das Unterprogramm:

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 

Hier ist die Erklärung in der C++ Code:

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

Hier ist der Anruf von meinem C++ Programm:

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

Mein Programm verwendet nur eine 3x3-Matrix. Wenn ich die Identitätsmatrix passieren sieht das Ergebnis wie:

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

Sie übergeben ein Array, das als Typ 'c_double' deklariert ist, an lapack-Routinen, die eine einfache Genauigkeit erwarten, was manchmal Probleme verursachen kann. Können Sie versuchen, 'sgetrf' und' sgetri' durch 'dgetrf' und' dgetri' zu ersetzen und hilft das? Ich hätte nicht erwartet, dass der Fortran in diesem Fall funktionieren würde. Beachten Sie, dass Sie die Deklarationen wahrscheinlich auch im C++ - Code anzeigen sollten. –

+0

Ich habe die Deklaration in C++ - Code hinzugefügt. Auch ich habe ersetzt, wie Sie angerufen haben, aber das Ergebnis ist eine Matrix mit nur Nullen, egal welche Werte ich versuchte. – fx88

+2

Es ist viel besser, das moderne Fortran90 + Interfacemodul an LAPACK zu verwenden oder zumindest einen Schnittstellenblock zu haben, um den Aufruf auf Fehler zu überprüfen. –

Antwort

4

Sie Ihre Arrays als Typ real mit Art c_double erklärt, aber sie lapack Routinen verwenden, die mit einfacher Genauigkeit Eingänge erwarten (z c_float). Um dies zu beheben, sollten Sie die Anrufe von sgetrf und sgetri durch dgetrf und dgetri ersetzen.

Wie von Vladimir F in den Kommentaren erwähnt, können diese Probleme leichter abgefangen werden, wenn Sie Schnittstellen bereitstellen.