Here’s a snippet I created for a Stack Exchange reply. The purpose is to form the product L L^T for a lower-triangular matrix stored in the packed storage format.
module matmult
implicit none
public
contains
! SLLTPM performs the update
!
! B := A*A**T
!
! where B is a n by n symmetric matrix, and A is an n by n
! lower-triangular matrix. Packed storage is used for both A and B.
subroutine slltpm(n,a,b)
implicit none
integer, intent(in) :: n
real, intent(in) :: a(*)
real, intent(out) :: b(*)
integer :: i, j, k
do j = 1, n
b(id(j,j):id(n,j)) = 0
do k = 1, j
!$omp simd
do i = j, n
b(id(i,j)) = b(id(i,j)) + a(id(i,k))*a(id(j,k))
end do
end do
end do
contains
integer function id(i,j)
integer, intent(in) :: i, j
id = i + (2*n-j)*(j-1)/2
end function
end subroutine
end module
program main
use matmult, only: slltpm
implicit none
integer, parameter :: n = 4
real :: ad(n,n), bd(n,n)
integer, parameter :: np = n*(n+1)/2
real :: a(np), b(np)
! A := L
a = [real :: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
! B := AA^T
call slltpm(n,a,b)
call print_packed(n,a,"a (packed)")
call print_packed(n,b,"b (packed)")
call unpack(n,a,ad)
bd = matmul(ad,transpose(ad))
call print_dense(n,ad,"a (dense)")
call print_dense(n,bd,"b (dense)")
contains
subroutine unpack(n,a,b)
integer, intent(in) :: n
real, intent(in) :: a(*)
real, intent(out) :: b(n,n)
integer :: id, i, j
id(i,j) = i + (2*n-j)*(j-1)/2
b = 0
do j = 1, n
do i = j, n
b(i,j) = a(id(i,j))
end do
end do
end subroutine
subroutine print_packed(n,a,str)
integer, intent(in) :: n
real, intent(in) :: a(*)
character(*), intent(in) :: str
integer :: id, i, j
id(i,j) = i + (2*n-j)*(j-1)/2
print *, str
do i = 1, n
print *, a( [(id(i,j), j = 1, i)] )
end do
end subroutine
subroutine print_dense(n,a,str)
integer, intent(in) :: n
real, intent(in) :: a(n,n)
character(*), intent(in) :: str
integer :: i, j
print *, str
do i = 1, n
print *, (a(i,j), j = 1, n)
end do
end subroutine
end program