couple of observations, Fortran needs matrix diagonal() function, and determinant()
- From: "Nasser M. Abbasi" <nma@xxxxxxxxx>
- Date: Fri, 22 Jun 2012 05:11:06 -0500
For fun, I spend over 3 hrs adding Fortran to one entry
of my HOWTO cheat sheet page. This entry is on how to compute
the adjugate matrix of a square matrix.
The adjugate matrix is defined here
http://en.wikipedia.org/wiki/Adjugate_matrix
It is basically the transpose of the cofactor matrix. If you
divide it by the determinant of the matrix, you get the
inverse of the matrix.
I thought this will take me may be 10-20 minutes in Fortran,
but it ended up taking more than 3 hrs. The first reason is
that Fortran does not have determinant function build-in,
and also, it does not have a function to read the diagonal
of a matrix. So, ended up linking to lapack DGETRF() to
do LU decomposition in order to obtain the determinant
from the PLU result of the decomposition.
But all went well in the end. I get the same results as
shown on the wiki, and the same as Matlab and Mathematica,
tested on number of matrices and learned a bit of Fortran.
But my question is: Why is there no intrinsic for finding
the determinant for rank-2 matrix? I find this strange
given Fortran is for numerical computation and given
that Lapack does not have a build-in function either
(one needs to use LU and more processing afterwords)
And also there is no function to obtain the diagonal of
rank 2 array? I see Fortran now has intrinsic for matrix
multiply, transpose. I think a diag() function would be
nice to have, and also a det() function.
I found Fortran array/matrix operation to be flexible
and easy to work with. I just think it needs few more
intrinsic functions such as the above missing ones to make
it 'easier' to do common things. For example, I did this
same operation in Mathematica in only 3 lines, a solution in
Matlab is the same.
Here is the Fortran function I wrote. If you find improvements
please feel free to let me know and I'll correct
-------------------------------------
!-- Find the Adjugate of a square matrix
!-- Version 6/22/2012
!-- gfortran 4.6.3
program t44
implicit none
integer, parameter :: n=3
integer :: INFO,i,j,ii,IPIV(n-1),number_row_exchange
real (kind=kind(0.0d0)) :: A(n,n),B(n-1,n-1),C(n,n)
logical :: M(n,n)
A(1,:) = [1,2,3];
A(2,:) = [4,5,6];
A(3,:) = [7,8,9];
!A(1,:) = [-3,2,-5];
!A(2,:) = [-1,0,-2];
!A(3,:) = [3,-4,1];
DO i=1,n
DO j=1,n
!build the mask to extract submatrices
M = .true.
M(:,j) = .false.
M(i,:) = .false.
B = reshape(pack(A, M),[n-1,n-1])
!-- LU decomposition in order to obtain determinant
CALL DGETRF( n-1, n-1, B, n-1, IPIV, INFO )
!-- determinant of U is the product of diagonal
C(i,j)=1.0d0
DO ii=1,n-1
C(i,j)=C(i,j)*B(ii,ii)
END DO
!-- Adjust sign based on number of row exchanges
number_row_exchange = 0
DO ii=1,n-1
IF (IPIV(ii) .NE. ii) THEN
number_row_exchange = number_row_exchange +1
END IF
END DO
IF (MOD(number_row_exchange,2).EQ.1) THEN
C(i,j)=-C(i,j)
END IF
!-- Apply the (-1)^(i+j) logic
IF (MOD(i+j,2).EQ.1) THEN
C(i,j)=-C(i,j)
END IF
END DO
END DO
!-- Transpose the matrix of cofactor to obtain the adjugate matrix
C = TRANSPOSE(C)
PRINT *,'C='
write(*,'(3F15.4)') ( (C(i,j),j=1,n), i=1,n)
end program t44
-----------------------------
compile/link/run (linux)
export LD_LIBRARY_PATH=/usr/lib/atlas-base/:/usr/lib/atlas-base/atlas/
gfortran -fcheck=all -Wall t44.f90 -L/usr/lib/atlas-base/atlas/ -lblas -llapack
./a.outC=
-3.0000 6.0000 -3.0000
6.0000 -12.0000 6.0000
-3.0000 6.0000 -3.0000
fyi, using Mathematica, has build-in Cofactor function:
-------------------------
<<"Combinatorica`"
mat = {{1,2,3},{4,5,6},{7,8,9}};
cof = Table[Cofactor[mat,{i,j}],{i,3},{j,3}];
adjugate = Transpose[cof]
------------------------
Out[22]= { {-3, 6, -3},
{ 6, -12, 6},
{-3, 6, -3}}
--Nasser
.
- Follow-Ups:
- Re: couple of observations, Fortran needs matrix diagonal() function, and determinant()
- From: michaelmetcalf
- Re: couple of observations, Fortran needs matrix diagonal() function, and determinant()
- From: Tobias Burnus
- Re: couple of observations, Fortran needs matrix diagonal() function, and determinant()
- From: James Van Buskirk
- Re: couple of observations, Fortran needs matrix diagonal() function, and determinant()
- From: Arjen Markus
- Re: couple of observations, Fortran needs matrix diagonal() function, and determinant()
- Prev by Date: Re: Subroutine/library to read a parametric file
- Next by Date: Re: couple of observations, Fortran needs matrix diagonal() function, and determinant()
- Previous by thread: How to vectorize row times matrix rows multiplications (element wise)
- Next by thread: Re: couple of observations, Fortran needs matrix diagonal() function, and determinant()
- Index(es):
Relevant Pages
|