      SUBROUTINE ROT2(A,THETA,RM)
C***********************************************************************
C This subroutine finds the (3 by 3) rotation matrix for the
C given axis (vector) --- a and the rotation angle --- theta.
C On input:
C a(3)    --- axis of rotation  (vector, any length)
C theta   --- angle of rotation (in radians) around vector a
C On output:
C rm(3,3) --- rotation matrix such that new vector v2 is obtained
C             from the old vector v1 by the transformation:
C             v2 = rm \dot v1
C (If more rotations are needed: generate matrices rm with the
C help of this subroutine and (matrix) multiply them before
C performing v2 = rm \dot v1.)
C
C Reference:
C Leubner, C., 1977,  Coordinate-free  rotation operator,
C Am. J. Phys. 47, 727---729.
C
C History:
C Written by PJF, May 1989, for use in the rotation-averaged
C DDA calculations.
C
C Copyright (C) 1993, B.T. Draine and P.J. Flatau
C This code is covered by the GNU General Public License.
C***********************************************************************
C pre-calculate some stuff:
C     .. Scalar Arguments ..
      REAL THETA
C     ..
C     .. Array Arguments ..
      REAL A(3), RM(3,3)
C     ..
C     .. Local Scalars ..
      REAL ANORM, CT, ST
      INTEGER I, J
C     ..
C     .. Local Arrays ..
      REAL AHAT(3)
C     ..
C     .. External Subroutines ..
      EXTERNAL XNORM3
C     ..
C     .. Intrinsic Functions ..
      INTRINSIC COS, SIN
C     ..
      CT = COS(THETA)
      ST = SIN(THETA)
      CALL XNORM3(A,ANORM)
      AHAT(1) = A(1)/ANORM
      AHAT(2) = A(2)/ANORM
      AHAT(3) = A(3)/ANORM
C  cos(\theta) {\bf 1}  term:
      RM(1,1) = CT
      RM(2,2) = CT
      RM(3,3) = CT
C Skew-term  a \times {\bf 1}:
      RM(1,2) = -ST*AHAT(3)
      RM(1,3) = ST*AHAT(2)
      RM(2,1) = ST*AHAT(3)
      RM(2,3) = -ST*AHAT(1)
      RM(3,1) = -ST*AHAT(2)
      RM(3,2) = ST*AHAT(1)
C aa-dyadic (outer-product):
      DO 20 I = 1, 3
          DO 10 J = 1, 3
              RM(I,J) = RM(I,J) + (1.-CT)*AHAT(J)*AHAT(I)
   10     CONTINUE
   20 CONTINUE
      RETURN
      END
      SUBROUTINE XNORM3(A,XN)
C auxiliary for "rotation" routines
C
C Copyright (C) 1993, B.T. Draine and P.J. Flatau
C This code is covered by the GNU General Public License.
C***********************************************************************
C     .. Scalar Arguments ..
      REAL XN
C     ..
C     .. Array Arguments ..
      REAL A(3)
C     ..
C     .. Intrinsic Functions ..
      INTRINSIC SQRT
C     ..
      XN = SQRT(A(1)**2+A(2)**2+A(3)**2)
      RETURN
      END
      SUBROUTINE MULT3(A,B,C)
C***********************************************************************
C Purpose:
C Given:  A(I,J)= 3x3 matrix
C         B(J,K)= 3x3 matrix
C Returns:C(I,K)= matrix product of A and B
C This is auxilary for "rotation" routines
C
C Copyright (C) 1993, B.T. Draine and P.J. Flatau
C This code is covered by the GNU General Public License.
***********************************************************************
C Arguments:
      REAL A(3,3),B(3,3),C(3,3)
C Local variables:
      REAL S
      INTEGER I,J,K
C
      DO 30 J = 1, 3
          DO 20 I = 1, 3
              S = 0.
              DO 10 K = 1, 3
                  S = S + A(I,K)*B(K,J)
   10         CONTINUE
              C(I,J) = S
   20     CONTINUE
   30 CONTINUE
      RETURN
      END
      SUBROUTINE PROD3(RM,VIN,VOUT)
C Given:  RM(I,J)=3x3 matrix
C         VIN(J)=3-vector
C Returns:VOUT(I)=RM*VIN
C 
C Auxiliary for "rotation" routines
C
C Copyright (C) 1993, B.T. Draine and P.J. Flatau
C This code is covered by the GNU General Public License.
C***********************************************************************
C Arguments;
      REAL RM(3,3), VIN(3), VOUT(3)
C Local variables:
      INTEGER I,J
C
      DO 20 I = 1, 3
         VOUT(I) = 0.
         DO 10 J = 1, 3
            VOUT(I) = VOUT(I) + RM(I,J)*VIN(J)
   10    CONTINUE
   20 CONTINUE
      RETURN
      END
      SUBROUTINE PROD3C(RM,CVIN,CVOUT)
C Arguments:
      REAL RM(3,3)
      COMPLEX CVIN(3),CVOUT(3)
C Local variables:
      INTEGER I,J
C Given:
C       RM=3x3 rotation matrix
C       CVIN=complex 3-vector
C Computes:
C       CVOUT=RM \dot CVIN
C
C Copyright (C) 1993, B.T. Draine and P.J. Flatau
C This code is covered by the GNU General Public License.
C***********************************************************************
      DO 20 I=1,3
         CVOUT(I)=(0.,0.)
         DO 10 J=1,3
            CVOUT(I)=CVOUT(I)+RM(I,J)*CVIN(J)
 10      CONTINUE
 20   CONTINUE
      RETURN
      END
      SUBROUTINE PROD3V(RM,VIN,VOUT,NV,NVMAX)
C Arguments:
      INTEGER NV,NVMAX
      REAL RM(3,3),VIN(3,NVMAX),VOUT(3,NVMAX)
C Local variables:
      INTEGER I,J,N
C Given:
C       RM = 3x3 rotation matrix
C       VIN = NV 3-vectors
C Computes:
C       VOUT=RM \dot VIN for each of the NV 3-vectors
C
C Copyright (C) 1993,1996 B.T. Draine and P.J. Flatau
C History
C 96.08.09 (BTD) trivial modification to remove obsolescent construct.
C end history
C This code is covered by the GNU General Public License.
C***********************************************************************
      DO 20 I=1,3
         DO 10 N=1,NV
            VOUT(I,N)=0.
 10      CONTINUE
 20   CONTINUE
C
      DO 50 I=1,3
         DO 40 J=1,3
            DO 30 N=1,NV
               VOUT(I,N)=VOUT(I,N)+RM(I,J)*VIN(J,N)
 30         CONTINUE
 40      CONTINUE
 50   CONTINUE
      RETURN
      END

