subroutine eulmat (psi,the,phi,mat)
  !---------------------------------------------------------------------
  ! @ public
  !  from Didier Despois 1980
  !  modified 30 november 1984 by Michel Perault
  !  matrice de changement de coordonnees pour une rotation d'angles d'Euler
  !  PSI, THE et PHI, given in radians.
  !  Multiplication of the euclidian coordinates of a vector in the original base
  !  by this matrix gives the coordinates in the rotated base.
  !  For example, the transformation from galactic II coordinates to equatorial
  !  1950 coordinates is obtained with PSI=33., THETA=-62.6, PHI=-282.25 degrees.
  !  The reverse transformation with PSI=282.25, THETA=62.5, PHI=-33 degrees.
  !---------------------------------------------------------------------
  real(kind=8), intent(in)  :: psi       ! Euler angles (radians)
  real(kind=8), intent(in)  :: the       ! Euler angles (radians)
  real(kind=8), intent(in)  :: phi       ! Euler angles (radians)
  real(kind=8), intent(out) :: mat(3,3)  ! transformation matrix
  ! Local
  real(kind=8) :: cpsi,spsi,cthe,sthe,cphi,sphi ! sines and cosines
  real(kind=8) :: x
  !
  !  coefficients de la matrice de transformation
  cpsi=dcos(psi)
  spsi=dsin(psi)
  cthe=dcos(the)
  sthe=dsin(the)
  cphi=dcos(phi)
  sphi=dsin(phi)
  x=spsi*cthe
  mat(1,1)=cpsi*cphi-x*sphi
  mat(2,1)=-cpsi*sphi-x*cphi
  mat(3,1)=spsi*sthe
  x=cpsi*cthe
  mat(1,2)=spsi*cphi+x*sphi
  mat(2,2)=-spsi*sphi+x*cphi
  mat(3,2)=-cpsi*sthe
  mat(1,3)=sthe*sphi
  mat(2,3)=sthe*cphi
  mat(3,3)=cthe
  !
end subroutine eulmat
!
subroutine mulmat (mat1,mat2,mat)
  !---------------------------------------------------------------------
  ! @ public
  !  multiplication of two 3 by 3 matrices
  !  Michel Perault - 1 december 1984.
  !  this routine computes MAT = MAT2 x MAT1
  !  it could be a little faster, but also less compact
  !  take care that MAT ought to be different from MAT1 and MAT2
  !---------------------------------------------------------------------
  real(kind=8), intent(in)  :: mat1(3,3)  !
  real(kind=8), intent(in)  :: mat2(3,3)  !
  real(kind=8), intent(out) :: mat(3,3)   !
  ! Local
  integer(kind=4) :: i,j
  !
  do i=1,3
    do j=1,3
      mat(i,j) = mat2(i,1)*mat1(1,j) + mat2(i,2)*mat1(2,j) + mat2(i,3)*mat1(3,j)
    enddo
  enddo
end subroutine mulmat
!
subroutine matvec (mat1,mat2,mat)
  !---------------------------------------------------------------------
  ! @ public
  !  multiplication of 1 3-D vector by a 3x3 matrix
  !  Michel Perault - 1 december 1984.
  !  this routine computes MAT = MAT2 x MAT1
  !  take care that MAT must be different from MAT1 and MAT2
  !---------------------------------------------------------------------
  real(kind=8), intent(in)  :: mat1(3)    !
  real(kind=8), intent(in)  :: mat2(3,3)  !
  real(kind=8), intent(out) :: mat(3)     !
  !
  mat(1) = mat2(1,1)*mat1(1) + mat2(1,2)*mat1(2) + mat2(1,3)*mat1(3)
  mat(2) = mat2(2,1)*mat1(1) + mat2(2,2)*mat1(2) + mat2(2,3)*mat1(3)
  mat(3) = mat2(3,1)*mat1(1) + mat2(3,2)*mat1(2) + mat2(3,3)*mat1(3)
end subroutine matvec
!
subroutine transp (mat1,mat2)
  !---------------------------------------------------------------------
  ! @ public
  !  Transposee d'une matrice 3x3
  !  20 Septembre 1985 - Michel Perault - POM Version 2.0
  !  Appel : call TRANSP (MAT1,MAT2)  result in MAT2 = transp (MAT1)
  !---------------------------------------------------------------------
  real(kind=8), intent(in)  :: mat1(9)  !
  real(kind=8), intent(out) :: mat2(9)  !
  !
  mat2(1)=mat1(1)
  mat2(2)=mat1(4)
  mat2(3)=mat1(7)
  mat2(4)=mat1(2)
  mat2(5)=mat1(5)
  mat2(6)=mat1(8)
  mat2(7)=mat1(3)
  mat2(8)=mat1(6)
  mat2(9)=mat1(9)
  !
end subroutine transp
!
subroutine matinv3(a,b)
  !---------------------------------------------------------------------
  ! @ public
  ! Performs a direct calculation of the inverse of a 3x3 matrix.
  !---------------------------------------------------------------------
  real(kind=8), intent(in)  :: A(3,3)  ! Matrix
  real(kind=8), intent(out) :: B(3,3)  ! Inverse matrix
  ! Local
  real(kind=8) :: detinv
  !
  ! Calculate the determinant of the matrix
  detinv = A(1,1)*A(2,2)*A(3,3) - A(1,1)*A(2,3)*A(3,2)  &
         - A(1,2)*A(2,1)*A(3,3) + A(1,2)*A(2,3)*A(3,1)  &
         + A(1,3)*A(2,1)*A(3,2) - A(1,3)*A(2,2)*A(3,1)
  !
  ! Inverse determinant of the matrix
  detinv = 1.d0/detinv
  !
  ! Calculate the inverse of the matrix
  B(1,1) = +detinv * (A(2,2)*A(3,3) - A(2,3)*A(3,2))
  B(2,1) = -detinv * (A(2,1)*A(3,3) - A(2,3)*A(3,1))
  B(3,1) = +detinv * (A(2,1)*A(3,2) - A(2,2)*A(3,1))
  B(1,2) = -detinv * (A(1,2)*A(3,3) - A(1,3)*A(3,2))
  B(2,2) = +detinv * (A(1,1)*A(3,3) - A(1,3)*A(3,1))
  B(3,2) = -detinv * (A(1,1)*A(3,2) - A(1,2)*A(3,1))
  B(1,3) = +detinv * (A(1,2)*A(2,3) - A(1,3)*A(2,2))
  B(2,3) = -detinv * (A(1,1)*A(2,3) - A(1,3)*A(2,1))
  B(3,3) = +detinv * (A(1,1)*A(2,2) - A(1,2)*A(2,1))
  !
end subroutine matinv3
