so die folgende Frage (Correct use of FORTRAN INTENT() for large arrays) Ich lernte, dass das Definieren einer Variablen mit Absicht (in) ist nicht genug, da wenn die Variable an ein anderes Unterprogramm/Funktion übergeben wird, kann wieder geändert. Wie kann ich das vermeiden? Im ursprünglichen Thread haben sie darüber gesprochen, das Unterprogramm in ein Modul zu setzen, aber das hilft mir nicht. Zum Beispiel möchte ich die Determinante einer Matrix mit einer LU-Faktorisierung berechnen. Daher benutze ich die Lapack-Funktion zgetrf, aber diese Funktion verändert meine Eingabematrix und der Compiler zeigt keine Warnungen an. Was kann ich also tun?Verhindern Ändern von Variablen mit Absicht (in)
module matHelper
implicit none
contains
subroutine initMat(AA)
real*8 :: u
double complex, dimension(:,:), intent(inout) :: AA
integer :: row, col, counter
counter = 1
do row=1,size(AA,1)
do col=1,size(AA,2)
AA(row,col)=cmplx(counter ,0)
counter=counter+1
end do
end do
end subroutine initMat
!subroutine to write a Matrix to file
!Input: AA - double complex matrix
! fid - integer file id
! fname - file name
! stat - integer status =replace[0] or old[1]
subroutine writeMat(AA,fid, fname, stat)
integer :: fid, stat
character(len=*) :: fname
double complex, dimension(:,:), intent(in) :: AA
integer :: row, col
character (len=64) :: fmtString
!opening file with given options
if(fid /= 0) then
if(stat == 0) then
open(unit=fid, file=fname, status='replace', &
action='write')
else if(stat ==1) then
open(unit=fid, file=fname, status='old', &
action='write')
else
print*, 'Error while trying to open file with Id', fid
return
end if
end if
!initializing matrix print format
write(fmtString,'(I0)') size(aa,2)
fmtString = '('// trim(fmtString) //'("{",ES10.3, ",", 1X, ES10.3,"}",:,1X))'
!write(*,*) fmtString
!writing matrix to file by iterating through each row
do row=1,size(aa,1)
write(fid,fmt = fmtString) AA(row,:)
enddo
write(fid,*) ''
end subroutine writeMat
!function to calculate the determinant of the input
!Input: AA - double complex matrix
!Output determinantMat - double complex,
! 0 if AA not a square matrix
function determinantMat(AA)
double complex, dimension(:,:), intent(in) :: AA
double complex :: determinantMat
integer, dimension(min(size(AA,1),size(AA,2)))&
:: ipiv
integer :: ii, info
!check if not square matrix, then set determinant to 0
if(size(AA,1)/= size(AA,2)) then
determinantMat = 0
return
end if
!compute LU facotirzation with LAPACK function
call zgetrf(size(AA,1),size(AA,2), AA,size(AA,1), ipiv,info)
if(info /= 0) then
determinantMat = cmplx(0.D0, 0.D0)
return
end if
determinantMat = cmplx(1.D0, 0.D0)
!determinant of triangular matrix is product of diagonal elements
do ii=1,size(AA,1)
if(ipiv(ii) /= ii) then
!a permutation was done, so a factor of -1
determinantMat = -determinantMat *AA(ii,ii)
else
!no permutation, so no -1
determinantMat = determinantMat*AA(ii,ii)
end if
end do
end function determinantMat
end module matHelper
!***********************************************************************
!module which stores matrix elements, dimension, trace, determinant
program test
use matHelper
implicit none
double complex, dimension(:,:), allocatable :: AA, BB
integer :: n, fid
fid = 0;
allocate(AA(3,3))
call initMat(AA)
call writeMat(AA,0,' ', 0)
print*, 'Determinante: ',determinantMat(AA) !changes AA
call writeMat(AA,0, ' ', 0)
end program test
PS: Ich bin mit dem ifort Compiler v15.0.3 20150407
ist es so schwer, die lapack docs zu lesen und sich bewusst zu sein, wenn die Routinen, die Sie verwenden, ihre Argumente ändern? – agentp
sicher ist es nicht so schwer, aber ich war neugierig und wollte wissen, ob es eine Möglichkeit gab, dieses Verhalten zu vermeiden, so dass ich nicht ein temporäres Array verwenden müsste –
ist eigentlich nicht klar, was Sie fragen. Ich habe es als "Wie kann ich den Compiler dazu bringen, mich zu warnen, wenn eine externe Routine eine' intent (in) 'Variable" ändert. Es scheint keinen Weg zu geben, eine Kopie zu erstellen, aber die Verwendung von Klammern "(AA)" im Unteraufruf sollte eine Kopie erzwingen. – agentp