      SUBROUTINE DAXPY( N, DA, DX, INCX, DY, INCY )
*
*     constant times a vector plus a vector.
*     uses unrolled loops for increments equal to one.
*     jack dongarra, linpack, 3/11/78.
*
*     .. Scalar Arguments ..
      INTEGER           INCX, INCY, N
      DOUBLE PRECISION  DA
*     ..
*     .. Array Arguments ..
      DOUBLE PRECISION  DX( 1 ), DY( 1 )
*     ..
*     .. Local Scalars ..
      INTEGER           I, IX, IY, M, MP1
*     ..
*     .. Intrinsic Functions ..
      INTRINSIC         MOD
*     ..
*     .. Executable Statements ..
*
      IF( N.LE.0 )
     $   RETURN
      IF( DA.EQ.0.0D0 )
     $   RETURN
      IF( INCX.EQ.1 .AND. INCY.EQ.1 )
     $   GO TO 20
*
*        code for unequal increments or equal increments
*          not equal to 1
*
      IX = 1
      IY = 1
      IF( INCX.LT.0 )
     $   IX = ( -N+1 )*INCX + 1
      IF( INCY.LT.0 )
     $   IY = ( -N+1 )*INCY + 1
      DO 10 I = 1, N
         DY( IY ) = DY( IY ) + DA*DX( IX )
         IX = IX + INCX
         IY = IY + INCY
   10 CONTINUE
      RETURN
*
*        code for both increments equal to 1
*
*
*        clean-up loop
*
   20 M = MOD( N, 4 )
      IF( M.EQ.0 )
     $   GO TO 40
      DO 30 I = 1, M
         DY( I ) = DY( I ) + DA*DX( I )
   30 CONTINUE
      IF( N.LT.4 )
     $   RETURN
   40 MP1 = M + 1
      DO 50 I = MP1, N, 4
         DY( I ) = DY( I ) + DA*DX( I )
         DY( I+1 ) = DY( I+1 ) + DA*DX( I+1 )
         DY( I+2 ) = DY( I+2 ) + DA*DX( I+2 )
         DY( I+3 ) = DY( I+3 ) + DA*DX( I+3 )
   50 CONTINUE
      RETURN
      END
      SUBROUTINE DCOPY( N, DX, INCX, DY, INCY )
*
*     copies a vector, x, to a vector, y.
*     uses unrolled loops for increments equal to one.
*     jack dongarra, linpack, 3/11/78.
*
*     .. Scalar Arguments ..
      INTEGER           INCX, INCY, N
*     ..
*     .. Array Arguments ..
      DOUBLE PRECISION  DX( 1 ), DY( 1 )
*     ..
*     .. Local Scalars ..
      INTEGER           I, IX, IY, M, MP1
*     ..
*     .. Intrinsic Functions ..
      INTRINSIC         MOD
*     ..
*     .. Executable Statements ..
*
      IF( N.LE.0 )
     $   RETURN
      IF( INCX.EQ.1 .AND. INCY.EQ.1 )
     $   GO TO 20
*
*        code for unequal increments or equal increments
*          not equal to 1
*
      IX = 1
      IY = 1
      IF( INCX.LT.0 )
     $   IX = ( -N+1 )*INCX + 1
      IF( INCY.LT.0 )
     $   IY = ( -N+1 )*INCY + 1
      DO 10 I = 1, N
         DY( IY ) = DX( IX )
         IX = IX + INCX
         IY = IY + INCY
   10 CONTINUE
      RETURN
*
*        code for both increments equal to 1
*
*
*        clean-up loop
*
   20 M = MOD( N, 7 )
      IF( M.EQ.0 )
     $   GO TO 40
      DO 30 I = 1, M
         DY( I ) = DX( I )
   30 CONTINUE
      IF( N.LT.7 )
     $   RETURN
   40 MP1 = M + 1
      DO 50 I = MP1, N, 7
         DY( I ) = DX( I )
         DY( I+1 ) = DX( I+1 )
         DY( I+2 ) = DX( I+2 )
         DY( I+3 ) = DX( I+3 )
         DY( I+4 ) = DX( I+4 )
         DY( I+5 ) = DX( I+5 )
         DY( I+6 ) = DX( I+6 )
   50 CONTINUE
      RETURN
      END
      DOUBLE PRECISION FUNCTION DDOT( N, DX, INCX, DY, INCY )
*
*     forms the dot product of two vectors.
*     uses unrolled loops for increments equal to one.
*     jack dongarra, linpack, 3/11/78.
*
*     .. Scalar Arguments ..
      INTEGER                         INCX, INCY, N
*     ..
*     .. Array Arguments ..
      DOUBLE PRECISION                DX( 1 ), DY( 1 )
*     ..
*     .. Local Scalars ..
      INTEGER                         I, IX, IY, M, MP1
      DOUBLE PRECISION                DTEMP
*     ..
*     .. Intrinsic Functions ..
      INTRINSIC                       MOD
*     ..
*     .. Executable Statements ..
*
      DDOT = 0.0D0
      DTEMP = 0.0D0
      IF( N.LE.0 )
     $   RETURN
      IF( INCX.EQ.1 .AND. INCY.EQ.1 )
     $   GO TO 20
*
*        code for unequal increments or equal increments
*          not equal to 1
*
      IX = 1
      IY = 1
      IF( INCX.LT.0 )
     $   IX = ( -N+1 )*INCX + 1
      IF( INCY.LT.0 )
     $   IY = ( -N+1 )*INCY + 1
      DO 10 I = 1, N
         DTEMP = DTEMP + DX( IX )*DY( IY )
         IX = IX + INCX
         IY = IY + INCY
   10 CONTINUE
      DDOT = DTEMP
      RETURN
*
*        code for both increments equal to 1
*
*
*        clean-up loop
*
   20 M = MOD( N, 5 )
      IF( M.EQ.0 )
     $   GO TO 40
      DO 30 I = 1, M
         DTEMP = DTEMP + DX( I )*DY( I )
   30 CONTINUE
      IF( N.LT.5 )
     $   GO TO 60
   40 MP1 = M + 1
      DO 50 I = MP1, N, 5
         DTEMP = DTEMP + DX( I )*DY( I ) + DX( I+1 )*DY( I+1 ) +
     $           DX( I+2 )*DY( I+2 ) + DX( I+3 )*DY( I+3 ) +
     $           DX( I+4 )*DY( I+4 )
   50 CONTINUE
   60 DDOT = DTEMP
      RETURN
      END
      DOUBLE PRECISION FUNCTION DNRM2( N, DX, INCX )
*
*     euclidean norm of the n-vector stored in dx() with storage
*     increment incx .
*     if    n .le. 0 return with result = 0.
*     if n .ge. 1 then incx must be .ge. 1
*
*           c.l.lawson, 1978 jan 08
*
*     four phase method     using two built-in constants that are
*     hopefully applicable to all machines.
*         cutlo = maximum of  dsqrt(u/eps)  over all known machines.
*         cuthi = minimum of  dsqrt(v)      over all known machines.
*     where
*         eps = smallest no. such that eps + 1. .gt. 1.
*         u   = smallest positive no.   (underflow limit)
*         v   = largest  no.            (overflow  limit)
*
*     brief outline of algorithm..
*
*     phase 1    scans zero components.
*     move to phase 2 when a component is nonzero and .le. cutlo
*     move to phase 3 when a component is .gt. cutlo
*     move to phase 4 when a component is .ge. cuthi/m
*     where m = n for x() real and m = 2*n for complex.
*
*     values for cutlo and cuthi..
*     from the environmental parameters listed in the imsl converter
*     document the limiting values are as follows..
*     cutlo, s.p.   u/eps = 2**(-102) for  honeywell.  close seconds are
*                   univac and dec at 2**(-103)
*                   thus cutlo = 2**(-51) = 4.44089e-16
*     cuthi, s.p.   v = 2**127 for univac, honeywell, and dec.
*                   thus cuthi = 2**(63.5) = 1.30438e19
*     cutlo, d.p.   u/eps = 2**(-67) for honeywell and dec.
*                   thus cutlo = 2**(-33.5) = 8.23181d-11
*     cuthi, d.p.   same as s.p.  cuthi = 1.30438d19
*     data cutlo, cuthi / 8.232d-11,  1.304d19 /
*     data cutlo, cuthi / 4.441e-16,  1.304e19 /
*
*     .. Scalar Arguments ..
      INTEGER                          INCX, N
*     ..
*     .. Array Arguments ..
      DOUBLE PRECISION                 DX( 1 )
*     ..
*     .. Local Scalars ..
      INTEGER                          I, IX, J, NEXT, NN
      DOUBLE PRECISION                 CUTHI, CUTLO, HITEST, ONE, SUM,
     $                                 XMAX, ZERO
*     ..
*     .. Intrinsic Functions ..
      INTRINSIC                        DABS, DSQRT, FLOAT
*     ..
*     .. Data statements ..
      DATA                             ZERO, ONE / 0.0D0, 1.0D0 /
      DATA                             CUTLO, CUTHI / 8.232D-11,
     $                                 1.304D19 /
*     ..
*     .. Executable Statements ..
*
      IF( N.GT.0 )
     $   GO TO 10
      DNRM2 = ZERO
      GO TO 140
*
   10 ASSIGN 30 TO NEXT
      SUM = ZERO
*
*        begin main loop
*
      IX = 1
      IF( INCX.LT.0 )
     $   IX = 1 - ( N-1 )*INCX
      I = IX
      NN = IX + ( N-1 )*INCX
   20 GO TO NEXT( 30, 40, 70, 80 )
   30 IF( DABS( DX( I ) ).GT.CUTLO )
     $   GO TO 110
      ASSIGN 40 TO NEXT
      XMAX = ZERO
*
*        phase 1.  sum is zero
*
   40 IF( DX( I ).EQ.ZERO )
     $   GO TO 130
      IF( DABS( DX( I ) ).GT.CUTLO )
     $   GO TO 110
*
*        prepare for phase 2.
*
      ASSIGN 70 TO NEXT
      GO TO 60
*
*        prepare for phase 4.
*
   50 I = J
      ASSIGN 80 TO NEXT
      SUM = ( SUM / DX( I ) ) / DX( I )
   60 XMAX = DABS( DX( I ) )
      GO TO 90
*
*        phase 2.  sum is small.
*                  scale to avoid destructive underflow.
*
   70 IF( DABS( DX( I ) ).GT.CUTLO )
     $   GO TO 100
*
*        common code for phases 2 and 4.
*        in phase 4 sum is large.  scale to avoid overflow.
*
   80 IF( DABS( DX( I ) ).LE.XMAX )
     $   GO TO 90
      SUM = ONE + SUM*( XMAX / DX( I ) )**2
      XMAX = DABS( DX( I ) )
      GO TO 130
*
   90 SUM = SUM + ( DX( I ) / XMAX )**2
      GO TO 130
*
*        prepare for phase 3.
*
  100 SUM = ( SUM*XMAX )*XMAX
*
*        for real or d.p. set hitest = cuthi/n
*        for complex      set hitest = cuthi/(2*n)
*
  110 HITEST = CUTHI / FLOAT( N )
*
*        phase 3.  sum is mid-range.  no scaling.
*
      DO 120 J = I, NN, INCX
         IF( DABS( DX( J ) ).GE.HITEST )
     $      GO TO 50
         SUM = SUM + DX( J )**2
  120 CONTINUE
      DNRM2 = DSQRT( SUM )
      GO TO 140
*
  130 CONTINUE
      IF( I.NE.NN ) THEN
         I = I + INCX
         GO TO 20
      ENDIF
*
*        end of main loop.
*
*        compute square root and adjust for scaling.
*
      DNRM2 = XMAX*DSQRT( SUM )
  140 CONTINUE
      RETURN
      END
      SUBROUTINE DROT( N, DX, INCX, DY, INCY, C, S )
*
*     applies a plane rotation.
*     jack dongarra, linpack, 3/11/78.
*
*     .. Scalar Arguments ..
      INTEGER          INCX, INCY, N
      DOUBLE PRECISION C, S
*     ..
*     .. Array Arguments ..
      DOUBLE PRECISION DX( 1 ), DY( 1 )
*     ..
*     .. Local Scalars ..
      INTEGER          I, IX, IY
      DOUBLE PRECISION DTEMP
*     ..
*     .. Executable Statements ..
*
      IF( N.LE.0 )
     $   RETURN
      IF( INCX.EQ.1 .AND. INCY.EQ.1 )
     $   GO TO 20
*
*        code for unequal increments or equal increments
*          not equal to 1
*
      IX = 1
      IY = 1
      IF( INCX.LT.0 )
     $   IX = ( -N+1 )*INCX + 1
      IF( INCY.LT.0 )
     $   IY = ( -N+1 )*INCY + 1
      DO 10 I = 1, N
         DTEMP = C*DX( IX ) + S*DY( IY )
         DY( IY ) = C*DY( IY ) - S*DX( IX )
         DX( IX ) = DTEMP
         IX = IX + INCX
         IY = IY + INCY
   10 CONTINUE
      RETURN
*
*        code for both increments equal to 1
*
   20 DO 30 I = 1, N
         DTEMP = C*DX( I ) + S*DY( I )
         DY( I ) = C*DY( I ) - S*DX( I )
         DX( I ) = DTEMP
   30 CONTINUE
      RETURN
      END
      SUBROUTINE DROTG( DA, DB, C, S )
*
*     construct givens plane rotation.
*     jack dongarra, linpack, 3/11/78.
*                    modified 9/27/86.
*
*     .. Scalar Arguments ..
      DOUBLE PRECISION  C, DA, DB, S
*     ..
*     .. Local Scalars ..
      DOUBLE PRECISION  R, ROE, SCALE, Z
*     ..
*     .. Intrinsic Functions ..
      INTRINSIC         DABS, DSIGN, DSQRT
*     ..
*     .. Executable Statements ..
*
      ROE = DB
      IF( DABS( DA ).GT.DABS( DB ) )
     $   ROE = DA
      SCALE = DABS( DA ) + DABS( DB )
      IF( SCALE.NE.0.0D0 )
     $   GO TO 10
      C = 1.0D0
      S = 0.0D0
      R = 0.0D0
      GO TO 20
   10 R = SCALE*DSQRT( ( DA / SCALE )**2+( DB / SCALE )**2 )
      R = DSIGN( 1.0D0, ROE )*R
      C = DA / R
      S = DB / R
   20 Z = S
      IF( DABS( C ).GT.0.0D0 .AND. DABS( C ).LE.S )
     $   Z = 1.0D0 / C
      DA = R
      DB = Z
      RETURN
      END
      SUBROUTINE DSCAL( N, DA, DX, INCX )
*
*     scales a vector by a constant.
*     uses unrolled loops for increment equal to one.
*     jack dongarra, linpack, 3/11/78.
*
*     .. Scalar Arguments ..
      INTEGER           INCX, N
      DOUBLE PRECISION  DA
*     ..
*     .. Array Arguments ..
      DOUBLE PRECISION  DX( 1 )
*     ..
*     .. Local Scalars ..
      INTEGER           I, IX, M, MP1, NINCX
*     ..
*     .. Intrinsic Functions ..
      INTRINSIC         MOD
*     ..
*     .. Executable Statements ..
*
      IF( N.LE.0 )
     $   RETURN
      IF( INCX.EQ.1 )
     $   GO TO 20
*
*        code for increment not equal to 1
*
      IX = 1
      IF( INCX.LT.0 )
     $   IX = 1 - ( N-1 )*INCX
      NINCX = IX + ( N-1 )*INCX
      DO 10 I = IX, NINCX, INCX
         DX( I ) = DA*DX( I )
   10 CONTINUE
      RETURN
*
*        code for increment equal to 1
*
*
*        clean-up loop
*
   20 M = MOD( N, 5 )
      IF( M.EQ.0 )
     $   GO TO 40
      DO 30 I = 1, M
         DX( I ) = DA*DX( I )
   30 CONTINUE
      IF( N.LT.5 )
     $   RETURN
   40 MP1 = M + 1
      DO 50 I = MP1, N, 5
         DX( I ) = DA*DX( I )
         DX( I+1 ) = DA*DX( I+1 )
         DX( I+2 ) = DA*DX( I+2 )
         DX( I+3 ) = DA*DX( I+3 )
         DX( I+4 ) = DA*DX( I+4 )
   50 CONTINUE
      RETURN
      END
      SUBROUTINE DSWAP( N, DX, INCX, DY, INCY )
*
*     interchanges two vectors.
*     uses unrolled loops for increments equal one.
*     jack dongarra, linpack, 3/11/78.
*
*     .. Scalar Arguments ..
      INTEGER           INCX, INCY, N
*     ..
*     .. Array Arguments ..
      DOUBLE PRECISION  DX( 1 ), DY( 1 )
*     ..
*     .. Local Scalars ..
      INTEGER           I, IX, IY, M, MP1
      DOUBLE PRECISION  DTEMP
*     ..
*     .. Intrinsic Functions ..
      INTRINSIC         MOD
*     ..
*     .. Executable Statements ..
*
      IF( N.LE.0 )
     $   RETURN
      IF( INCX.EQ.1 .AND. INCY.EQ.1 )
     $   GO TO 20
*
*        code for unequal increments or equal increments
*          not equal to 1
*
      IX = 1
      IY = 1
      IF( INCX.LT.0 )
     $   IX = ( -N+1 )*INCX + 1
      IF( INCY.LT.0 )
     $   IY = ( -N+1 )*INCY + 1
      DO 10 I = 1, N
         DTEMP = DX( IX )
         DX( IX ) = DY( IY )
         DY( IY ) = DTEMP
         IX = IX + INCX
         IY = IY + INCY
   10 CONTINUE
      RETURN
*
*        code for both increments equal to 1
*
*
*        clean-up loop
*
   20 M = MOD( N, 3 )
      IF( M.EQ.0 )
     $   GO TO 40
      DO 30 I = 1, M
         DTEMP = DX( I )
         DX( I ) = DY( I )
         DY( I ) = DTEMP
   30 CONTINUE
      IF( N.LT.3 )
     $   RETURN
   40 MP1 = M + 1
      DO 50 I = MP1, N, 3
         DTEMP = DX( I )
         DX( I ) = DY( I )
         DY( I ) = DTEMP
         DTEMP = DX( I+1 )
         DX( I+1 ) = DY( I+1 )
         DY( I+1 ) = DTEMP
         DTEMP = DX( I+2 )
         DX( I+2 ) = DY( I+2 )
         DY( I+2 ) = DTEMP
   50 CONTINUE
      RETURN
      END
      DOUBLE PRECISION FUNCTION DASUM(N,DX,INCX)
C
C     TAKES THE SUM OF THE ABSOLUTE VALUES.
C     JACK DONGARRA, LINPACK, 3/11/78.
C
      DOUBLE PRECISION DX(1),DTEMP
      INTEGER I,INCX,M,MP1,N,NINCX
C
      DASUM = 0.0D0
      DTEMP = 0.0D0
      IF(N.LE.0)RETURN
      IF(INCX.EQ.1)GO TO 20
C
C        CODE FOR INCREMENT NOT EQUAL TO 1
C
      NINCX = N*INCX
      DO 10 I = 1,NINCX,INCX
        DTEMP = DTEMP + DABS(DX(I))
   10 CONTINUE
      DASUM = DTEMP
      RETURN
C
C        CODE FOR INCREMENT EQUAL TO 1
C
C
C        CLEAN-UP LOOP
C
   20 M = MOD(N,6)
      IF( M .EQ. 0 ) GO TO 40
      DO 30 I = 1,M
        DTEMP = DTEMP + DABS(DX(I))
   30 CONTINUE
      IF( N .LT. 6 ) GO TO 60
   40 MP1 = M + 1
      DO 50 I = MP1,N,6
        DTEMP = DTEMP + DABS(DX(I)) + DABS(DX(I + 1)) + DABS(DX(I + 2))
     *  + DABS(DX(I + 3)) + DABS(DX(I + 4)) + DABS(DX(I + 5))
   50 CONTINUE
   60 DASUM = DTEMP
      RETURN
      END

