I saw this Fortran code to calculate the determinant of a n x n size matrix on the internet. I intend to apply it to my research which involves a very large size of matrix. But I tried to apply it first to a 3 x 3 matrix and run it using gfortran compiler to understand how it works, but I get the following errors:
determinant.f:39.26:
cf = cofactor(matrix, i, 1)
1
Warning: Legacy Extension: REAL array index at (1) determinant.f:39.26:
cf = cofactor(matrix, i, 1)
1
Error: Array index at (1) is an array of rank 2 determinant.f:14.21:
D = determinant(A)
1
Error: Return type mismatch of function 'determinant' at (1) (UNKNOWN/REAL(4)) determinant.f:14.21:
D = determinant(A)
1
Error: Procedure 'determinant' at (1) with assumed-shape dummy argument 'matrix' must have an explicit interface determinant.f:14.10:
D = determinant(A)
1
Error: Function 'determinant' at (1) has no IMPLICIT type
The code which I worked on is as shown below:
Program determinant_matrix
implicit none
real, dimension(9) :: Aa
real, dimension(3,3):: A
real :: D
integer, dimension(1:2) :: order2 = (/2,1/)
Aa = (/2.0,9.0,4.0,7.0,5.0,3.0,6.0,1.0,8.0/)
A= reshape(Aa,(/3,3/), order = order2 )
D = determinant(A)
end program determinant_matrix
c Expansion of determinants using Laplace formula
recursive function determinant(matrix) result(laplace_det)
real, dimension(:,:) :: matrix
integer :: msize(2), i, n
real :: laplace_det, det
real, dimension(:,:), allocatable :: cf, cofactor
msize = shape(matrix)
n = msize(1)
if (n .eq. 1) then
det = matrix(1,1)
else
det = 0
do i=1, n
allocate(cf(n-1, n-1))
cf = cofactor(matrix, i, 1)
det = det + ((-1)**(i+1))* matrix(i,1) * determinant(cf)
deallocate(cf)
end do
end if
laplace_det = det
end function determinant
function cofactor(matrix, mI, mJ)
real, dimension(:,:) :: matrix
integer :: mI, mJ
integer :: msize(2), i, j, k, l, n
real, dimension(:,:), allocatable :: cofactor
msize = shape(matrix)
n = msize(1)
allocate(cofactor(n-1, n-1))
l=0
k = 1
do i=1, n
if (i .ne. mI) then
l = 1
do j=1, n
if (j .ne. mJ) then
cofactor(k,l) = matrix(i,j)
l = l+ 1
end if
end do
k = k+ 1
end if
end do
return
end function cofactor
Please, is there a way to rectify these errors?
It goes without saying that this is ... not a good method. The first row would spawn N cofactors. Each of those would spawn (N-1) cofactors and so on, resulting in N! cofactors. N! (N factorial) grows very fast with N. There are also a lot of allocations/deallocations and there is likely to be a lot of memory in use at the same time.
To use a function taking an assumed-shape array as argument requires an explicit interface; either: a separate module (probably best here), a "contain"-ed internal function, or an explicit interface statement.
You can certainly do the problem by recursion, but you should reduce it first (e.g. by similar row operations to Gauss elimination). Then you end up multiplying the diagonal elements only, and there need be no mention of cofactors.
The following code will do the determinant by recursion, but please note:
(1) it would be far better using an optimised library routine (e.g. Lapack, as suggested by Ian Bush);
(2) it would be far better to use a loop than recursion - there's a real danger of growing memory;
(3) the working will modify matrix A (use a copy if you don't want that);
(4) it's very vulnerable to floating-point round-off error.
Output: