*  =====================================================================
*
*  Purpose
*  =======
*
*  SLARF applies a real elementary reflector H to a real m by n matrix
*  C, from either the left or the right. H is represented in the form
*
*        H = I - tau * v * v**T
*
*  where tau is a real scalar and v is a real vector.
*
*  If tau = 0, then H is taken to be the unit matrix.
*
*  Arguments
*  =========
*
*  SIDE    (input) CHARACTER*1
*          = 'L': form  H * C
*          = 'R': form  C * H
*
*  M       (input) INTEGER
*          The number of rows of the matrix C.
*
*  N       (input) INTEGER
*          The number of columns of the matrix C.
*
*  V       (input) REAL array, dimension
*                     (1 + (M-1)*abs(INCV)) if SIDE = 'L'
*                  or (1 + (N-1)*abs(INCV)) if SIDE = 'R'
*          The vector v in the representation of H. V is not used if
*          TAU = 0.
*
*  INCV    (input) INTEGER
*          The increment between elements of v. INCV <> 0.
*
*  TAU     (input) REAL
*          The value tau in the representation of H.
*
*  C       (input/output) REAL array, dimension (LDC,N)
*          On entry, the m by n matrix C.
*          On exit, C is overwritten by the matrix H * C if SIDE = 'L',
*          or C * H if SIDE = 'R'.
*
*  LDC     (input) INTEGER
*          The leading dimension of the array C. LDC >= max(1,M).
*
*  =====================================================================
*
      SUBROUTINE SLARF(SIDE, M, N, V, INCV, TAU, C, LDC)
      IMPLICIT NONE
      CHARACTER SIDE
      INTEGER I, J, INCV, LASTV, LDC, M, N
      INTEGER LASTC, ILASLR
      REAL    ONE, ZERO, TEMP, TAU, C(LDC, *), V(*)
      REAL    SDOT
      LOGICAL APPLYLEFT, LSAME
      PARAMETER ( ONE = 1.0E+0, ZERO = 0.0E+0 )
!
      APPLYLEFT = LSAME( SIDE, 'L' )
!     Set up variables for scanning V.  LASTV begins pointing to the end of V.
      IF( APPLYLEFT ) THEN
         LASTV = M
      ELSE
         LASTV = N
      END IF
      IF( INCV.GT.0 ) THEN
         I = 1 + (LASTV-1) * INCV
      ELSE
         I = 1
      END IF
!     Look for the last non-zero row in V.
      DO WHILE( LASTV.GT.0 .AND. V( I ).EQ.ZERO )
         LASTV = LASTV - 1
         I = I - INCV
      END DO
      IF( LASTV.LE.0 )
     $   RETURN
!     Note that lastc.eq.0 renders the BLAS operations null;
!     no special case is needed at this level.
      IF( APPLYLEFT ) THEN
*       Form  H * C
!       Scan for the last non-zero column in C(1:lastv,:).
*       Scan each column from the end, returning with the first non-zero.
        DO LASTC = N, 1, -1
            DO I = 1, LASTV
                IF(C(I,LASTC).NE.ZERO) GOTO 11
            END DO
        END DO
  11    CONTINUE
        DO 10 I = 1,LASTC
*          w(1:lastc,1) := C(1:lastv,1:lastc)**T * v(1:lastv,1)
           TEMP = -TAU*SDOT(LASTV, V, INCV, C(1,I), 1)
*          C(1:lastv,1:lastc) := C(...) - v(1:lastv,1) * w(1:lastc,1)**T
           CALL SAXPY(LASTV, TEMP, V, INCV, C(1,I), 1)
  10   CONTINUE
      ELSE
*        Form  C * H
!        Scan for the last non-zero row in C(:,1:lastv).
         LASTC = ILASLR(M, LASTV, C, LDC)
         DO 20 I = 1,LASTC
*           w(1:m,1) := C(1:m,1:lastv) * v(1:lastv,1)
            TEMP = -TAU*SDOT(LASTV, V, INCV, C(I,1), LDC)
*           C(1:m,1:lastv) := C(...) - w(1:m,1) * v(1:lastv,1)**T
            CALL SAXPY(LASTV, TEMP, V, INCV, C(I,1), LDC)
   20    CONTINUE
      END IF
      RETURN
*     End of SLARF
      END

