/* zlavsp.f -- translated by f2c (version 20061008).
   You must link the resulting object file with libf2c:
	on Microsoft Windows system, link with libf2c.lib;
	on Linux or Unix systems, link with .../path/to/libf2c.a -lm
	or, if you install libf2c.a in a standard place, with -lf2c -lm
	-- in that order, at the end of the command line, as in
		cc *.o -lf2c -lm
	Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,

		http://www.netlib.org/f2c/libf2c.zip
*/

#include "f2c.h"
#include "blaswrap.h"

/* Table of constant values */

static doublecomplex c_b1 = {1.,0.};
static integer c__1 = 1;

/* Subroutine */ int zlavsp_(char *uplo, char *trans, char *diag, integer *n, 
	integer *nrhs, doublecomplex *a, integer *ipiv, doublecomplex *b, 
	integer *ldb, integer *info)
{
    /* System generated locals */
    integer b_dim1, b_offset, i__1, i__2;
    doublecomplex z__1, z__2, z__3;

    /* Local variables */
    integer j, k;
    doublecomplex t1, t2, d11, d12, d21, d22;
    integer kc, kp;
    extern logical lsame_(char *, char *);
    extern /* Subroutine */ int zscal_(integer *, doublecomplex *, 
	    doublecomplex *, integer *), zgemv_(char *, integer *, integer *, 
	    doublecomplex *, doublecomplex *, integer *, doublecomplex *, 
	    integer *, doublecomplex *, doublecomplex *, integer *), 
	    zgeru_(integer *, integer *, doublecomplex *, doublecomplex *, 
	    integer *, doublecomplex *, integer *, doublecomplex *, integer *)
	    , zswap_(integer *, doublecomplex *, integer *, doublecomplex *, 
	    integer *), xerbla_(char *, integer *);
    integer kcnext;
    logical nounit;


/*  -- LAPACK auxiliary routine (version 3.1) -- */
/*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
/*     November 2006 */

/*     .. Scalar Arguments .. */
/*     .. */
/*     .. Array Arguments .. */
/*     .. */

/*  Purpose */
/*  ======= */

/*     ZLAVSP  performs one of the matrix-vector operations */
/*        x := A*x  or  x := A^T*x, */
/*     where x is an N element vector and  A is one of the factors */
/*     from the symmetric factorization computed by ZSPTRF. */
/*     ZSPTRF produces a factorization of the form */
/*          U * D * U^T     or     L * D * L^T, */
/*     where U (or L) is a product of permutation and unit upper (lower) */
/*     triangular matrices, U^T (or L^T) is the transpose of */
/*     U (or L), and D is symmetric and block diagonal with 1 x 1 and */
/*     2 x 2 diagonal blocks.  The multipliers for the transformations */
/*     and the upper or lower triangular parts of the diagonal blocks */
/*     are stored columnwise in packed format in the linear array A. */

/*     If TRANS = 'N' or 'n', ZLAVSP multiplies either by U or U * D */
/*     (or L or L * D). */
/*     If TRANS = 'C' or 'c', ZLAVSP multiplies either by U^T or D * U^T */
/*     (or L^T or D * L^T ). */

/*  Arguments */
/*  ========== */

/*  UPLO   - CHARACTER*1 */
/*           On entry, UPLO specifies whether the triangular matrix */
/*           stored in A is upper or lower triangular. */
/*              UPLO = 'U' or 'u'   The matrix is upper triangular. */
/*              UPLO = 'L' or 'l'   The matrix is lower triangular. */
/*           Unchanged on exit. */

/*  TRANS  - CHARACTER*1 */
/*           On entry, TRANS specifies the operation to be performed as */
/*           follows: */
/*              TRANS = 'N' or 'n'   x := A*x. */
/*              TRANS = 'T' or 't'   x := A^T*x. */
/*           Unchanged on exit. */

/*  DIAG   - CHARACTER*1 */
/*           On entry, DIAG specifies whether the diagonal blocks are */
/*           assumed to be unit matrices, as follows: */
/*              DIAG = 'U' or 'u'   Diagonal blocks are unit matrices. */
/*              DIAG = 'N' or 'n'   Diagonal blocks are non-unit. */
/*           Unchanged on exit. */

/*  N      - INTEGER */
/*           On entry, N specifies the order of the matrix A. */
/*           N must be at least zero. */
/*           Unchanged on exit. */

/*  NRHS   - INTEGER */
/*           On entry, NRHS specifies the number of right hand sides, */
/*           i.e., the number of vectors x to be multiplied by A. */
/*           NRHS must be at least zero. */
/*           Unchanged on exit. */

/*  A      - COMPLEX*16 array, dimension( N*(N+1)/2 ) */
/*           On entry, A contains a block diagonal matrix and the */
/*           multipliers of the transformations used to obtain it, */
/*           stored as a packed triangular matrix. */
/*           Unchanged on exit. */

/*  IPIV   - INTEGER array, dimension( N ) */
/*           On entry, IPIV contains the vector of pivot indices as */
/*           determined by ZSPTRF. */
/*           If IPIV( K ) = K, no interchange was done. */
/*           If IPIV( K ) <> K but IPIV( K ) > 0, then row K was inter- */
/*           changed with row IPIV( K ) and a 1 x 1 pivot block was used. */
/*           If IPIV( K ) < 0 and UPLO = 'U', then row K-1 was exchanged */
/*           with row | IPIV( K ) | and a 2 x 2 pivot block was used. */
/*           If IPIV( K ) < 0 and UPLO = 'L', then row K+1 was exchanged */
/*           with row | IPIV( K ) | and a 2 x 2 pivot block was used. */

/*  B      - COMPLEX*16 array, dimension( LDB, NRHS ) */
/*           On entry, B contains NRHS vectors of length N. */
/*           On exit, B is overwritten with the product A * B. */

/*  LDB    - INTEGER */
/*           On entry, LDB contains the leading dimension of B as */
/*           declared in the calling program.  LDB must be at least */
/*           max( 1, N ). */
/*           Unchanged on exit. */

/*  INFO   - INTEGER */
/*           INFO is the error flag. */
/*           On exit, a value of 0 indicates a successful exit. */
/*           A negative value, say -K, indicates that the K-th argument */
/*           has an illegal value. */

/*  ===================================================================== */

/*     .. Parameters .. */
/*     .. */
/*     .. Local Scalars .. */
/*     .. */
/*     .. External Functions .. */
/*     .. */
/*     .. External Subroutines .. */
/*     .. */
/*     .. Intrinsic Functions .. */
/*     .. */
/*     .. Executable Statements .. */

/*     Test the input parameters. */

    /* Parameter adjustments */
    --a;
    --ipiv;
    b_dim1 = *ldb;
    b_offset = 1 + b_dim1;
    b -= b_offset;

    /* Function Body */
    *info = 0;
    if (! lsame_(uplo, "U") && ! lsame_(uplo, "L")) {
	*info = -1;
    } else if (! lsame_(trans, "N") && ! lsame_(trans, 
	    "T")) {
	*info = -2;
    } else if (! lsame_(diag, "U") && ! lsame_(diag, 
	    "N")) {
	*info = -3;
    } else if (*n < 0) {
	*info = -4;
    } else if (*ldb < max(1,*n)) {
	*info = -8;
    }
    if (*info != 0) {
	i__1 = -(*info);
	xerbla_("ZLAVSP ", &i__1);
	return 0;
    }

/*     Quick return if possible. */

    if (*n == 0) {
	return 0;
    }

    nounit = lsame_(diag, "N");
/* ------------------------------------------ */

/*     Compute  B := A * B  (No transpose) */

/* ------------------------------------------ */
    if (lsame_(trans, "N")) {

/*        Compute  B := U*B */
/*        where U = P(m)*inv(U(m))* ... *P(1)*inv(U(1)) */

	if (lsame_(uplo, "U")) {

/*        Loop forward applying the transformations. */

	    k = 1;
	    kc = 1;
L10:
	    if (k > *n) {
		goto L30;
	    }

/*           1 x 1 pivot block */

	    if (ipiv[k] > 0) {

/*              Multiply by the diagonal element if forming U * D. */

		if (nounit) {
		    zscal_(nrhs, &a[kc + k - 1], &b[k + b_dim1], ldb);
		}

/*              Multiply by P(K) * inv(U(K))  if K > 1. */

		if (k > 1) {

/*                 Apply the transformation. */

		    i__1 = k - 1;
		    zgeru_(&i__1, nrhs, &c_b1, &a[kc], &c__1, &b[k + b_dim1], 
			    ldb, &b[b_dim1 + 1], ldb);

/*                 Interchange if P(K) != I. */

		    kp = ipiv[k];
		    if (kp != k) {
			zswap_(nrhs, &b[k + b_dim1], ldb, &b[kp + b_dim1], 
				ldb);
		    }
		}
		kc += k;
		++k;
	    } else {

/*              2 x 2 pivot block */

		kcnext = kc + k;

/*              Multiply by the diagonal block if forming U * D. */

		if (nounit) {
		    i__1 = kcnext - 1;
		    d11.r = a[i__1].r, d11.i = a[i__1].i;
		    i__1 = kcnext + k;
		    d22.r = a[i__1].r, d22.i = a[i__1].i;
		    i__1 = kcnext + k - 1;
		    d12.r = a[i__1].r, d12.i = a[i__1].i;
		    d21.r = d12.r, d21.i = d12.i;
		    i__1 = *nrhs;
		    for (j = 1; j <= i__1; ++j) {
			i__2 = k + j * b_dim1;
			t1.r = b[i__2].r, t1.i = b[i__2].i;
			i__2 = k + 1 + j * b_dim1;
			t2.r = b[i__2].r, t2.i = b[i__2].i;
			i__2 = k + j * b_dim1;
			z__2.r = d11.r * t1.r - d11.i * t1.i, z__2.i = d11.r *
				 t1.i + d11.i * t1.r;
			z__3.r = d12.r * t2.r - d12.i * t2.i, z__3.i = d12.r *
				 t2.i + d12.i * t2.r;
			z__1.r = z__2.r + z__3.r, z__1.i = z__2.i + z__3.i;
			b[i__2].r = z__1.r, b[i__2].i = z__1.i;
			i__2 = k + 1 + j * b_dim1;
			z__2.r = d21.r * t1.r - d21.i * t1.i, z__2.i = d21.r *
				 t1.i + d21.i * t1.r;
			z__3.r = d22.r * t2.r - d22.i * t2.i, z__3.i = d22.r *
				 t2.i + d22.i * t2.r;
			z__1.r = z__2.r + z__3.r, z__1.i = z__2.i + z__3.i;
			b[i__2].r = z__1.r, b[i__2].i = z__1.i;
/* L20: */
		    }
		}

/*              Multiply by  P(K) * inv(U(K))  if K > 1. */

		if (k > 1) {

/*                 Apply the transformations. */

		    i__1 = k - 1;
		    zgeru_(&i__1, nrhs, &c_b1, &a[kc], &c__1, &b[k + b_dim1], 
			    ldb, &b[b_dim1 + 1], ldb);
		    i__1 = k - 1;
		    zgeru_(&i__1, nrhs, &c_b1, &a[kcnext], &c__1, &b[k + 1 + 
			    b_dim1], ldb, &b[b_dim1 + 1], ldb);

/*                 Interchange if P(K) != I. */

		    kp = (i__1 = ipiv[k], abs(i__1));
		    if (kp != k) {
			zswap_(nrhs, &b[k + b_dim1], ldb, &b[kp + b_dim1], 
				ldb);
		    }
		}
		kc = kcnext + k + 1;
		k += 2;
	    }
	    goto L10;
L30:

/*        Compute  B := L*B */
/*        where L = P(1)*inv(L(1))* ... *P(m)*inv(L(m)) . */

	    ;
	} else {

/*           Loop backward applying the transformations to B. */

	    k = *n;
	    kc = *n * (*n + 1) / 2 + 1;
L40:
	    if (k < 1) {
		goto L60;
	    }
	    kc -= *n - k + 1;

/*           Test the pivot index.  If greater than zero, a 1 x 1 */
/*           pivot was used, otherwise a 2 x 2 pivot was used. */

	    if (ipiv[k] > 0) {

/*              1 x 1 pivot block: */

/*              Multiply by the diagonal element if forming L * D. */

		if (nounit) {
		    zscal_(nrhs, &a[kc], &b[k + b_dim1], ldb);
		}

/*              Multiply by  P(K) * inv(L(K))  if K < N. */

		if (k != *n) {
		    kp = ipiv[k];

/*                 Apply the transformation. */

		    i__1 = *n - k;
		    zgeru_(&i__1, nrhs, &c_b1, &a[kc + 1], &c__1, &b[k + 
			    b_dim1], ldb, &b[k + 1 + b_dim1], ldb);

/*                 Interchange if a permutation was applied at the */
/*                 K-th step of the factorization. */

		    if (kp != k) {
			zswap_(nrhs, &b[k + b_dim1], ldb, &b[kp + b_dim1], 
				ldb);
		    }
		}
		--k;

	    } else {

/*              2 x 2 pivot block: */

		kcnext = kc - (*n - k + 2);

/*              Multiply by the diagonal block if forming L * D. */

		if (nounit) {
		    i__1 = kcnext;
		    d11.r = a[i__1].r, d11.i = a[i__1].i;
		    i__1 = kc;
		    d22.r = a[i__1].r, d22.i = a[i__1].i;
		    i__1 = kcnext + 1;
		    d21.r = a[i__1].r, d21.i = a[i__1].i;
		    d12.r = d21.r, d12.i = d21.i;
		    i__1 = *nrhs;
		    for (j = 1; j <= i__1; ++j) {
			i__2 = k - 1 + j * b_dim1;
			t1.r = b[i__2].r, t1.i = b[i__2].i;
			i__2 = k + j * b_dim1;
			t2.r = b[i__2].r, t2.i = b[i__2].i;
			i__2 = k - 1 + j * b_dim1;
			z__2.r = d11.r * t1.r - d11.i * t1.i, z__2.i = d11.r *
				 t1.i + d11.i * t1.r;
			z__3.r = d12.r * t2.r - d12.i * t2.i, z__3.i = d12.r *
				 t2.i + d12.i * t2.r;
			z__1.r = z__2.r + z__3.r, z__1.i = z__2.i + z__3.i;
			b[i__2].r = z__1.r, b[i__2].i = z__1.i;
			i__2 = k + j * b_dim1;
			z__2.r = d21.r * t1.r - d21.i * t1.i, z__2.i = d21.r *
				 t1.i + d21.i * t1.r;
			z__3.r = d22.r * t2.r - d22.i * t2.i, z__3.i = d22.r *
				 t2.i + d22.i * t2.r;
			z__1.r = z__2.r + z__3.r, z__1.i = z__2.i + z__3.i;
			b[i__2].r = z__1.r, b[i__2].i = z__1.i;
/* L50: */
		    }
		}

/*              Multiply by  P(K) * inv(L(K))  if K < N. */

		if (k != *n) {

/*                 Apply the transformation. */

		    i__1 = *n - k;
		    zgeru_(&i__1, nrhs, &c_b1, &a[kc + 1], &c__1, &b[k + 
			    b_dim1], ldb, &b[k + 1 + b_dim1], ldb);
		    i__1 = *n - k;
		    zgeru_(&i__1, nrhs, &c_b1, &a[kcnext + 2], &c__1, &b[k - 
			    1 + b_dim1], ldb, &b[k + 1 + b_dim1], ldb);

/*                 Interchange if a permutation was applied at the */
/*                 K-th step of the factorization. */

		    kp = (i__1 = ipiv[k], abs(i__1));
		    if (kp != k) {
			zswap_(nrhs, &b[k + b_dim1], ldb, &b[kp + b_dim1], 
				ldb);
		    }
		}
		kc = kcnext;
		k += -2;
	    }
	    goto L40;
L60:
	    ;
	}
/* ------------------------------------------------- */

/*     Compute  B := A^T * B  (transpose) */

/* ------------------------------------------------- */
    } else {

/*        Form  B := U^T*B */
/*        where U  = P(m)*inv(U(m))* ... *P(1)*inv(U(1)) */
/*        and   U^T = inv(U^T(1))*P(1)* ... *inv(U^T(m))*P(m) */

	if (lsame_(uplo, "U")) {

/*           Loop backward applying the transformations. */

	    k = *n;
	    kc = *n * (*n + 1) / 2 + 1;
L70:
	    if (k < 1) {
		goto L90;
	    }
	    kc -= k;

/*           1 x 1 pivot block. */

	    if (ipiv[k] > 0) {
		if (k > 1) {

/*                 Interchange if P(K) != I. */

		    kp = ipiv[k];
		    if (kp != k) {
			zswap_(nrhs, &b[k + b_dim1], ldb, &b[kp + b_dim1], 
				ldb);
		    }

/*                 Apply the transformation: */
/*                    y := y - B' * conjg(x) */
/*                 where x is a column of A and y is a row of B. */

		    i__1 = k - 1;
		    zgemv_("Transpose", &i__1, nrhs, &c_b1, &b[b_offset], ldb, 
			     &a[kc], &c__1, &c_b1, &b[k + b_dim1], ldb);
		}
		if (nounit) {
		    zscal_(nrhs, &a[kc + k - 1], &b[k + b_dim1], ldb);
		}
		--k;

/*           2 x 2 pivot block. */

	    } else {
		kcnext = kc - (k - 1);
		if (k > 2) {

/*                 Interchange if P(K) != I. */

		    kp = (i__1 = ipiv[k], abs(i__1));
		    if (kp != k - 1) {
			zswap_(nrhs, &b[k - 1 + b_dim1], ldb, &b[kp + b_dim1], 
				 ldb);
		    }

/*                 Apply the transformations. */

		    i__1 = k - 2;
		    zgemv_("Transpose", &i__1, nrhs, &c_b1, &b[b_offset], ldb, 
			     &a[kc], &c__1, &c_b1, &b[k + b_dim1], ldb);

		    i__1 = k - 2;
		    zgemv_("Transpose", &i__1, nrhs, &c_b1, &b[b_offset], ldb, 
			     &a[kcnext], &c__1, &c_b1, &b[k - 1 + b_dim1], 
			    ldb);
		}

/*              Multiply by the diagonal block if non-unit. */

		if (nounit) {
		    i__1 = kc - 1;
		    d11.r = a[i__1].r, d11.i = a[i__1].i;
		    i__1 = kc + k - 1;
		    d22.r = a[i__1].r, d22.i = a[i__1].i;
		    i__1 = kc + k - 2;
		    d12.r = a[i__1].r, d12.i = a[i__1].i;
		    d21.r = d12.r, d21.i = d12.i;
		    i__1 = *nrhs;
		    for (j = 1; j <= i__1; ++j) {
			i__2 = k - 1 + j * b_dim1;
			t1.r = b[i__2].r, t1.i = b[i__2].i;
			i__2 = k + j * b_dim1;
			t2.r = b[i__2].r, t2.i = b[i__2].i;
			i__2 = k - 1 + j * b_dim1;
			z__2.r = d11.r * t1.r - d11.i * t1.i, z__2.i = d11.r *
				 t1.i + d11.i * t1.r;
			z__3.r = d12.r * t2.r - d12.i * t2.i, z__3.i = d12.r *
				 t2.i + d12.i * t2.r;
			z__1.r = z__2.r + z__3.r, z__1.i = z__2.i + z__3.i;
			b[i__2].r = z__1.r, b[i__2].i = z__1.i;
			i__2 = k + j * b_dim1;
			z__2.r = d21.r * t1.r - d21.i * t1.i, z__2.i = d21.r *
				 t1.i + d21.i * t1.r;
			z__3.r = d22.r * t2.r - d22.i * t2.i, z__3.i = d22.r *
				 t2.i + d22.i * t2.r;
			z__1.r = z__2.r + z__3.r, z__1.i = z__2.i + z__3.i;
			b[i__2].r = z__1.r, b[i__2].i = z__1.i;
/* L80: */
		    }
		}
		kc = kcnext;
		k += -2;
	    }
	    goto L70;
L90:

/*        Form  B := L^T*B */
/*        where L  = P(1)*inv(L(1))* ... *P(m)*inv(L(m)) */
/*        and   L^T = inv(L(m))*P(m)* ... *inv(L(1))*P(1) */

	    ;
	} else {

/*           Loop forward applying the L-transformations. */

	    k = 1;
	    kc = 1;
L100:
	    if (k > *n) {
		goto L120;
	    }

/*           1 x 1 pivot block */

	    if (ipiv[k] > 0) {
		if (k < *n) {

/*                 Interchange if P(K) != I. */

		    kp = ipiv[k];
		    if (kp != k) {
			zswap_(nrhs, &b[k + b_dim1], ldb, &b[kp + b_dim1], 
				ldb);
		    }

/*                 Apply the transformation */

		    i__1 = *n - k;
		    zgemv_("Transpose", &i__1, nrhs, &c_b1, &b[k + 1 + b_dim1]
, ldb, &a[kc + 1], &c__1, &c_b1, &b[k + b_dim1], 
			    ldb);
		}
		if (nounit) {
		    zscal_(nrhs, &a[kc], &b[k + b_dim1], ldb);
		}
		kc = kc + *n - k + 1;
		++k;

/*           2 x 2 pivot block. */

	    } else {
		kcnext = kc + *n - k + 1;
		if (k < *n - 1) {

/*              Interchange if P(K) != I. */

		    kp = (i__1 = ipiv[k], abs(i__1));
		    if (kp != k + 1) {
			zswap_(nrhs, &b[k + 1 + b_dim1], ldb, &b[kp + b_dim1], 
				 ldb);
		    }

/*                 Apply the transformation */

		    i__1 = *n - k - 1;
		    zgemv_("Transpose", &i__1, nrhs, &c_b1, &b[k + 2 + b_dim1]
, ldb, &a[kcnext + 1], &c__1, &c_b1, &b[k + 1 + 
			    b_dim1], ldb);

		    i__1 = *n - k - 1;
		    zgemv_("Transpose", &i__1, nrhs, &c_b1, &b[k + 2 + b_dim1]
, ldb, &a[kc + 2], &c__1, &c_b1, &b[k + b_dim1], 
			    ldb);
		}

/*              Multiply by the diagonal block if non-unit. */

		if (nounit) {
		    i__1 = kc;
		    d11.r = a[i__1].r, d11.i = a[i__1].i;
		    i__1 = kcnext;
		    d22.r = a[i__1].r, d22.i = a[i__1].i;
		    i__1 = kc + 1;
		    d21.r = a[i__1].r, d21.i = a[i__1].i;
		    d12.r = d21.r, d12.i = d21.i;
		    i__1 = *nrhs;
		    for (j = 1; j <= i__1; ++j) {
			i__2 = k + j * b_dim1;
			t1.r = b[i__2].r, t1.i = b[i__2].i;
			i__2 = k + 1 + j * b_dim1;
			t2.r = b[i__2].r, t2.i = b[i__2].i;
			i__2 = k + j * b_dim1;
			z__2.r = d11.r * t1.r - d11.i * t1.i, z__2.i = d11.r *
				 t1.i + d11.i * t1.r;
			z__3.r = d12.r * t2.r - d12.i * t2.i, z__3.i = d12.r *
				 t2.i + d12.i * t2.r;
			z__1.r = z__2.r + z__3.r, z__1.i = z__2.i + z__3.i;
			b[i__2].r = z__1.r, b[i__2].i = z__1.i;
			i__2 = k + 1 + j * b_dim1;
			z__2.r = d21.r * t1.r - d21.i * t1.i, z__2.i = d21.r *
				 t1.i + d21.i * t1.r;
			z__3.r = d22.r * t2.r - d22.i * t2.i, z__3.i = d22.r *
				 t2.i + d22.i * t2.r;
			z__1.r = z__2.r + z__3.r, z__1.i = z__2.i + z__3.i;
			b[i__2].r = z__1.r, b[i__2].i = z__1.i;
/* L110: */
		    }
		}
		kc = kcnext + (*n - k);
		k += 2;
	    }
	    goto L100;
L120:
	    ;
	}

    }
    return 0;

/*     End of ZLAVSP */

} /* zlavsp_ */
