      real function dot(a,b)
      implicit none
      real a(3),b(3)

      dot=a(1)*b(1)+a(2)*b(2)+a(3)*b(3)
      return
      end


C***********************************************************

      subroutine cross(a,b,c)
      implicit none
      real a(3),b(3),c(3)

      c(1)=a(2)*b(3)-a(3)*b(2)
      c(2)=a(3)*b(1)-a(1)*b(3)
      c(3)=a(1)*b(2)-a(2)*b(1)

      return
      end

C**********************************************************

      subroutine MMMULT (a, b, m, n, o, c)

C  Multiplies a matrix by a matrix
C     equation:   C(i,j) = A(i,l) * B(l,j)
C   dimensions:  m x n   m x o    o x n

      implicit none
      integer m, n, o, i, j, l
      real a(m,o), b(o,n), c(m,n)

      do i=1,m
        do j=1,n
          c(i,j)=0.0
        enddo
      enddo
      
      do 110 i = 1, m
        do 120 j = 1, n
          do 130 l= 1, o
            c(i,j) = c(i,j) + a(i,l)*b(l,j)
 130      continue
 120    continue
 110  continue

      return
      end

C**************************************************************

      subroutine MVMULT (amat, vin, m, n, vout)

C  Multiplies a vector by a matrix
C     equation:   VOUT(i) = AMAT(i,j) * VIN(j)
C   dimensions:     m         m x n       n

      implicit none
      integer m, n, i, j
      real amat(m,n), vin(n), vout(m)

      do 10 i = 1, m
        vout(i) = 0.0
 10   continue

      do 110 j = 1, n
        do 120 i = 1, m
          vout(i) = vout(i) + amat(i,j)*vin(j)
 120    continue
 110  continue

      return
      end
      
c_Func===1=========2=========3=========4=========5=========6=========712
	logical function invert(msize, thematrix)				!c_Func
c_Func Description:
c_Func	Matrix inversion routine. Assumes square matrix.
c_Func	Returns true if sucessfull, false if not.
c_Func.................................................................
c	Tanya Riseman,	Aug 18, 1997

	implicit none

c	passed variables
	integer		 msize
	real 		 thematrix(3,3)

c	local variables
        integer		maxerrors
	parameter	(maxerrors = 3)
	double precision akj, hold, pivot
	integer		 ISW(maxerrors)
	integer		 i, j, k, ii, jj
	double precision matrix(maxerrors, maxerrors)

	if (msize .gt. maxerrors) then
	  write (*,*) 'invert: array size too large for ', 
     &		'dimensioned arrays:', msize, '>',  maxerrors
	  invert = .false.
	  return
	endif

	do i = 1, msize
	  do j = 1, msize
	    matrix(i,j) = dble(thematrix(i,j))
	  enddo
	enddo

	invert = .true.
	do k = 1, msize						! 11
C	  FIND MAX OF REMAINDER OF COLUMN K FOR USE AS PIVOT
	  ii = k
	  do I = k, msize					! 21
	    if (abs(matrix(i,k)) .gt. abs(matrix(ii,k))) ii = i
	  enddo							! 21

	  isw(k) = ii
C	  INTERCHANGE ROWS IF NECESSARY
	  if (ii .ne. k) then
	      do j = 1, msize					! 22
		hold = matrix(ii,j)
		matrix(ii,j) = matrix(k,j)
		matrix(k,j) = hold
	      enddo						! 22
	  endif

C	  COMMENCE PIVOTING PROCEDURE
	  pivot = matrix(k,k)
	  if (pivot .eq. 0.0d0) then
	      invert = .false.
	      return
	  endif	      
	  do j = 1, msize					! 23
	      if (.not.(j.eq.k.or.matrix(k,j).eq.0.0d0)) then
C     		DIVIDE ROW K SUCH AS TO GIVE matrix(K,K)=1.0
		akj = matrix(k,j)/pivot
		matrix(k,j) = akj

C     		SUBTRACT ROWS SUCH AS TO ZERO matrix(I,K) FOR I.NE.K
		do i = 1, msize					! 31
		  if (i.ne.k) then
		    matrix(i,j) = matrix(i,j) - matrix(i,k)*akj
		  endif
		enddo						! 31
	      endif
	  enddo							! 23

C     	  INSERT TRANSFORMED COLUMN K FROM VIRTUAL UNIT MATRIX
	  do i=1, msize						! 24
	    if (i.ne.k) then
	      matrix(I,K) = -matrix(I,K)/PIVOT
	    endif
	  enddo							! 24

	  matrix(k,k) = 1.0d0/pivot
C         PIVOTING PROCEDURE COMPLETED 

	enddo							! 11

C     	INTERCHANGE COLUMNS TO MATCH THE INTERCHANGE OF ROWS, IN REVERSE Order
	do j =1, msize						! 13
	  k = msize - j + 1
	  jj = isw(k)
	  if (jj .ne. k) then 
	    do i = 1, msize					! 25
	      hold = matrix(i,jj)
	      matrix(i,jj) = matrix(i,k)
	      matrix(i,k) = hold
	    enddo						! 25
	  endif
	enddo							! 13

	do i = 1, msize
	  do j = 1, msize
	    thematrix(i,j) = sngl(matrix(i,j))
	  enddo
	enddo

	return
	end
