예제 #1
0
파일: clalsa.c 프로젝트: MichaelH13/sdkpub
/* Subroutine */ int clalsa_(integer *icompq, integer *smlsiz, integer *n, 
	integer *nrhs, complex *b, integer *ldb, complex *bx, integer *ldbx, 
	real *u, integer *ldu, real *vt, integer *k, real *difl, real *difr, 
	real *z__, real *poles, integer *givptr, integer *givcol, integer *
	ldgcol, integer *perm, real *givnum, real *c__, real *s, real *rwork, 
	integer *iwork, integer *info)
{
/*  -- LAPACK routine (version 3.0) --   
       Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,   
       Courant Institute, Argonne National Lab, and Rice University   
       June 30, 1999   


    Purpose   
    =======   

    CLALSA is an itermediate step in solving the least squares problem   
    by computing the SVD of the coefficient matrix in compact form (The   
    singular vectors are computed as products of simple orthorgonal   
    matrices.).   

    If ICOMPQ = 0, CLALSA applies the inverse of the left singular vector   
    matrix of an upper bidiagonal matrix to the right hand side; and if   
    ICOMPQ = 1, CLALSA applies the right singular vector matrix to the   
    right hand side. The singular vector matrices were generated in   
    compact form by CLALSA.   

    Arguments   
    =========   

    ICOMPQ (input) INTEGER   
           Specifies whether the left or the right singular vector   
           matrix is involved.   
           = 0: Left singular vector matrix   
           = 1: Right singular vector matrix   

    SMLSIZ (input) INTEGER   
           The maximum size of the subproblems at the bottom of the   
           computation tree.   

    N      (input) INTEGER   
           The row and column dimensions of the upper bidiagonal matrix.   

    NRHS   (input) INTEGER   
           The number of columns of B and BX. NRHS must be at least 1.   

    B      (input) COMPLEX array, dimension ( LDB, NRHS )   
           On input, B contains the right hand sides of the least   
           squares problem in rows 1 through M. On output, B contains   
           the solution X in rows 1 through N.   

    LDB    (input) INTEGER   
           The leading dimension of B in the calling subprogram.   
           LDB must be at least max(1,MAX( M, N ) ).   

    BX     (output) COMPLEX array, dimension ( LDBX, NRHS )   
           On exit, the result of applying the left or right singular   
           vector matrix to B.   

    LDBX   (input) INTEGER   
           The leading dimension of BX.   

    U      (input) REAL array, dimension ( LDU, SMLSIZ ).   
           On entry, U contains the left singular vector matrices of all   
           subproblems at the bottom level.   

    LDU    (input) INTEGER, LDU = > N.   
           The leading dimension of arrays U, VT, DIFL, DIFR,   
           POLES, GIVNUM, and Z.   

    VT     (input) REAL array, dimension ( LDU, SMLSIZ+1 ).   
           On entry, VT' contains the right singular vector matrices of   
           all subproblems at the bottom level.   

    K      (input) INTEGER array, dimension ( N ).   

    DIFL   (input) REAL array, dimension ( LDU, NLVL ).   
           where NLVL = INT(log_2 (N/(SMLSIZ+1))) + 1.   

    DIFR   (input) REAL array, dimension ( LDU, 2 * NLVL ).   
           On entry, DIFL(*, I) and DIFR(*, 2 * I -1) record   
           distances between singular values on the I-th level and   
           singular values on the (I -1)-th level, and DIFR(*, 2 * I)   
           record the normalizing factors of the right singular vectors   
           matrices of subproblems on I-th level.   

    Z      (input) REAL array, dimension ( LDU, NLVL ).   
           On entry, Z(1, I) contains the components of the deflation-   
           adjusted updating row vector for subproblems on the I-th   
           level.   

    POLES  (input) REAL array, dimension ( LDU, 2 * NLVL ).   
           On entry, POLES(*, 2 * I -1: 2 * I) contains the new and old   
           singular values involved in the secular equations on the I-th   
           level.   

    GIVPTR (input) INTEGER array, dimension ( N ).   
           On entry, GIVPTR( I ) records the number of Givens   
           rotations performed on the I-th problem on the computation   
           tree.   

    GIVCOL (input) INTEGER array, dimension ( LDGCOL, 2 * NLVL ).   
           On entry, for each I, GIVCOL(*, 2 * I - 1: 2 * I) records the   
           locations of Givens rotations performed on the I-th level on   
           the computation tree.   

    LDGCOL (input) INTEGER, LDGCOL = > N.   
           The leading dimension of arrays GIVCOL and PERM.   

    PERM   (input) INTEGER array, dimension ( LDGCOL, NLVL ).   
           On entry, PERM(*, I) records permutations done on the I-th   
           level of the computation tree.   

    GIVNUM (input) REAL array, dimension ( LDU, 2 * NLVL ).   
           On entry, GIVNUM(*, 2 *I -1 : 2 * I) records the C- and S-   
           values of Givens rotations performed on the I-th level on the   
           computation tree.   

    C      (input) REAL array, dimension ( N ).   
           On entry, if the I-th subproblem is not square,   
           C( I ) contains the C-value of a Givens rotation related to   
           the right null space of the I-th subproblem.   

    S      (input) REAL array, dimension ( N ).   
           On entry, if the I-th subproblem is not square,   
           S( I ) contains the S-value of a Givens rotation related to   
           the right null space of the I-th subproblem.   

    RWORK  (workspace) REAL array, dimension at least   
           max ( N, (SMLSZ+1)*NRHS*3 ).   

    IWORK  (workspace) INTEGER array.   
           The dimension must be at least 3 * N   

    INFO   (output) INTEGER   
            = 0:  successful exit.   
            < 0:  if INFO = -i, the i-th argument had an illegal value.   

    Further Details   
    ===============   

    Based on contributions by   
       Ming Gu and Ren-Cang Li, Computer Science Division, University of   
         California at Berkeley, USA   
       Osni Marques, LBNL/NERSC, USA   

    =====================================================================   


       Test the input parameters.   

       Parameter adjustments */
    /* Table of constant values */
    static real c_b9 = 1.f;
    static real c_b10 = 0.f;
    static integer c__2 = 2;
    
    /* System generated locals */
    integer givcol_dim1, givcol_offset, perm_dim1, perm_offset, difl_dim1, 
	    difl_offset, difr_dim1, difr_offset, givnum_dim1, givnum_offset, 
	    poles_dim1, poles_offset, u_dim1, u_offset, vt_dim1, vt_offset, 
	    z_dim1, z_offset, b_dim1, b_offset, bx_dim1, bx_offset, i__1, 
	    i__2, i__3, i__4, i__5, i__6;
    complex q__1;
    /* Builtin functions */
    double r_imag(complex *);
    integer pow_ii(integer *, integer *);
    /* Local variables */
    static integer jcol, nlvl, sqre, jrow, i__, j, jimag, jreal, inode, ndiml;
    extern /* Subroutine */ int sgemm_(char *, char *, integer *, integer *, 
	    integer *, real *, real *, integer *, real *, integer *, real *, 
	    real *, integer *);
    static integer ndimr;
    extern /* Subroutine */ int ccopy_(integer *, complex *, integer *, 
	    complex *, integer *);
    static integer i1;
    extern /* Subroutine */ int clals0_(integer *, integer *, integer *, 
	    integer *, integer *, complex *, integer *, complex *, integer *, 
	    integer *, integer *, integer *, integer *, real *, integer *, 
	    real *, real *, real *, real *, integer *, real *, real *, real *,
	     integer *);
    static integer ic, lf, nd, ll, nl, nr;
    extern /* Subroutine */ int xerbla_(char *, integer *), slasdt_(
	    integer *, integer *, integer *, integer *, integer *, integer *, 
	    integer *);
    static integer im1, nlf, nrf, lvl, ndb1, nlp1, lvl2, nrp1;
#define difl_ref(a_1,a_2) difl[(a_2)*difl_dim1 + a_1]
#define difr_ref(a_1,a_2) difr[(a_2)*difr_dim1 + a_1]
#define perm_ref(a_1,a_2) perm[(a_2)*perm_dim1 + a_1]
#define b_subscr(a_1,a_2) (a_2)*b_dim1 + a_1
#define b_ref(a_1,a_2) b[b_subscr(a_1,a_2)]
#define u_ref(a_1,a_2) u[(a_2)*u_dim1 + a_1]
#define z___ref(a_1,a_2) z__[(a_2)*z_dim1 + a_1]
#define poles_ref(a_1,a_2) poles[(a_2)*poles_dim1 + a_1]
#define bx_subscr(a_1,a_2) (a_2)*bx_dim1 + a_1
#define bx_ref(a_1,a_2) bx[bx_subscr(a_1,a_2)]
#define vt_ref(a_1,a_2) vt[(a_2)*vt_dim1 + a_1]
#define givcol_ref(a_1,a_2) givcol[(a_2)*givcol_dim1 + a_1]
#define givnum_ref(a_1,a_2) givnum[(a_2)*givnum_dim1 + a_1]


    b_dim1 = *ldb;
    b_offset = 1 + b_dim1 * 1;
    b -= b_offset;
    bx_dim1 = *ldbx;
    bx_offset = 1 + bx_dim1 * 1;
    bx -= bx_offset;
    givnum_dim1 = *ldu;
    givnum_offset = 1 + givnum_dim1 * 1;
    givnum -= givnum_offset;
    poles_dim1 = *ldu;
    poles_offset = 1 + poles_dim1 * 1;
    poles -= poles_offset;
    z_dim1 = *ldu;
    z_offset = 1 + z_dim1 * 1;
    z__ -= z_offset;
    difr_dim1 = *ldu;
    difr_offset = 1 + difr_dim1 * 1;
    difr -= difr_offset;
    difl_dim1 = *ldu;
    difl_offset = 1 + difl_dim1 * 1;
    difl -= difl_offset;
    vt_dim1 = *ldu;
    vt_offset = 1 + vt_dim1 * 1;
    vt -= vt_offset;
    u_dim1 = *ldu;
    u_offset = 1 + u_dim1 * 1;
    u -= u_offset;
    --k;
    --givptr;
    perm_dim1 = *ldgcol;
    perm_offset = 1 + perm_dim1 * 1;
    perm -= perm_offset;
    givcol_dim1 = *ldgcol;
    givcol_offset = 1 + givcol_dim1 * 1;
    givcol -= givcol_offset;
    --c__;
    --s;
    --rwork;
    --iwork;

    /* Function Body */
    *info = 0;

    if (*icompq < 0 || *icompq > 1) {
	*info = -1;
    } else if (*smlsiz < 3) {
	*info = -2;
    } else if (*n < *smlsiz) {
	*info = -3;
    } else if (*nrhs < 1) {
	*info = -4;
    } else if (*ldb < *n) {
	*info = -6;
    } else if (*ldbx < *n) {
	*info = -8;
    } else if (*ldu < *n) {
	*info = -10;
    } else if (*ldgcol < *n) {
	*info = -19;
    }
    if (*info != 0) {
	i__1 = -(*info);
	xerbla_("CLALSA", &i__1);
	return 0;
    }

/*     Book-keeping and  setting up the computation tree. */

    inode = 1;
    ndiml = inode + *n;
    ndimr = ndiml + *n;

    slasdt_(n, &nlvl, &nd, &iwork[inode], &iwork[ndiml], &iwork[ndimr], 
	    smlsiz);

/*     The following code applies back the left singular vector factors.   
       For applying back the right singular vector factors, go to 170. */

    if (*icompq == 1) {
	goto L170;
    }

/*     The nodes on the bottom level of the tree were solved   
       by SLASDQ. The corresponding left and right singular vector   
       matrices are in explicit form. First apply back the left   
       singular vector matrices. */

    ndb1 = (nd + 1) / 2;
    i__1 = nd;
    for (i__ = ndb1; i__ <= i__1; ++i__) {

/*        IC : center row of each node   
          NL : number of rows of left  subproblem   
          NR : number of rows of right subproblem   
          NLF: starting row of the left   subproblem   
          NRF: starting row of the right  subproblem */

	i1 = i__ - 1;
	ic = iwork[inode + i1];
	nl = iwork[ndiml + i1];
	nr = iwork[ndimr + i1];
	nlf = ic - nl;
	nrf = ic + 1;

/*        Since B and BX are complex, the following call to SGEMM   
          is performed in two steps (real and imaginary parts).   

          CALL SGEMM( 'T', 'N', NL, NRHS, NL, ONE, U( NLF, 1 ), LDU,   
       $               B( NLF, 1 ), LDB, ZERO, BX( NLF, 1 ), LDBX ) */

	j = nl * *nrhs << 1;
	i__2 = *nrhs;
	for (jcol = 1; jcol <= i__2; ++jcol) {
	    i__3 = nlf + nl - 1;
	    for (jrow = nlf; jrow <= i__3; ++jrow) {
		++j;
		i__4 = b_subscr(jrow, jcol);
		rwork[j] = b[i__4].r;
/* L10: */
	    }
/* L20: */
	}
	sgemm_("T", "N", &nl, nrhs, &nl, &c_b9, &u_ref(nlf, 1), ldu, &rwork[(
		nl * *nrhs << 1) + 1], &nl, &c_b10, &rwork[1], &nl);
	j = nl * *nrhs << 1;
	i__2 = *nrhs;
	for (jcol = 1; jcol <= i__2; ++jcol) {
	    i__3 = nlf + nl - 1;
	    for (jrow = nlf; jrow <= i__3; ++jrow) {
		++j;
		rwork[j] = r_imag(&b_ref(jrow, jcol));
/* L30: */
	    }
/* L40: */
	}
	sgemm_("T", "N", &nl, nrhs, &nl, &c_b9, &u_ref(nlf, 1), ldu, &rwork[(
		nl * *nrhs << 1) + 1], &nl, &c_b10, &rwork[nl * *nrhs + 1], &
		nl);
	jreal = 0;
	jimag = nl * *nrhs;
	i__2 = *nrhs;
	for (jcol = 1; jcol <= i__2; ++jcol) {
	    i__3 = nlf + nl - 1;
	    for (jrow = nlf; jrow <= i__3; ++jrow) {
		++jreal;
		++jimag;
		i__4 = bx_subscr(jrow, jcol);
		i__5 = jreal;
		i__6 = jimag;
		q__1.r = rwork[i__5], q__1.i = rwork[i__6];
		bx[i__4].r = q__1.r, bx[i__4].i = q__1.i;
/* L50: */
	    }
/* L60: */
	}

/*        Since B and BX are complex, the following call to SGEMM   
          is performed in two steps (real and imaginary parts).   

          CALL SGEMM( 'T', 'N', NR, NRHS, NR, ONE, U( NRF, 1 ), LDU,   
      $               B( NRF, 1 ), LDB, ZERO, BX( NRF, 1 ), LDBX ) */

	j = nr * *nrhs << 1;
	i__2 = *nrhs;
	for (jcol = 1; jcol <= i__2; ++jcol) {
	    i__3 = nrf + nr - 1;
	    for (jrow = nrf; jrow <= i__3; ++jrow) {
		++j;
		i__4 = b_subscr(jrow, jcol);
		rwork[j] = b[i__4].r;
/* L70: */
	    }
/* L80: */
	}
	sgemm_("T", "N", &nr, nrhs, &nr, &c_b9, &u_ref(nrf, 1), ldu, &rwork[(
		nr * *nrhs << 1) + 1], &nr, &c_b10, &rwork[1], &nr);
	j = nr * *nrhs << 1;
	i__2 = *nrhs;
	for (jcol = 1; jcol <= i__2; ++jcol) {
	    i__3 = nrf + nr - 1;
	    for (jrow = nrf; jrow <= i__3; ++jrow) {
		++j;
		rwork[j] = r_imag(&b_ref(jrow, jcol));
/* L90: */
	    }
/* L100: */
	}
	sgemm_("T", "N", &nr, nrhs, &nr, &c_b9, &u_ref(nrf, 1), ldu, &rwork[(
		nr * *nrhs << 1) + 1], &nr, &c_b10, &rwork[nr * *nrhs + 1], &
		nr);
	jreal = 0;
	jimag = nr * *nrhs;
	i__2 = *nrhs;
	for (jcol = 1; jcol <= i__2; ++jcol) {
	    i__3 = nrf + nr - 1;
	    for (jrow = nrf; jrow <= i__3; ++jrow) {
		++jreal;
		++jimag;
		i__4 = bx_subscr(jrow, jcol);
		i__5 = jreal;
		i__6 = jimag;
		q__1.r = rwork[i__5], q__1.i = rwork[i__6];
		bx[i__4].r = q__1.r, bx[i__4].i = q__1.i;
/* L110: */
	    }
/* L120: */
	}

/* L130: */
    }

/*     Next copy the rows of B that correspond to unchanged rows   
       in the bidiagonal matrix to BX. */

    i__1 = nd;
    for (i__ = 1; i__ <= i__1; ++i__) {
	ic = iwork[inode + i__ - 1];
	ccopy_(nrhs, &b_ref(ic, 1), ldb, &bx_ref(ic, 1), ldbx);
/* L140: */
    }

/*     Finally go through the left singular vector matrices of all   
       the other subproblems bottom-up on the tree. */

    j = pow_ii(&c__2, &nlvl);
    sqre = 0;

    for (lvl = nlvl; lvl >= 1; --lvl) {
	lvl2 = (lvl << 1) - 1;

/*        find the first node LF and last node LL on   
          the current level LVL */

	if (lvl == 1) {
	    lf = 1;
	    ll = 1;
	} else {
	    i__1 = lvl - 1;
	    lf = pow_ii(&c__2, &i__1);
	    ll = (lf << 1) - 1;
	}
	i__1 = ll;
	for (i__ = lf; i__ <= i__1; ++i__) {
	    im1 = i__ - 1;
	    ic = iwork[inode + im1];
	    nl = iwork[ndiml + im1];
	    nr = iwork[ndimr + im1];
	    nlf = ic - nl;
	    nrf = ic + 1;
	    --j;
	    clals0_(icompq, &nl, &nr, &sqre, nrhs, &bx_ref(nlf, 1), ldbx, &
		    b_ref(nlf, 1), ldb, &perm_ref(nlf, lvl), &givptr[j], &
		    givcol_ref(nlf, lvl2), ldgcol, &givnum_ref(nlf, lvl2), 
		    ldu, &poles_ref(nlf, lvl2), &difl_ref(nlf, lvl), &
		    difr_ref(nlf, lvl2), &z___ref(nlf, lvl), &k[j], &c__[j], &
		    s[j], &rwork[1], info);
/* L150: */
	}
/* L160: */
    }
    goto L330;

/*     ICOMPQ = 1: applying back the right singular vector factors. */

L170:

/*     First now go through the right singular vector matrices of all   
       the tree nodes top-down. */

    j = 0;
    i__1 = nlvl;
    for (lvl = 1; lvl <= i__1; ++lvl) {
	lvl2 = (lvl << 1) - 1;

/*        Find the first node LF and last node LL on   
          the current level LVL. */

	if (lvl == 1) {
	    lf = 1;
	    ll = 1;
	} else {
	    i__2 = lvl - 1;
	    lf = pow_ii(&c__2, &i__2);
	    ll = (lf << 1) - 1;
	}
	i__2 = lf;
	for (i__ = ll; i__ >= i__2; --i__) {
	    im1 = i__ - 1;
	    ic = iwork[inode + im1];
	    nl = iwork[ndiml + im1];
	    nr = iwork[ndimr + im1];
	    nlf = ic - nl;
	    nrf = ic + 1;
	    if (i__ == ll) {
		sqre = 0;
	    } else {
		sqre = 1;
	    }
	    ++j;
	    clals0_(icompq, &nl, &nr, &sqre, nrhs, &b_ref(nlf, 1), ldb, &
		    bx_ref(nlf, 1), ldbx, &perm_ref(nlf, lvl), &givptr[j], &
		    givcol_ref(nlf, lvl2), ldgcol, &givnum_ref(nlf, lvl2), 
		    ldu, &poles_ref(nlf, lvl2), &difl_ref(nlf, lvl), &
		    difr_ref(nlf, lvl2), &z___ref(nlf, lvl), &k[j], &c__[j], &
		    s[j], &rwork[1], info);
/* L180: */
	}
/* L190: */
    }

/*     The nodes on the bottom level of the tree were solved   
       by SLASDQ. The corresponding right singular vector   
       matrices are in explicit form. Apply them back. */

    ndb1 = (nd + 1) / 2;
    i__1 = nd;
    for (i__ = ndb1; i__ <= i__1; ++i__) {
	i1 = i__ - 1;
	ic = iwork[inode + i1];
	nl = iwork[ndiml + i1];
	nr = iwork[ndimr + i1];
	nlp1 = nl + 1;
	if (i__ == nd) {
	    nrp1 = nr;
	} else {
	    nrp1 = nr + 1;
	}
	nlf = ic - nl;
	nrf = ic + 1;

/*        Since B and BX are complex, the following call to SGEMM is   
          performed in two steps (real and imaginary parts).   

          CALL SGEMM( 'T', 'N', NLP1, NRHS, NLP1, ONE, VT( NLF, 1 ), LDU,   
      $               B( NLF, 1 ), LDB, ZERO, BX( NLF, 1 ), LDBX ) */

	j = nlp1 * *nrhs << 1;
	i__2 = *nrhs;
	for (jcol = 1; jcol <= i__2; ++jcol) {
	    i__3 = nlf + nlp1 - 1;
	    for (jrow = nlf; jrow <= i__3; ++jrow) {
		++j;
		i__4 = b_subscr(jrow, jcol);
		rwork[j] = b[i__4].r;
/* L200: */
	    }
/* L210: */
	}
	sgemm_("T", "N", &nlp1, nrhs, &nlp1, &c_b9, &vt_ref(nlf, 1), ldu, &
		rwork[(nlp1 * *nrhs << 1) + 1], &nlp1, &c_b10, &rwork[1], &
		nlp1);
	j = nlp1 * *nrhs << 1;
	i__2 = *nrhs;
	for (jcol = 1; jcol <= i__2; ++jcol) {
	    i__3 = nlf + nlp1 - 1;
	    for (jrow = nlf; jrow <= i__3; ++jrow) {
		++j;
		rwork[j] = r_imag(&b_ref(jrow, jcol));
/* L220: */
	    }
/* L230: */
	}
	sgemm_("T", "N", &nlp1, nrhs, &nlp1, &c_b9, &vt_ref(nlf, 1), ldu, &
		rwork[(nlp1 * *nrhs << 1) + 1], &nlp1, &c_b10, &rwork[nlp1 * *
		nrhs + 1], &nlp1);
	jreal = 0;
	jimag = nlp1 * *nrhs;
	i__2 = *nrhs;
	for (jcol = 1; jcol <= i__2; ++jcol) {
	    i__3 = nlf + nlp1 - 1;
	    for (jrow = nlf; jrow <= i__3; ++jrow) {
		++jreal;
		++jimag;
		i__4 = bx_subscr(jrow, jcol);
		i__5 = jreal;
		i__6 = jimag;
		q__1.r = rwork[i__5], q__1.i = rwork[i__6];
		bx[i__4].r = q__1.r, bx[i__4].i = q__1.i;
/* L240: */
	    }
/* L250: */
	}

/*        Since B and BX are complex, the following call to SGEMM is   
          performed in two steps (real and imaginary parts).   

          CALL SGEMM( 'T', 'N', NRP1, NRHS, NRP1, ONE, VT( NRF, 1 ), LDU,   
      $               B( NRF, 1 ), LDB, ZERO, BX( NRF, 1 ), LDBX ) */

	j = nrp1 * *nrhs << 1;
	i__2 = *nrhs;
	for (jcol = 1; jcol <= i__2; ++jcol) {
	    i__3 = nrf + nrp1 - 1;
	    for (jrow = nrf; jrow <= i__3; ++jrow) {
		++j;
		i__4 = b_subscr(jrow, jcol);
		rwork[j] = b[i__4].r;
/* L260: */
	    }
/* L270: */
	}
	sgemm_("T", "N", &nrp1, nrhs, &nrp1, &c_b9, &vt_ref(nrf, 1), ldu, &
		rwork[(nrp1 * *nrhs << 1) + 1], &nrp1, &c_b10, &rwork[1], &
		nrp1);
	j = nrp1 * *nrhs << 1;
	i__2 = *nrhs;
	for (jcol = 1; jcol <= i__2; ++jcol) {
	    i__3 = nrf + nrp1 - 1;
	    for (jrow = nrf; jrow <= i__3; ++jrow) {
		++j;
		rwork[j] = r_imag(&b_ref(jrow, jcol));
/* L280: */
	    }
/* L290: */
	}
	sgemm_("T", "N", &nrp1, nrhs, &nrp1, &c_b9, &vt_ref(nrf, 1), ldu, &
		rwork[(nrp1 * *nrhs << 1) + 1], &nrp1, &c_b10, &rwork[nrp1 * *
		nrhs + 1], &nrp1);
	jreal = 0;
	jimag = nrp1 * *nrhs;
	i__2 = *nrhs;
	for (jcol = 1; jcol <= i__2; ++jcol) {
	    i__3 = nrf + nrp1 - 1;
	    for (jrow = nrf; jrow <= i__3; ++jrow) {
		++jreal;
		++jimag;
		i__4 = bx_subscr(jrow, jcol);
		i__5 = jreal;
		i__6 = jimag;
		q__1.r = rwork[i__5], q__1.i = rwork[i__6];
		bx[i__4].r = q__1.r, bx[i__4].i = q__1.i;
/* L300: */
	    }
/* L310: */
	}

/* L320: */
    }

L330:

    return 0;

/*     End of CLALSA */

} /* clalsa_ */
예제 #2
0
/* Subroutine */ int slasda_(integer *icompq, integer *smlsiz, integer *n,
                             integer *sqre, real *d__, real *e, real *u, integer *ldu, real *vt,
                             integer *k, real *difl, real *difr, real *z__, real *poles, integer *
                             givptr, integer *givcol, integer *ldgcol, integer *perm, real *givnum,
                             real *c__, real *s, real *work, integer *iwork, integer *info)
{
    /* System generated locals */
    integer givcol_dim1, givcol_offset, perm_dim1, perm_offset, difl_dim1,
            difl_offset, difr_dim1, difr_offset, givnum_dim1, givnum_offset,
            poles_dim1, poles_offset, u_dim1, u_offset, vt_dim1, vt_offset,
            z_dim1, z_offset, i__1, i__2;

    /* Builtin functions */
    integer pow_ii(integer *, integer *);

    /* Local variables */
    integer i__, j, m, i1, ic, lf, nd, ll, nl, vf, nr, vl, im1, ncc, nlf, nrf,
            vfi, iwk, vli, lvl, nru, ndb1, nlp1, lvl2, nrp1;
    real beta;
    integer idxq, nlvl;
    real alpha;
    integer inode, ndiml, ndimr, idxqi, itemp, sqrei;
    extern /* Subroutine */ int scopy_(integer *, real *, integer *, real *,
                                       integer *), slasd6_(integer *, integer *, integer *, integer *,
                                               real *, real *, real *, real *, real *, integer *, integer *,
                                               integer *, integer *, integer *, real *, integer *, real *, real *
                                               , real *, real *, integer *, real *, real *, real *, integer *,
                                               integer *);
    integer nwork1, nwork2;
    extern /* Subroutine */ int xerbla_(char *, integer *), slasdq_(
        char *, integer *, integer *, integer *, integer *, integer *,
        real *, real *, real *, integer *, real *, integer *, real *,
        integer *, real *, integer *), slasdt_(integer *, integer
                *, integer *, integer *, integer *, integer *, integer *),
                slaset_(char *, integer *, integer *, real *, real *, real *,
                        integer *);
    integer smlszp;


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

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

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

    /*  Using a divide and conquer approach, SLASDA computes the singular */
    /*  value decomposition (SVD) of a real upper bidiagonal N-by-M matrix */
    /*  B with diagonal D and offdiagonal E, where M = N + SQRE. The */
    /*  algorithm computes the singular values in the SVD B = U * S * VT. */
    /*  The orthogonal matrices U and VT are optionally computed in */
    /*  compact form. */

    /*  A related subroutine, SLASD0, computes the singular values and */
    /*  the singular vectors in explicit form. */

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

    /*  ICOMPQ (input) INTEGER */
    /*         Specifies whether singular vectors are to be computed */
    /*         in compact form, as follows */
    /*         = 0: Compute singular values only. */
    /*         = 1: Compute singular vectors of upper bidiagonal */
    /*              matrix in compact form. */

    /*  SMLSIZ (input) INTEGER */
    /*         The maximum size of the subproblems at the bottom of the */
    /*         computation tree. */

    /*  N      (input) INTEGER */
    /*         The row dimension of the upper bidiagonal matrix. This is */
    /*         also the dimension of the main diagonal array D. */

    /*  SQRE   (input) INTEGER */
    /*         Specifies the column dimension of the bidiagonal matrix. */
    /*         = 0: The bidiagonal matrix has column dimension M = N; */
    /*         = 1: The bidiagonal matrix has column dimension M = N + 1. */

    /*  D      (input/output) REAL array, dimension ( N ) */
    /*         On entry D contains the main diagonal of the bidiagonal */
    /*         matrix. On exit D, if INFO = 0, contains its singular values. */

    /*  E      (input) REAL array, dimension ( M-1 ) */
    /*         Contains the subdiagonal entries of the bidiagonal matrix. */
    /*         On exit, E has been destroyed. */

    /*  U      (output) REAL array, */
    /*         dimension ( LDU, SMLSIZ ) if ICOMPQ = 1, and not referenced */
    /*         if ICOMPQ = 0. If ICOMPQ = 1, on exit, U contains the left */
    /*         singular vector matrices of all subproblems at the bottom */
    /*         level. */

    /*  LDU    (input) INTEGER, LDU = > N. */
    /*         The leading dimension of arrays U, VT, DIFL, DIFR, POLES, */
    /*         GIVNUM, and Z. */

    /*  VT     (output) REAL array, */
    /*         dimension ( LDU, SMLSIZ+1 ) if ICOMPQ = 1, and not referenced */
    /*         if ICOMPQ = 0. If ICOMPQ = 1, on exit, VT' contains the right */
    /*         singular vector matrices of all subproblems at the bottom */
    /*         level. */

    /*  K      (output) INTEGER array, dimension ( N ) */
    /*         if ICOMPQ = 1 and dimension 1 if ICOMPQ = 0. */
    /*         If ICOMPQ = 1, on exit, K(I) is the dimension of the I-th */
    /*         secular equation on the computation tree. */

    /*  DIFL   (output) REAL array, dimension ( LDU, NLVL ), */
    /*         where NLVL = floor(log_2 (N/SMLSIZ))). */

    /*  DIFR   (output) REAL array, */
    /*                  dimension ( LDU, 2 * NLVL ) if ICOMPQ = 1 and */
    /*                  dimension ( N ) if ICOMPQ = 0. */
    /*         If ICOMPQ = 1, on exit, DIFL(1:N, I) and DIFR(1:N, 2 * I - 1) */
    /*         record distances between singular values on the I-th */
    /*         level and singular values on the (I -1)-th level, and */
    /*         DIFR(1:N, 2 * I ) contains the normalizing factors for */
    /*         the right singular vector matrix. See SLASD8 for details. */

    /*  Z      (output) REAL array, */
    /*                  dimension ( LDU, NLVL ) if ICOMPQ = 1 and */
    /*                  dimension ( N ) if ICOMPQ = 0. */
    /*         The first K elements of Z(1, I) contain the components of */
    /*         the deflation-adjusted updating row vector for subproblems */
    /*         on the I-th level. */

    /*  POLES  (output) REAL array, */
    /*         dimension ( LDU, 2 * NLVL ) if ICOMPQ = 1, and not referenced */
    /*         if ICOMPQ = 0. If ICOMPQ = 1, on exit, POLES(1, 2*I - 1) and */
    /*         POLES(1, 2*I) contain  the new and old singular values */
    /*         involved in the secular equations on the I-th level. */

    /*  GIVPTR (output) INTEGER array, */
    /*         dimension ( N ) if ICOMPQ = 1, and not referenced if */
    /*         ICOMPQ = 0. If ICOMPQ = 1, on exit, GIVPTR( I ) records */
    /*         the number of Givens rotations performed on the I-th */
    /*         problem on the computation tree. */

    /*  GIVCOL (output) INTEGER array, */
    /*         dimension ( LDGCOL, 2 * NLVL ) if ICOMPQ = 1, and not */
    /*         referenced if ICOMPQ = 0. If ICOMPQ = 1, on exit, for each I, */
    /*         GIVCOL(1, 2 *I - 1) and GIVCOL(1, 2 *I) record the locations */
    /*         of Givens rotations performed on the I-th level on the */
    /*         computation tree. */

    /*  LDGCOL (input) INTEGER, LDGCOL = > N. */
    /*         The leading dimension of arrays GIVCOL and PERM. */

    /*  PERM   (output) INTEGER array, dimension ( LDGCOL, NLVL ) */
    /*         if ICOMPQ = 1, and not referenced */
    /*         if ICOMPQ = 0. If ICOMPQ = 1, on exit, PERM(1, I) records */
    /*         permutations done on the I-th level of the computation tree. */

    /*  GIVNUM (output) REAL array, */
    /*         dimension ( LDU,  2 * NLVL ) if ICOMPQ = 1, and not */
    /*         referenced if ICOMPQ = 0. If ICOMPQ = 1, on exit, for each I, */
    /*         GIVNUM(1, 2 *I - 1) and GIVNUM(1, 2 *I) record the C- and S- */
    /*         values of Givens rotations performed on the I-th level on */
    /*         the computation tree. */

    /*  C      (output) REAL array, */
    /*         dimension ( N ) if ICOMPQ = 1, and dimension 1 if ICOMPQ = 0. */
    /*         If ICOMPQ = 1 and the I-th subproblem is not square, on exit, */
    /*         C( I ) contains the C-value of a Givens rotation related to */
    /*         the right null space of the I-th subproblem. */

    /*  S      (output) REAL array, dimension ( N ) if */
    /*         ICOMPQ = 1, and dimension 1 if ICOMPQ = 0. If ICOMPQ = 1 */
    /*         and the I-th subproblem is not square, on exit, S( I ) */
    /*         contains the S-value of a Givens rotation related to */
    /*         the right null space of the I-th subproblem. */

    /*  WORK   (workspace) REAL array, dimension */
    /*         (6 * N + (SMLSIZ + 1)*(SMLSIZ + 1)). */

    /*  IWORK  (workspace) INTEGER array, dimension (7*N). */

    /*  INFO   (output) INTEGER */
    /*          = 0:  successful exit. */
    /*          < 0:  if INFO = -i, the i-th argument had an illegal value. */
    /*          > 0:  if INFO = 1, an singular value did not converge */

    /*  Further Details */
    /*  =============== */

    /*  Based on contributions by */
    /*     Ming Gu and Huan Ren, Computer Science Division, University of */
    /*     California at Berkeley, USA */

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

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

    /*     Test the input parameters. */

    /* Parameter adjustments */
    --d__;
    --e;
    givnum_dim1 = *ldu;
    givnum_offset = 1 + givnum_dim1;
    givnum -= givnum_offset;
    poles_dim1 = *ldu;
    poles_offset = 1 + poles_dim1;
    poles -= poles_offset;
    z_dim1 = *ldu;
    z_offset = 1 + z_dim1;
    z__ -= z_offset;
    difr_dim1 = *ldu;
    difr_offset = 1 + difr_dim1;
    difr -= difr_offset;
    difl_dim1 = *ldu;
    difl_offset = 1 + difl_dim1;
    difl -= difl_offset;
    vt_dim1 = *ldu;
    vt_offset = 1 + vt_dim1;
    vt -= vt_offset;
    u_dim1 = *ldu;
    u_offset = 1 + u_dim1;
    u -= u_offset;
    --k;
    --givptr;
    perm_dim1 = *ldgcol;
    perm_offset = 1 + perm_dim1;
    perm -= perm_offset;
    givcol_dim1 = *ldgcol;
    givcol_offset = 1 + givcol_dim1;
    givcol -= givcol_offset;
    --c__;
    --s;
    --work;
    --iwork;

    /* Function Body */
    *info = 0;

    if (*icompq < 0 || *icompq > 1) {
        *info = -1;
    } else if (*smlsiz < 3) {
        *info = -2;
    } else if (*n < 0) {
        *info = -3;
    } else if (*sqre < 0 || *sqre > 1) {
        *info = -4;
    } else if (*ldu < *n + *sqre) {
        *info = -8;
    } else if (*ldgcol < *n) {
        *info = -17;
    }
    if (*info != 0) {
        i__1 = -(*info);
        xerbla_("SLASDA", &i__1);
        return 0;
    }

    m = *n + *sqre;

    /*     If the input matrix is too small, call SLASDQ to find the SVD. */

    if (*n <= *smlsiz) {
        if (*icompq == 0) {
            slasdq_("U", sqre, n, &c__0, &c__0, &c__0, &d__[1], &e[1], &vt[
                        vt_offset], ldu, &u[u_offset], ldu, &u[u_offset], ldu, &
                    work[1], info);
        } else {
            slasdq_("U", sqre, n, &m, n, &c__0, &d__[1], &e[1], &vt[vt_offset]
                    , ldu, &u[u_offset], ldu, &u[u_offset], ldu, &work[1],
                    info);
        }
        return 0;
    }

    /*     Book-keeping and  set up the computation tree. */

    inode = 1;
    ndiml = inode + *n;
    ndimr = ndiml + *n;
    idxq = ndimr + *n;
    iwk = idxq + *n;

    ncc = 0;
    nru = 0;

    smlszp = *smlsiz + 1;
    vf = 1;
    vl = vf + m;
    nwork1 = vl + m;
    nwork2 = nwork1 + smlszp * smlszp;

    slasdt_(n, &nlvl, &nd, &iwork[inode], &iwork[ndiml], &iwork[ndimr],
            smlsiz);

    /*     for the nodes on bottom level of the tree, solve */
    /*     their subproblems by SLASDQ. */

    ndb1 = (nd + 1) / 2;
    i__1 = nd;
    for (i__ = ndb1; i__ <= i__1; ++i__) {

        /*        IC : center row of each node */
        /*        NL : number of rows of left  subproblem */
        /*        NR : number of rows of right subproblem */
        /*        NLF: starting row of the left   subproblem */
        /*        NRF: starting row of the right  subproblem */

        i1 = i__ - 1;
        ic = iwork[inode + i1];
        nl = iwork[ndiml + i1];
        nlp1 = nl + 1;
        nr = iwork[ndimr + i1];
        nlf = ic - nl;
        nrf = ic + 1;
        idxqi = idxq + nlf - 2;
        vfi = vf + nlf - 1;
        vli = vl + nlf - 1;
        sqrei = 1;
        if (*icompq == 0) {
            slaset_("A", &nlp1, &nlp1, &c_b11, &c_b12, &work[nwork1], &smlszp);
            slasdq_("U", &sqrei, &nl, &nlp1, &nru, &ncc, &d__[nlf], &e[nlf], &
                    work[nwork1], &smlszp, &work[nwork2], &nl, &work[nwork2],
                    &nl, &work[nwork2], info);
            itemp = nwork1 + nl * smlszp;
            scopy_(&nlp1, &work[nwork1], &c__1, &work[vfi], &c__1);
            scopy_(&nlp1, &work[itemp], &c__1, &work[vli], &c__1);
        } else {
            slaset_("A", &nl, &nl, &c_b11, &c_b12, &u[nlf + u_dim1], ldu);
            slaset_("A", &nlp1, &nlp1, &c_b11, &c_b12, &vt[nlf + vt_dim1],
                    ldu);
            slasdq_("U", &sqrei, &nl, &nlp1, &nl, &ncc, &d__[nlf], &e[nlf], &
                    vt[nlf + vt_dim1], ldu, &u[nlf + u_dim1], ldu, &u[nlf +
                            u_dim1], ldu, &work[nwork1], info);
            scopy_(&nlp1, &vt[nlf + vt_dim1], &c__1, &work[vfi], &c__1);
            scopy_(&nlp1, &vt[nlf + nlp1 * vt_dim1], &c__1, &work[vli], &c__1)
            ;
        }
        if (*info != 0) {
            return 0;
        }
        i__2 = nl;
        for (j = 1; j <= i__2; ++j) {
            iwork[idxqi + j] = j;
            /* L10: */
        }
        if (i__ == nd && *sqre == 0) {
            sqrei = 0;
        } else {
            sqrei = 1;
        }
        idxqi += nlp1;
        vfi += nlp1;
        vli += nlp1;
        nrp1 = nr + sqrei;
        if (*icompq == 0) {
            slaset_("A", &nrp1, &nrp1, &c_b11, &c_b12, &work[nwork1], &smlszp);
            slasdq_("U", &sqrei, &nr, &nrp1, &nru, &ncc, &d__[nrf], &e[nrf], &
                    work[nwork1], &smlszp, &work[nwork2], &nr, &work[nwork2],
                    &nr, &work[nwork2], info);
            itemp = nwork1 + (nrp1 - 1) * smlszp;
            scopy_(&nrp1, &work[nwork1], &c__1, &work[vfi], &c__1);
            scopy_(&nrp1, &work[itemp], &c__1, &work[vli], &c__1);
        } else {
            slaset_("A", &nr, &nr, &c_b11, &c_b12, &u[nrf + u_dim1], ldu);
            slaset_("A", &nrp1, &nrp1, &c_b11, &c_b12, &vt[nrf + vt_dim1],
                    ldu);
            slasdq_("U", &sqrei, &nr, &nrp1, &nr, &ncc, &d__[nrf], &e[nrf], &
                    vt[nrf + vt_dim1], ldu, &u[nrf + u_dim1], ldu, &u[nrf +
                            u_dim1], ldu, &work[nwork1], info);
            scopy_(&nrp1, &vt[nrf + vt_dim1], &c__1, &work[vfi], &c__1);
            scopy_(&nrp1, &vt[nrf + nrp1 * vt_dim1], &c__1, &work[vli], &c__1)
            ;
        }
        if (*info != 0) {
            return 0;
        }
        i__2 = nr;
        for (j = 1; j <= i__2; ++j) {
            iwork[idxqi + j] = j;
            /* L20: */
        }
        /* L30: */
    }

    /*     Now conquer each subproblem bottom-up. */

    j = pow_ii(&c__2, &nlvl);
    for (lvl = nlvl; lvl >= 1; --lvl) {
        lvl2 = (lvl << 1) - 1;

        /*        Find the first node LF and last node LL on */
        /*        the current level LVL. */

        if (lvl == 1) {
            lf = 1;
            ll = 1;
        } else {
            i__1 = lvl - 1;
            lf = pow_ii(&c__2, &i__1);
            ll = (lf << 1) - 1;
        }
        i__1 = ll;
        for (i__ = lf; i__ <= i__1; ++i__) {
            im1 = i__ - 1;
            ic = iwork[inode + im1];
            nl = iwork[ndiml + im1];
            nr = iwork[ndimr + im1];
            nlf = ic - nl;
            nrf = ic + 1;
            if (i__ == ll) {
                sqrei = *sqre;
            } else {
                sqrei = 1;
            }
            vfi = vf + nlf - 1;
            vli = vl + nlf - 1;
            idxqi = idxq + nlf - 1;
            alpha = d__[ic];
            beta = e[ic];
            if (*icompq == 0) {
                slasd6_(icompq, &nl, &nr, &sqrei, &d__[nlf], &work[vfi], &
                        work[vli], &alpha, &beta, &iwork[idxqi], &perm[
                            perm_offset], &givptr[1], &givcol[givcol_offset],
                        ldgcol, &givnum[givnum_offset], ldu, &poles[
                            poles_offset], &difl[difl_offset], &difr[difr_offset],
                        &z__[z_offset], &k[1], &c__[1], &s[1], &work[nwork1],
                        &iwork[iwk], info);
            } else {
                --j;
                slasd6_(icompq, &nl, &nr, &sqrei, &d__[nlf], &work[vfi], &
                        work[vli], &alpha, &beta, &iwork[idxqi], &perm[nlf +
                                lvl * perm_dim1], &givptr[j], &givcol[nlf + lvl2 *
                                        givcol_dim1], ldgcol, &givnum[nlf + lvl2 *
                                                givnum_dim1], ldu, &poles[nlf + lvl2 * poles_dim1], &
                        difl[nlf + lvl * difl_dim1], &difr[nlf + lvl2 *
                                difr_dim1], &z__[nlf + lvl * z_dim1], &k[j], &c__[j],
                        &s[j], &work[nwork1], &iwork[iwk], info);
            }
            if (*info != 0) {
                return 0;
            }
            /* L40: */
        }
        /* L50: */
    }

    return 0;

    /*     End of SLASDA */

} /* slasda_ */
예제 #3
0
/* Subroutine */ int slasd0_(integer *n, integer *sqre, real *d__, real *e, 
	real *u, integer *ldu, real *vt, integer *ldvt, integer *smlsiz, 
	integer *iwork, real *work, integer *info)
{
    /* System generated locals */
    integer u_dim1, u_offset, vt_dim1, vt_offset, i__1, i__2;

    /* Builtin functions */
    integer pow_ii(integer *, integer *);

    /* Local variables */
    integer i__, j, m, i1, ic, lf, nd, ll, nl, nr, im1, ncc, nlf, nrf, iwk, 
	    lvl, ndb1, nlp1, nrp1;
    real beta;
    integer idxq, nlvl;
    real alpha;
    integer inode, ndiml, idxqc, ndimr, itemp, sqrei;
    extern /* Subroutine */ int slasd1_(integer *, integer *, integer *, real 
	    *, real *, real *, real *, integer *, real *, integer *, integer *
, integer *, real *, integer *), xerbla_(char *, integer *), slasdq_(char *, integer *, integer *, integer *, integer 
	    *, integer *, real *, real *, real *, integer *, real *, integer *
, real *, integer *, real *, integer *), slasdt_(integer *
, integer *, integer *, integer *, integer *, integer *, integer *
);


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

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

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

/*  Using a divide and conquer approach, SLASD0 computes the singular */
/*  value decomposition (SVD) of a real upper bidiagonal N-by-M */
/*  matrix B with diagonal D and offdiagonal E, where M = N + SQRE. */
/*  The algorithm computes orthogonal matrices U and VT such that */
/*  B = U * S * VT. The singular values S are overwritten on D. */

/*  A related subroutine, SLASDA, computes only the singular values, */
/*  and optionally, the singular vectors in compact form. */

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

/*  N      (input) INTEGER */
/*         On entry, the row dimension of the upper bidiagonal matrix. */
/*         This is also the dimension of the main diagonal array D. */

/*  SQRE   (input) INTEGER */
/*         Specifies the column dimension of the bidiagonal matrix. */
/*         = 0: The bidiagonal matrix has column dimension M = N; */
/*         = 1: The bidiagonal matrix has column dimension M = N+1; */

/*  D      (input/output) REAL array, dimension (N) */
/*         On entry D contains the main diagonal of the bidiagonal */
/*         matrix. */
/*         On exit D, if INFO = 0, contains its singular values. */

/*  E      (input) REAL array, dimension (M-1) */
/*         Contains the subdiagonal entries of the bidiagonal matrix. */
/*         On exit, E has been destroyed. */

/*  U      (output) REAL array, dimension at least (LDQ, N) */
/*         On exit, U contains the left singular vectors. */

/*  LDU    (input) INTEGER */
/*         On entry, leading dimension of U. */

/*  VT     (output) REAL array, dimension at least (LDVT, M) */
/*         On exit, VT' contains the right singular vectors. */

/*  LDVT   (input) INTEGER */
/*         On entry, leading dimension of VT. */

/*  SMLSIZ (input) INTEGER */
/*         On entry, maximum size of the subproblems at the */
/*         bottom of the computation tree. */

/*  IWORK  (workspace) INTEGER array, dimension (8*N) */

/*  WORK   (workspace) REAL array, dimension (3*M**2+2*M) */

/*  INFO   (output) INTEGER */
/*          = 0:  successful exit. */
/*          < 0:  if INFO = -i, the i-th argument had an illegal value. */
/*          > 0:  if INFO = 1, an singular value did not converge */

/*  Further Details */
/*  =============== */

/*  Based on contributions by */
/*     Ming Gu and Huan Ren, Computer Science Division, University of */
/*     California at Berkeley, USA */

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

/*     .. Local Scalars .. */
/*     .. */
/*     .. External Subroutines .. */
/*     .. */
/*     .. Executable Statements .. */

/*     Test the input parameters. */

    /* Parameter adjustments */
    --d__;
    --e;
    u_dim1 = *ldu;
    u_offset = 1 + u_dim1;
    u -= u_offset;
    vt_dim1 = *ldvt;
    vt_offset = 1 + vt_dim1;
    vt -= vt_offset;
    --iwork;
    --work;

    /* Function Body */
    *info = 0;

    if (*n < 0) {
	*info = -1;
    } else if (*sqre < 0 || *sqre > 1) {
	*info = -2;
    }

    m = *n + *sqre;

    if (*ldu < *n) {
	*info = -6;
    } else if (*ldvt < m) {
	*info = -8;
    } else if (*smlsiz < 3) {
	*info = -9;
    }
    if (*info != 0) {
	i__1 = -(*info);
	xerbla_("SLASD0", &i__1);
	return 0;
    }

/*     If the input matrix is too small, call SLASDQ to find the SVD. */

    if (*n <= *smlsiz) {
	slasdq_("U", sqre, n, &m, n, &c__0, &d__[1], &e[1], &vt[vt_offset], 
		ldvt, &u[u_offset], ldu, &u[u_offset], ldu, &work[1], info);
	return 0;
    }

/*     Set up the computation tree. */

    inode = 1;
    ndiml = inode + *n;
    ndimr = ndiml + *n;
    idxq = ndimr + *n;
    iwk = idxq + *n;
    slasdt_(n, &nlvl, &nd, &iwork[inode], &iwork[ndiml], &iwork[ndimr], 
	    smlsiz);

/*     For the nodes on bottom level of the tree, solve */
/*     their subproblems by SLASDQ. */

    ndb1 = (nd + 1) / 2;
    ncc = 0;
    i__1 = nd;
    for (i__ = ndb1; i__ <= i__1; ++i__) {

/*     IC : center row of each node */
/*     NL : number of rows of left  subproblem */
/*     NR : number of rows of right subproblem */
/*     NLF: starting row of the left   subproblem */
/*     NRF: starting row of the right  subproblem */

	i1 = i__ - 1;
	ic = iwork[inode + i1];
	nl = iwork[ndiml + i1];
	nlp1 = nl + 1;
	nr = iwork[ndimr + i1];
	nrp1 = nr + 1;
	nlf = ic - nl;
	nrf = ic + 1;
	sqrei = 1;
	slasdq_("U", &sqrei, &nl, &nlp1, &nl, &ncc, &d__[nlf], &e[nlf], &vt[
		nlf + nlf * vt_dim1], ldvt, &u[nlf + nlf * u_dim1], ldu, &u[
		nlf + nlf * u_dim1], ldu, &work[1], info);
	if (*info != 0) {
	    return 0;
	}
	itemp = idxq + nlf - 2;
	i__2 = nl;
	for (j = 1; j <= i__2; ++j) {
	    iwork[itemp + j] = j;
/* L10: */
	}
	if (i__ == nd) {
	    sqrei = *sqre;
	} else {
	    sqrei = 1;
	}
	nrp1 = nr + sqrei;
	slasdq_("U", &sqrei, &nr, &nrp1, &nr, &ncc, &d__[nrf], &e[nrf], &vt[
		nrf + nrf * vt_dim1], ldvt, &u[nrf + nrf * u_dim1], ldu, &u[
		nrf + nrf * u_dim1], ldu, &work[1], info);
	if (*info != 0) {
	    return 0;
	}
	itemp = idxq + ic;
	i__2 = nr;
	for (j = 1; j <= i__2; ++j) {
	    iwork[itemp + j - 1] = j;
/* L20: */
	}
/* L30: */
    }

/*     Now conquer each subproblem bottom-up. */

    for (lvl = nlvl; lvl >= 1; --lvl) {

/*        Find the first node LF and last node LL on the */
/*        current level LVL. */

	if (lvl == 1) {
	    lf = 1;
	    ll = 1;
	} else {
	    i__1 = lvl - 1;
	    lf = pow_ii(&c__2, &i__1);
	    ll = (lf << 1) - 1;
	}
	i__1 = ll;
	for (i__ = lf; i__ <= i__1; ++i__) {
	    im1 = i__ - 1;
	    ic = iwork[inode + im1];
	    nl = iwork[ndiml + im1];
	    nr = iwork[ndimr + im1];
	    nlf = ic - nl;
	    if (*sqre == 0 && i__ == ll) {
		sqrei = *sqre;
	    } else {
		sqrei = 1;
	    }
	    idxqc = idxq + nlf - 1;
	    alpha = d__[ic];
	    beta = e[ic];
	    slasd1_(&nl, &nr, &sqrei, &d__[nlf], &alpha, &beta, &u[nlf + nlf *
		     u_dim1], ldu, &vt[nlf + nlf * vt_dim1], ldvt, &iwork[
		    idxqc], &iwork[iwk], &work[1], info);
	    if (*info != 0) {
		return 0;
	    }
/* L40: */
	}
/* L50: */
    }

    return 0;

/*     End of SLASD0 */

} /* slasd0_ */
예제 #4
0
파일: slasd0.c 프로젝트: csapng/libflame
/* Subroutine */
int slasd0_(integer *n, integer *sqre, real *d__, real *e, real *u, integer *ldu, real *vt, integer *ldvt, integer *smlsiz, integer *iwork, real *work, integer *info)
{
    /* System generated locals */
    integer u_dim1, u_offset, vt_dim1, vt_offset, i__1, i__2;
    /* Builtin functions */
    integer pow_ii(integer *, integer *);
    /* Local variables */
    integer i__, j, m, i1, ic, lf, nd, ll, nl, nr, im1, ncc, nlf, nrf, iwk, lvl, ndb1, nlp1, nrp1;
    real beta;
    integer idxq, nlvl;
    real alpha;
    integer inode, ndiml, idxqc, ndimr, itemp, sqrei;
    extern /* Subroutine */
    int slasd1_(integer *, integer *, integer *, real *, real *, real *, real *, integer *, real *, integer *, integer * , integer *, real *, integer *), xerbla_(char *, integer *), slasdq_(char *, integer *, integer *, integer *, integer *, integer *, real *, real *, real *, integer *, real *, integer * , real *, integer *, real *, integer *), slasdt_(integer * , integer *, integer *, integer *, integer *, integer *, integer * );
    /* -- LAPACK auxiliary routine (version 3.4.2) -- */
    /* -- LAPACK is a software package provided by Univ. of Tennessee, -- */
    /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */
    /* September 2012 */
    /* .. Scalar Arguments .. */
    /* .. */
    /* .. Array Arguments .. */
    /* .. */
    /* ===================================================================== */
    /* .. Local Scalars .. */
    /* .. */
    /* .. External Subroutines .. */
    /* .. */
    /* .. Executable Statements .. */
    /* Test the input parameters. */
    /* Parameter adjustments */
    --d__;
    --e;
    u_dim1 = *ldu;
    u_offset = 1 + u_dim1;
    u -= u_offset;
    vt_dim1 = *ldvt;
    vt_offset = 1 + vt_dim1;
    vt -= vt_offset;
    --iwork;
    --work;
    /* Function Body */
    *info = 0;
    if (*n < 0)
    {
        *info = -1;
    }
    else if (*sqre < 0 || *sqre > 1)
    {
        *info = -2;
    }
    m = *n + *sqre;
    if (*ldu < *n)
    {
        *info = -6;
    }
    else if (*ldvt < m)
    {
        *info = -8;
    }
    else if (*smlsiz < 3)
    {
        *info = -9;
    }
    if (*info != 0)
    {
        i__1 = -(*info);
        xerbla_("SLASD0", &i__1);
        return 0;
    }
    /* If the input matrix is too small, call SLASDQ to find the SVD. */
    if (*n <= *smlsiz)
    {
        slasdq_("U", sqre, n, &m, n, &c__0, &d__[1], &e[1], &vt[vt_offset], ldvt, &u[u_offset], ldu, &u[u_offset], ldu, &work[1], info);
        return 0;
    }
    /* Set up the computation tree. */
    inode = 1;
    ndiml = inode + *n;
    ndimr = ndiml + *n;
    idxq = ndimr + *n;
    iwk = idxq + *n;
    slasdt_(n, &nlvl, &nd, &iwork[inode], &iwork[ndiml], &iwork[ndimr], smlsiz);
    /* For the nodes on bottom level of the tree, solve */
    /* their subproblems by SLASDQ. */
    ndb1 = (nd + 1) / 2;
    ncc = 0;
    i__1 = nd;
    for (i__ = ndb1;
            i__ <= i__1;
            ++i__)
    {
        /* IC : center row of each node */
        /* NL : number of rows of left subproblem */
        /* NR : number of rows of right subproblem */
        /* NLF: starting row of the left subproblem */
        /* NRF: starting row of the right subproblem */
        i1 = i__ - 1;
        ic = iwork[inode + i1];
        nl = iwork[ndiml + i1];
        nlp1 = nl + 1;
        nr = iwork[ndimr + i1];
        nrp1 = nr + 1;
        nlf = ic - nl;
        nrf = ic + 1;
        sqrei = 1;
        slasdq_("U", &sqrei, &nl, &nlp1, &nl, &ncc, &d__[nlf], &e[nlf], &vt[ nlf + nlf * vt_dim1], ldvt, &u[nlf + nlf * u_dim1], ldu, &u[ nlf + nlf * u_dim1], ldu, &work[1], info);
        if (*info != 0)
        {
            return 0;
        }
        itemp = idxq + nlf - 2;
        i__2 = nl;
        for (j = 1;
                j <= i__2;
                ++j)
        {
            iwork[itemp + j] = j;
            /* L10: */
        }
        if (i__ == nd)
        {
            sqrei = *sqre;
        }
        else
        {
            sqrei = 1;
        }
        nrp1 = nr + sqrei;
        slasdq_("U", &sqrei, &nr, &nrp1, &nr, &ncc, &d__[nrf], &e[nrf], &vt[ nrf + nrf * vt_dim1], ldvt, &u[nrf + nrf * u_dim1], ldu, &u[ nrf + nrf * u_dim1], ldu, &work[1], info);
        if (*info != 0)
        {
            return 0;
        }
        itemp = idxq + ic;
        i__2 = nr;
        for (j = 1;
                j <= i__2;
                ++j)
        {
            iwork[itemp + j - 1] = j;
            /* L20: */
        }
        /* L30: */
    }
    /* Now conquer each subproblem bottom-up. */
    for (lvl = nlvl;
            lvl >= 1;
            --lvl)
    {
        /* Find the first node LF and last node LL on the */
        /* current level LVL. */
        if (lvl == 1)
        {
            lf = 1;
            ll = 1;
        }
        else
        {
            i__1 = lvl - 1;
            lf = pow_ii(&c__2, &i__1);
            ll = (lf << 1) - 1;
        }
        i__1 = ll;
        for (i__ = lf;
                i__ <= i__1;
                ++i__)
        {
            im1 = i__ - 1;
            ic = iwork[inode + im1];
            nl = iwork[ndiml + im1];
            nr = iwork[ndimr + im1];
            nlf = ic - nl;
            if (*sqre == 0 && i__ == ll)
            {
                sqrei = *sqre;
            }
            else
            {
                sqrei = 1;
            }
            idxqc = idxq + nlf - 1;
            alpha = d__[ic];
            beta = e[ic];
            slasd1_(&nl, &nr, &sqrei, &d__[nlf], &alpha, &beta, &u[nlf + nlf * u_dim1], ldu, &vt[nlf + nlf * vt_dim1], ldvt, &iwork[ idxqc], &iwork[iwk], &work[1], info);
            if (*info != 0)
            {
                return 0;
            }
            /* L40: */
        }
        /* L50: */
    }
    return 0;
    /* End of SLASD0 */
}
예제 #5
0
파일: slalsa.c 프로젝트: 353/viewercv
/* Subroutine */ int slalsa_(integer* icompq, integer* smlsiz, integer* n,
                             integer* nrhs, real* b, integer* ldb, real* bx, integer* ldbx, real *
                             u, integer* ldu, real* vt, integer* k, real* difl, real* difr, real *
                             z__, real* poles, integer* givptr, integer* givcol, integer* ldgcol,
                             integer* perm, real* givnum, real* c__, real* s, real* work, integer *
                             iwork, integer* info) {
    /* System generated locals */
    integer givcol_dim1, givcol_offset, perm_dim1, perm_offset, b_dim1,
            b_offset, bx_dim1, bx_offset, difl_dim1, difl_offset, difr_dim1,
            difr_offset, givnum_dim1, givnum_offset, poles_dim1, poles_offset,
            u_dim1, u_offset, vt_dim1, vt_offset, z_dim1, z_offset, i__1,
            i__2;

    /* Builtin functions */
    integer pow_ii(integer*, integer*);

    /* Local variables */
    integer i__, j, i1, ic, lf, nd, ll, nl, nr, im1, nlf, nrf, lvl, ndb1,
            nlp1, lvl2, nrp1, nlvl, sqre, inode, ndiml;
    extern /* Subroutine */ int sgemm_(char*, char*, integer*, integer*,
                                       integer*, real*, real*, integer*, real*, integer*, real*,
                                       real*, integer*);
    integer ndimr;
    extern /* Subroutine */ int scopy_(integer*, real*, integer*, real*,
                                       integer*), slals0_(integer*, integer*, integer*, integer*,
                                               integer*, real*, integer*, real*, integer*, integer*,
                                               integer*, integer*, integer*, real*, integer*, real*, real *
                                               , real*, real*, integer*, real*, real*, real*, integer*),
                                               xerbla_(char*, integer*), slasdt_(integer*, integer*,
                                                       integer*, integer*, integer*, integer*, integer*);


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

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

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

    /*  SLALSA is an itermediate step in solving the least squares problem */
    /*  by computing the SVD of the coefficient matrix in compact form (The */
    /*  singular vectors are computed as products of simple orthorgonal */
    /*  matrices.). */

    /*  If ICOMPQ = 0, SLALSA applies the inverse of the left singular vector */
    /*  matrix of an upper bidiagonal matrix to the right hand side; and if */
    /*  ICOMPQ = 1, SLALSA applies the right singular vector matrix to the */
    /*  right hand side. The singular vector matrices were generated in */
    /*  compact form by SLALSA. */

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


    /*  ICOMPQ (input) INTEGER */
    /*         Specifies whether the left or the right singular vector */
    /*         matrix is involved. */
    /*         = 0: Left singular vector matrix */
    /*         = 1: Right singular vector matrix */

    /*  SMLSIZ (input) INTEGER */
    /*         The maximum size of the subproblems at the bottom of the */
    /*         computation tree. */

    /*  N      (input) INTEGER */
    /*         The row and column dimensions of the upper bidiagonal matrix. */

    /*  NRHS   (input) INTEGER */
    /*         The number of columns of B and BX. NRHS must be at least 1. */

    /*  B      (input/output) REAL array, dimension ( LDB, NRHS ) */
    /*         On input, B contains the right hand sides of the least */
    /*         squares problem in rows 1 through M. */
    /*         On output, B contains the solution X in rows 1 through N. */

    /*  LDB    (input) INTEGER */
    /*         The leading dimension of B in the calling subprogram. */
    /*         LDB must be at least max(1,MAX( M, N ) ). */

    /*  BX     (output) REAL array, dimension ( LDBX, NRHS ) */
    /*         On exit, the result of applying the left or right singular */
    /*         vector matrix to B. */

    /*  LDBX   (input) INTEGER */
    /*         The leading dimension of BX. */

    /*  U      (input) REAL array, dimension ( LDU, SMLSIZ ). */
    /*         On entry, U contains the left singular vector matrices of all */
    /*         subproblems at the bottom level. */

    /*  LDU    (input) INTEGER, LDU = > N. */
    /*         The leading dimension of arrays U, VT, DIFL, DIFR, */
    /*         POLES, GIVNUM, and Z. */

    /*  VT     (input) REAL array, dimension ( LDU, SMLSIZ+1 ). */
    /*         On entry, VT' contains the right singular vector matrices of */
    /*         all subproblems at the bottom level. */

    /*  K      (input) INTEGER array, dimension ( N ). */

    /*  DIFL   (input) REAL array, dimension ( LDU, NLVL ). */
    /*         where NLVL = INT(log_2 (N/(SMLSIZ+1))) + 1. */

    /*  DIFR   (input) REAL array, dimension ( LDU, 2 * NLVL ). */
    /*         On entry, DIFL(*, I) and DIFR(*, 2 * I -1) record */
    /*         distances between singular values on the I-th level and */
    /*         singular values on the (I -1)-th level, and DIFR(*, 2 * I) */
    /*         record the normalizing factors of the right singular vectors */
    /*         matrices of subproblems on I-th level. */

    /*  Z      (input) REAL array, dimension ( LDU, NLVL ). */
    /*         On entry, Z(1, I) contains the components of the deflation- */
    /*         adjusted updating row vector for subproblems on the I-th */
    /*         level. */

    /*  POLES  (input) REAL array, dimension ( LDU, 2 * NLVL ). */
    /*         On entry, POLES(*, 2 * I -1: 2 * I) contains the new and old */
    /*         singular values involved in the secular equations on the I-th */
    /*         level. */

    /*  GIVPTR (input) INTEGER array, dimension ( N ). */
    /*         On entry, GIVPTR( I ) records the number of Givens */
    /*         rotations performed on the I-th problem on the computation */
    /*         tree. */

    /*  GIVCOL (input) INTEGER array, dimension ( LDGCOL, 2 * NLVL ). */
    /*         On entry, for each I, GIVCOL(*, 2 * I - 1: 2 * I) records the */
    /*         locations of Givens rotations performed on the I-th level on */
    /*         the computation tree. */

    /*  LDGCOL (input) INTEGER, LDGCOL = > N. */
    /*         The leading dimension of arrays GIVCOL and PERM. */

    /*  PERM   (input) INTEGER array, dimension ( LDGCOL, NLVL ). */
    /*         On entry, PERM(*, I) records permutations done on the I-th */
    /*         level of the computation tree. */

    /*  GIVNUM (input) REAL array, dimension ( LDU, 2 * NLVL ). */
    /*         On entry, GIVNUM(*, 2 *I -1 : 2 * I) records the C- and S- */
    /*         values of Givens rotations performed on the I-th level on the */
    /*         computation tree. */

    /*  C      (input) REAL array, dimension ( N ). */
    /*         On entry, if the I-th subproblem is not square, */
    /*         C( I ) contains the C-value of a Givens rotation related to */
    /*         the right null space of the I-th subproblem. */

    /*  S      (input) REAL array, dimension ( N ). */
    /*         On entry, if the I-th subproblem is not square, */
    /*         S( I ) contains the S-value of a Givens rotation related to */
    /*         the right null space of the I-th subproblem. */

    /*  WORK   (workspace) REAL array. */
    /*         The dimension must be at least N. */

    /*  IWORK  (workspace) INTEGER array. */
    /*         The dimension must be at least 3 * N */

    /*  INFO   (output) INTEGER */
    /*          = 0:  successful exit. */
    /*          < 0:  if INFO = -i, the i-th argument had an illegal value. */

    /*  Further Details */
    /*  =============== */

    /*  Based on contributions by */
    /*     Ming Gu and Ren-Cang Li, Computer Science Division, University of */
    /*       California at Berkeley, USA */
    /*     Osni Marques, LBNL/NERSC, USA */

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

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

    /*     Test the input parameters. */

    /* Parameter adjustments */
    b_dim1 = *ldb;
    b_offset = 1 + b_dim1;
    b -= b_offset;
    bx_dim1 = *ldbx;
    bx_offset = 1 + bx_dim1;
    bx -= bx_offset;
    givnum_dim1 = *ldu;
    givnum_offset = 1 + givnum_dim1;
    givnum -= givnum_offset;
    poles_dim1 = *ldu;
    poles_offset = 1 + poles_dim1;
    poles -= poles_offset;
    z_dim1 = *ldu;
    z_offset = 1 + z_dim1;
    z__ -= z_offset;
    difr_dim1 = *ldu;
    difr_offset = 1 + difr_dim1;
    difr -= difr_offset;
    difl_dim1 = *ldu;
    difl_offset = 1 + difl_dim1;
    difl -= difl_offset;
    vt_dim1 = *ldu;
    vt_offset = 1 + vt_dim1;
    vt -= vt_offset;
    u_dim1 = *ldu;
    u_offset = 1 + u_dim1;
    u -= u_offset;
    --k;
    --givptr;
    perm_dim1 = *ldgcol;
    perm_offset = 1 + perm_dim1;
    perm -= perm_offset;
    givcol_dim1 = *ldgcol;
    givcol_offset = 1 + givcol_dim1;
    givcol -= givcol_offset;
    --c__;
    --s;
    --work;
    --iwork;

    /* Function Body */
    *info = 0;

    if (*icompq < 0 || *icompq > 1) {
        *info = -1;
    } else if (*smlsiz < 3) {
        *info = -2;
    } else if (*n < *smlsiz) {
        *info = -3;
    } else if (*nrhs < 1) {
        *info = -4;
    } else if (*ldb < *n) {
        *info = -6;
    } else if (*ldbx < *n) {
        *info = -8;
    } else if (*ldu < *n) {
        *info = -10;
    } else if (*ldgcol < *n) {
        *info = -19;
    }
    if (*info != 0) {
        i__1 = -(*info);
        xerbla_("SLALSA", &i__1);
        return 0;
    }

    /*     Book-keeping and  setting up the computation tree. */

    inode = 1;
    ndiml = inode + *n;
    ndimr = ndiml + *n;

    slasdt_(n, &nlvl, &nd, &iwork[inode], &iwork[ndiml], &iwork[ndimr],
            smlsiz);

    /*     The following code applies back the left singular vector factors. */
    /*     For applying back the right singular vector factors, go to 50. */

    if (*icompq == 1) {
        goto L50;
    }

    /*     The nodes on the bottom level of the tree were solved */
    /*     by SLASDQ. The corresponding left and right singular vector */
    /*     matrices are in explicit form. First apply back the left */
    /*     singular vector matrices. */

    ndb1 = (nd + 1) / 2;
    i__1 = nd;
    for (i__ = ndb1; i__ <= i__1; ++i__) {

        /*        IC : center row of each node */
        /*        NL : number of rows of left  subproblem */
        /*        NR : number of rows of right subproblem */
        /*        NLF: starting row of the left   subproblem */
        /*        NRF: starting row of the right  subproblem */

        i1 = i__ - 1;
        ic = iwork[inode + i1];
        nl = iwork[ndiml + i1];
        nr = iwork[ndimr + i1];
        nlf = ic - nl;
        nrf = ic + 1;
        sgemm_("T", "N", &nl, nrhs, &nl, &c_b7, &u[nlf + u_dim1], ldu, &b[nlf
                + b_dim1], ldb, &c_b8, &bx[nlf + bx_dim1], ldbx);
        sgemm_("T", "N", &nr, nrhs, &nr, &c_b7, &u[nrf + u_dim1], ldu, &b[nrf
                + b_dim1], ldb, &c_b8, &bx[nrf + bx_dim1], ldbx);
        /* L10: */
    }

    /*     Next copy the rows of B that correspond to unchanged rows */
    /*     in the bidiagonal matrix to BX. */

    i__1 = nd;
    for (i__ = 1; i__ <= i__1; ++i__) {
        ic = iwork[inode + i__ - 1];
        scopy_(nrhs, &b[ic + b_dim1], ldb, &bx[ic + bx_dim1], ldbx);
        /* L20: */
    }

    /*     Finally go through the left singular vector matrices of all */
    /*     the other subproblems bottom-up on the tree. */

    j = pow_ii(&c__2, &nlvl);
    sqre = 0;

    for (lvl = nlvl; lvl >= 1; --lvl) {
        lvl2 = (lvl << 1) - 1;

        /*        find the first node LF and last node LL on */
        /*        the current level LVL */

        if (lvl == 1) {
            lf = 1;
            ll = 1;
        } else {
            i__1 = lvl - 1;
            lf = pow_ii(&c__2, &i__1);
            ll = (lf << 1) - 1;
        }
        i__1 = ll;
        for (i__ = lf; i__ <= i__1; ++i__) {
            im1 = i__ - 1;
            ic = iwork[inode + im1];
            nl = iwork[ndiml + im1];
            nr = iwork[ndimr + im1];
            nlf = ic - nl;
            nrf = ic + 1;
            --j;
            slals0_(icompq, &nl, &nr, &sqre, nrhs, &bx[nlf + bx_dim1], ldbx, &
                    b[nlf + b_dim1], ldb, &perm[nlf + lvl * perm_dim1], &
                    givptr[j], &givcol[nlf + lvl2 * givcol_dim1], ldgcol, &
                    givnum[nlf + lvl2 * givnum_dim1], ldu, &poles[nlf + lvl2 *
                            poles_dim1], &difl[nlf + lvl * difl_dim1], &difr[nlf +
                                    lvl2 * difr_dim1], &z__[nlf + lvl * z_dim1], &k[j], &c__[
                        j], &s[j], &work[1], info);
            /* L30: */
        }
        /* L40: */
    }
    goto L90;

    /*     ICOMPQ = 1: applying back the right singular vector factors. */

L50:

    /*     First now go through the right singular vector matrices of all */
    /*     the tree nodes top-down. */

    j = 0;
    i__1 = nlvl;
    for (lvl = 1; lvl <= i__1; ++lvl) {
        lvl2 = (lvl << 1) - 1;

        /*        Find the first node LF and last node LL on */
        /*        the current level LVL. */

        if (lvl == 1) {
            lf = 1;
            ll = 1;
        } else {
            i__2 = lvl - 1;
            lf = pow_ii(&c__2, &i__2);
            ll = (lf << 1) - 1;
        }
        i__2 = lf;
        for (i__ = ll; i__ >= i__2; --i__) {
            im1 = i__ - 1;
            ic = iwork[inode + im1];
            nl = iwork[ndiml + im1];
            nr = iwork[ndimr + im1];
            nlf = ic - nl;
            nrf = ic + 1;
            if (i__ == ll) {
                sqre = 0;
            } else {
                sqre = 1;
            }
            ++j;
            slals0_(icompq, &nl, &nr, &sqre, nrhs, &b[nlf + b_dim1], ldb, &bx[
                        nlf + bx_dim1], ldbx, &perm[nlf + lvl * perm_dim1], &
                    givptr[j], &givcol[nlf + lvl2 * givcol_dim1], ldgcol, &
                    givnum[nlf + lvl2 * givnum_dim1], ldu, &poles[nlf + lvl2 *
                            poles_dim1], &difl[nlf + lvl * difl_dim1], &difr[nlf +
                                    lvl2 * difr_dim1], &z__[nlf + lvl * z_dim1], &k[j], &c__[
                        j], &s[j], &work[1], info);
            /* L60: */
        }
        /* L70: */
    }

    /*     The nodes on the bottom level of the tree were solved */
    /*     by SLASDQ. The corresponding right singular vector */
    /*     matrices are in explicit form. Apply them back. */

    ndb1 = (nd + 1) / 2;
    i__1 = nd;
    for (i__ = ndb1; i__ <= i__1; ++i__) {
        i1 = i__ - 1;
        ic = iwork[inode + i1];
        nl = iwork[ndiml + i1];
        nr = iwork[ndimr + i1];
        nlp1 = nl + 1;
        if (i__ == nd) {
            nrp1 = nr;
        } else {
            nrp1 = nr + 1;
        }
        nlf = ic - nl;
        nrf = ic + 1;
        sgemm_("T", "N", &nlp1, nrhs, &nlp1, &c_b7, &vt[nlf + vt_dim1], ldu, &
               b[nlf + b_dim1], ldb, &c_b8, &bx[nlf + bx_dim1], ldbx);
        sgemm_("T", "N", &nrp1, nrhs, &nrp1, &c_b7, &vt[nrf + vt_dim1], ldu, &
               b[nrf + b_dim1], ldb, &c_b8, &bx[nrf + bx_dim1], ldbx);
        /* L80: */
    }

L90:

    return 0;

    /*     End of SLALSA */

} /* slalsa_ */