matrix_module.f90 Source File


This file depends on

sourcefile~~matrix_module.f90~~EfferentGraph sourcefile~matrix_module.f90 matrix_module.f90 sourcefile~kind_module.f90 kind_module.F90 sourcefile~matrix_module.f90->sourcefile~kind_module.f90 sourcefile~numbers_module.f90 numbers_module.f90 sourcefile~matrix_module.f90->sourcefile~numbers_module.f90 sourcefile~numbers_module.f90->sourcefile~kind_module.f90

Files dependent on this one

sourcefile~~matrix_module.f90~~AfferentGraph sourcefile~matrix_module.f90 matrix_module.f90 sourcefile~fortran_astrodynamics_toolkit.f90 fortran_astrodynamics_toolkit.f90 sourcefile~fortran_astrodynamics_toolkit.f90->sourcefile~matrix_module.f90 sourcefile~halo_orbit_module.f90 halo_orbit_module.f90 sourcefile~fortran_astrodynamics_toolkit.f90->sourcefile~halo_orbit_module.f90 sourcefile~halo_orbit_module.f90->sourcefile~matrix_module.f90

Source Code

!*****************************************************************************************
!> author: Jacob Williams
!
!  Various matrix routines

    module matrix_module

    use kind_module,    only: wp
    use numbers_module, only: zero,one

    implicit none

    private

    public :: print_matrix
    public :: matrix_trace
    public :: matrix_determinant
    public :: matrix_cofactor

    contains
!*****************************************************************************************

!*******************************************************************************
!>
!  Matrix determinant of an \( n \times n \) matrix (recursive formulation).
!
!### Reference
!  * https://rosettacode.org/wiki/Matrix_arithmetic#Fortran

    pure recursive function matrix_determinant(n,a) result(det)

    implicit none

    integer,intent(in)                  :: n   !! size of `a` matrix
    real(wp),dimension(n,n),intent(in)  :: a   !! the matrix
    real(wp)                            :: det !! the determinant of `a` matrix

    integer :: i   !! counter
    integer :: sgn !! `(-1)**(i-1)` term
    real(wp), dimension(n-1, n-1) :: b  !! temp matrix

    if (n == 1) then
        det = a(1,1)
    else
        det = zero
        sgn = 1
        do i = 1, n
            b(:, :(i-1)) = a(2:, :i-1)
            b(:, i:) = a(2:, i+1:)
            det = det + sgn * a(1, i) * matrix_determinant(n-1,b)
            sgn = -sgn
        end do
    end if

    end function matrix_determinant
!*******************************************************************************

!*******************************************************************************
!>
!  Compute the cofactors matrix (the transpose of the adjugate matrix).
!
!### References
!  * https://warwick.ac.uk/fac/sci/physics/research/condensedmatt/imr_cdt/students/david_goodwin/teaching/cis008-2/determinant_algorithm_cis008-2_lec_21.pdf
!  * https://groups.google.com/forum/#!topic/comp.lang.fortran/Y6jCv-QdDhc

    pure function matrix_cofactor (n,a) result(c)

    implicit none

    integer,intent(in)                  :: n   !! size of `a` matrix
    real(wp),dimension(n,n),intent(in)  :: a   !! the matrix
    real(wp),dimension(n,n)             :: c   !! the cofactors of `a` matrix

    integer :: i !! counter
    integer :: j !! counter
    real(wp),dimension(n-1,n-1) :: c_temp  !! temp matrix
    logical,dimension(n,n) :: m  !! mask for row/col removal

    if (n==1) then
        c(1,1) = one
    else
        do i=1,n
            do j=1,n
                ! remove the ith row and jth col from a:
                m = .true.
                m(:,j) = .false.
                m(i,:) = .false.
                c_temp = reshape(pack(a, m),[n-1,n-1])
                c(i,j) = ( (-1)**(i+j) ) * matrix_determinant(n-1,c_temp)
            end do
        end do
    end if

    end function matrix_cofactor
!*******************************************************************************

!*****************************************************************************************
!>
!  Print a matrix to the console.

    subroutine print_matrix(mat,unit)

    use iso_fortran_env, only: output_unit

    implicit none

    real(wp),dimension(:,:),intent(in) :: mat !! the matrix to print
    integer,intent(in),optional :: unit  !! unit number (assumed to be an open file).
                                         !! if not present, then the standard output is used.

    integer :: i      !! counter
    integer :: n      !! number of rows in the matrix
    integer :: iunit  !! the file unit to print to
    integer :: istat  !! `iostat` flag for write statement

    character(len=*),parameter :: fmt = 'E26.16'  !! real number format statement

    if (present(unit)) then
        iunit = unit
    else
        iunit = output_unit
    end if

    n = size(mat,1)

    do i=1,n
        write(iunit,fmt='(*('//fmt//',1X))',iostat=istat) mat(i,:)
    end do

    end subroutine print_matrix
!*****************************************************************************************

!*****************************************************************************************
!>
!  Compute the matrix trace (sum of the diagonal elements).

    pure function matrix_trace(n,mat) result(trace)

    implicit none

    integer,intent(in)                 :: n     !! size of the matrix
    real(wp),dimension(n,n),intent(in) :: mat   !! the matrix
    real(wp)                           :: trace !! the matrix trace

    integer :: i !! counter

    trace = zero
    do i = 1, n
        trace = trace + mat(i,i)
    end do

    end function matrix_trace
!*****************************************************************************************

!*****************************************************************************************
    end module matrix_module
!*****************************************************************************************