/* Multiply Q with a matrix using the output of geqrf */ void THLapack_(ormqr)(char side, char trans, int m, int n, int k, real *a, int lda, real *tau, real *c, int ldc, real *work, int lwork, int *info) { #ifdef USE_LAPACK #if defined(TH_REAL_IS_DOUBLE) dormqr_(&side, &trans, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, info); #else sormqr_(&side, &trans, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, info); #endif #else THError("ormqr: Lapack library not found in compile time\n"); #endif }
DLLEXPORT MKL_INT s_qr_solve_factored(MKL_INT m, MKL_INT n, MKL_INT bn, float r[], float b[], float tau[], float x[], float work[], MKL_INT len) { char side ='L'; char tran = 'T'; MKL_INT info = 0; float* clone_b = new float[m*bn]; std::memcpy(clone_b, b, m*bn*sizeof(float)); sormqr_(&side, &tran, &m, &bn, &n, r, &m, tau, clone_b, &m, work, &len, &info); cblas_strsm(CblasColMajor, CblasLeft, CblasUpper, CblasNoTrans, CblasNonUnit, n, bn, 1.0, r, m, clone_b, m); for (MKL_INT i = 0; i < n; ++i) { for (MKL_INT j = 0; j < bn; ++j) { x[j * n + i] = clone_b[j * m + i]; } } delete[] clone_b; return info; }
DLLEXPORT int s_qr_solve(int m, int n, int bn, float r[], float b[], float x[], float work[], int len) { int info = 0; float* clone_r = new float[m*n]; memcpy(clone_r, r, m*n*sizeof(float)); float* tau = new float[max(1, min(m,n))]; sgeqrf_(&m, &n, clone_r, &m, tau, work, &len, &info); if (info != 0) { delete[] clone_r; delete[] tau; return info; } float* clone_b = new float[m*bn]; memcpy(clone_b, b, m*bn*sizeof(float)); char side ='L'; char tran = 'T'; sormqr_(&side, &tran, &m, &bn, &n, clone_r, &m, tau, clone_b, &m, work, &len, &info); cblas_strsm(CblasColMajor, CblasLeft, CblasUpper, CblasNoTrans, CblasNonUnit, n, bn, 1.0, clone_r, m, clone_b, m); for (int i = 0; i < n; ++i) { for (int j = 0; j < bn; ++j) { x[j * n + i] = clone_b[j * m + i]; } } delete[] clone_r; delete[] tau; delete[] clone_b; return info; }
/* Subroutine */ int sggglm_(integer *n, integer *m, integer *p, real *a, integer *lda, real *b, integer *ldb, real *d__, real *x, real *y, real *work, integer *lwork, integer *info) { /* -- LAPACK driver 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 ======= SGGGLM solves a general Gauss-Markov linear model (GLM) problem: minimize || y ||_2 subject to d = A*x + B*y x where A is an N-by-M matrix, B is an N-by-P matrix, and d is a given N-vector. It is assumed that M <= N <= M+P, and rank(A) = M and rank( A B ) = N. Under these assumptions, the constrained equation is always consistent, and there is a unique solution x and a minimal 2-norm solution y, which is obtained using a generalized QR factorization of A and B. In particular, if matrix B is square nonsingular, then the problem GLM is equivalent to the following weighted linear least squares problem minimize || inv(B)*(d-A*x) ||_2 x where inv(B) denotes the inverse of B. Arguments ========= N (input) INTEGER The number of rows of the matrices A and B. N >= 0. M (input) INTEGER The number of columns of the matrix A. 0 <= M <= N. P (input) INTEGER The number of columns of the matrix B. P >= N-M. A (input/output) REAL array, dimension (LDA,M) On entry, the N-by-M matrix A. On exit, A is destroyed. LDA (input) INTEGER The leading dimension of the array A. LDA >= max(1,N). B (input/output) REAL array, dimension (LDB,P) On entry, the N-by-P matrix B. On exit, B is destroyed. LDB (input) INTEGER The leading dimension of the array B. LDB >= max(1,N). D (input/output) REAL array, dimension (N) On entry, D is the left hand side of the GLM equation. On exit, D is destroyed. X (output) REAL array, dimension (M) Y (output) REAL array, dimension (P) On exit, X and Y are the solutions of the GLM problem. WORK (workspace/output) REAL array, dimension (LWORK) On exit, if INFO = 0, WORK(1) returns the optimal LWORK. LWORK (input) INTEGER The dimension of the array WORK. LWORK >= max(1,N+M+P). For optimum performance, LWORK >= M+min(N,P)+max(N,P)*NB, where NB is an upper bound for the optimal blocksizes for SGEQRF, SGERQF, SORMQR and SORMRQ. If LWORK = -1, then a workspace query is assumed; the routine only calculates the optimal size of the WORK array, returns this value as the first entry of the WORK array, and no error message related to LWORK is issued by XERBLA. INFO (output) INTEGER = 0: successful exit. < 0: if INFO = -i, the i-th argument had an illegal value. =================================================================== Test the input parameters Parameter adjustments */ /* Table of constant values */ static integer c__1 = 1; static integer c_n1 = -1; static real c_b32 = -1.f; static real c_b34 = 1.f; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, i__1, i__2, i__3, i__4; /* Local variables */ static integer lopt, i__; extern /* Subroutine */ int sgemv_(char *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *), scopy_(integer *, real *, integer *, real *, integer *), strsv_(char *, char *, char *, integer *, real *, integer *, real *, integer *); static integer nb, np; extern /* Subroutine */ int xerbla_(char *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *, ftnlen, ftnlen); extern /* Subroutine */ int sggqrf_(integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, real *, integer * , integer *); static integer nb1, nb2, nb3, nb4, lwkopt; static logical lquery; extern /* Subroutine */ int sormqr_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *), sormrq_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real * , integer *, real *, integer *, integer *); #define b_ref(a_1,a_2) b[(a_2)*b_dim1 + a_1] a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; b_dim1 = *ldb; b_offset = 1 + b_dim1 * 1; b -= b_offset; --d__; --x; --y; --work; /* Function Body */ *info = 0; np = min(*n,*p); nb1 = ilaenv_(&c__1, "SGEQRF", " ", n, m, &c_n1, &c_n1, (ftnlen)6, ( ftnlen)1); nb2 = ilaenv_(&c__1, "SGERQF", " ", n, m, &c_n1, &c_n1, (ftnlen)6, ( ftnlen)1); nb3 = ilaenv_(&c__1, "SORMQR", " ", n, m, p, &c_n1, (ftnlen)6, (ftnlen)1); nb4 = ilaenv_(&c__1, "SORMRQ", " ", n, m, p, &c_n1, (ftnlen)6, (ftnlen)1); /* Computing MAX */ i__1 = max(nb1,nb2), i__1 = max(i__1,nb3); nb = max(i__1,nb4); lwkopt = *m + np + max(*n,*p) * nb; work[1] = (real) lwkopt; lquery = *lwork == -1; if (*n < 0) { *info = -1; } else if (*m < 0 || *m > *n) { *info = -2; } else if (*p < 0 || *p < *n - *m) { *info = -3; } else if (*lda < max(1,*n)) { *info = -5; } else if (*ldb < max(1,*n)) { *info = -7; } else /* if(complicated condition) */ { /* Computing MAX */ i__1 = 1, i__2 = *n + *m + *p; if (*lwork < max(i__1,i__2) && ! lquery) { *info = -12; } } if (*info != 0) { i__1 = -(*info); xerbla_("SGGGLM", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*n == 0) { return 0; } /* Compute the GQR factorization of matrices A and B: Q'*A = ( R11 ) M, Q'*B*Z' = ( T11 T12 ) M ( 0 ) N-M ( 0 T22 ) N-M M M+P-N N-M where R11 and T22 are upper triangular, and Q and Z are orthogonal. */ i__1 = *lwork - *m - np; sggqrf_(n, m, p, &a[a_offset], lda, &work[1], &b[b_offset], ldb, &work[*m + 1], &work[*m + np + 1], &i__1, info); lopt = work[*m + np + 1]; /* Update left-hand-side vector d = Q'*d = ( d1 ) M ( d2 ) N-M */ i__1 = max(1,*n); i__2 = *lwork - *m - np; sormqr_("Left", "Transpose", n, &c__1, m, &a[a_offset], lda, &work[1], & d__[1], &i__1, &work[*m + np + 1], &i__2, info); /* Computing MAX */ i__1 = lopt, i__2 = (integer) work[*m + np + 1]; lopt = max(i__1,i__2); /* Solve T22*y2 = d2 for y2 */ i__1 = *n - *m; strsv_("Upper", "No transpose", "Non unit", &i__1, &b_ref(*m + 1, *m + *p - *n + 1), ldb, &d__[*m + 1], &c__1); i__1 = *n - *m; scopy_(&i__1, &d__[*m + 1], &c__1, &y[*m + *p - *n + 1], &c__1); /* Set y1 = 0 */ i__1 = *m + *p - *n; for (i__ = 1; i__ <= i__1; ++i__) { y[i__] = 0.f; /* L10: */ } /* Update d1 = d1 - T12*y2 */ i__1 = *n - *m; sgemv_("No transpose", m, &i__1, &c_b32, &b_ref(1, *m + *p - *n + 1), ldb, &y[*m + *p - *n + 1], &c__1, &c_b34, &d__[1], &c__1); /* Solve triangular system: R11*x = d1 */ strsv_("Upper", "No Transpose", "Non unit", m, &a[a_offset], lda, &d__[1], &c__1); /* Copy D to X */ scopy_(m, &d__[1], &c__1, &x[1], &c__1); /* Backward transformation y = Z'*y Computing MAX */ i__1 = 1, i__2 = *n - *p + 1; i__3 = max(1,*p); i__4 = *lwork - *m - np; sormrq_("Left", "Transpose", p, &c__1, &np, &b_ref(max(i__1,i__2), 1), ldb, &work[*m + 1], &y[1], &i__3, &work[*m + np + 1], &i__4, info); /* Computing MAX */ i__1 = lopt, i__2 = (integer) work[*m + np + 1]; work[1] = (real) (*m + np + max(i__1,i__2)); return 0; /* End of SGGGLM */ } /* sggglm_ */
/* Subroutine */ int sgegv_(char *jobvl, char *jobvr, integer *n, real *a, integer *lda, real *b, integer *ldb, real *alphar, real *alphai, real *beta, real *vl, integer *ldvl, real *vr, integer *ldvr, real *work, integer *lwork, integer *info) { /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, vl_dim1, vl_offset, vr_dim1, vr_offset, i__1, i__2; real r__1, r__2, r__3, r__4; /* Local variables */ integer jc, nb, in, jr, nb1, nb2, nb3, ihi, ilo; real eps; logical ilv; real absb, anrm, bnrm; integer itau; real temp; logical ilvl, ilvr; integer lopt; real anrm1, anrm2, bnrm1, bnrm2, absai, scale, absar, sbeta; integer ileft, iinfo, icols, iwork, irows; real salfai; real salfar; real safmin; real safmax; char chtemp[1]; logical ldumma[1]; integer ijobvl, iright; logical ilimit; integer ijobvr; real onepls; integer lwkmin; integer lwkopt; logical lquery; /* -- LAPACK driver routine (version 3.2) -- */ /* November 2006 */ /* Purpose */ /* ======= */ /* This routine is deprecated and has been replaced by routine SGGEV. */ /* SGEGV computes the eigenvalues and, optionally, the left and/or right */ /* eigenvectors of a real matrix pair (A,B). */ /* Given two square matrices A and B, */ /* the generalized nonsymmetric eigenvalue problem (GNEP) is to find the */ /* eigenvalues lambda and corresponding (non-zero) eigenvectors x such */ /* that */ /* A*x = lambda*B*x. */ /* An alternate form is to find the eigenvalues mu and corresponding */ /* eigenvectors y such that */ /* mu*A*y = B*y. */ /* These two forms are equivalent with mu = 1/lambda and x = y if */ /* neither lambda nor mu is zero. In order to deal with the case that */ /* lambda or mu is zero or small, two values alpha and beta are returned */ /* for each eigenvalue, such that lambda = alpha/beta and */ /* mu = beta/alpha. */ /* The vectors x and y in the above equations are right eigenvectors of */ /* the matrix pair (A,B). Vectors u and v satisfying */ /* u**H*A = lambda*u**H*B or mu*v**H*A = v**H*B */ /* are left eigenvectors of (A,B). */ /* Note: this routine performs "full balancing" on A and B -- see */ /* "Further Details", below. */ /* Arguments */ /* ========= */ /* JOBVL (input) CHARACTER*1 */ /* = 'N': do not compute the left generalized eigenvectors; */ /* = 'V': compute the left generalized eigenvectors (returned */ /* in VL). */ /* JOBVR (input) CHARACTER*1 */ /* = 'N': do not compute the right generalized eigenvectors; */ /* = 'V': compute the right generalized eigenvectors (returned */ /* in VR). */ /* N (input) INTEGER */ /* The order of the matrices A, B, VL, and VR. N >= 0. */ /* A (input/output) REAL array, dimension (LDA, N) */ /* On entry, the matrix A. */ /* If JOBVL = 'V' or JOBVR = 'V', then on exit A */ /* contains the real Schur form of A from the generalized Schur */ /* factorization of the pair (A,B) after balancing. */ /* If no eigenvectors were computed, then only the diagonal */ /* blocks from the Schur form will be correct. See SGGHRD and */ /* SHGEQZ for details. */ /* LDA (input) INTEGER */ /* The leading dimension of A. LDA >= max(1,N). */ /* B (input/output) REAL array, dimension (LDB, N) */ /* On entry, the matrix B. */ /* If JOBVL = 'V' or JOBVR = 'V', then on exit B contains the */ /* upper triangular matrix obtained from B in the generalized */ /* Schur factorization of the pair (A,B) after balancing. */ /* If no eigenvectors were computed, then only those elements of */ /* B corresponding to the diagonal blocks from the Schur form of */ /* A will be correct. See SGGHRD and SHGEQZ for details. */ /* LDB (input) INTEGER */ /* The leading dimension of B. LDB >= max(1,N). */ /* ALPHAR (output) REAL array, dimension (N) */ /* The real parts of each scalar alpha defining an eigenvalue of */ /* GNEP. */ /* ALPHAI (output) REAL array, dimension (N) */ /* The imaginary parts of each scalar alpha defining an */ /* eigenvalue of GNEP. If ALPHAI(j) is zero, then the j-th */ /* eigenvalue is real; if positive, then the j-th and */ /* (j+1)-st eigenvalues are a complex conjugate pair, with */ /* ALPHAI(j+1) = -ALPHAI(j). */ /* BETA (output) REAL array, dimension (N) */ /* The scalars beta that define the eigenvalues of GNEP. */ /* Together, the quantities alpha = (ALPHAR(j),ALPHAI(j)) and */ /* beta = BETA(j) represent the j-th eigenvalue of the matrix */ /* pair (A,B), in one of the forms lambda = alpha/beta or */ /* mu = beta/alpha. Since either lambda or mu may overflow, */ /* they should not, in general, be computed. */ /* VL (output) REAL array, dimension (LDVL,N) */ /* If JOBVL = 'V', the left eigenvectors u(j) are stored */ /* in the columns of VL, in the same order as their eigenvalues. */ /* If the j-th eigenvalue is real, then u(j) = VL(:,j). */ /* If the j-th and (j+1)-st eigenvalues form a complex conjugate */ /* pair, then */ /* u(j) = VL(:,j) + i*VL(:,j+1) */ /* and */ /* u(j+1) = VL(:,j) - i*VL(:,j+1). */ /* Each eigenvector is scaled so that its largest component has */ /* abs(real part) + abs(imag. part) = 1, except for eigenvectors */ /* corresponding to an eigenvalue with alpha = beta = 0, which */ /* are set to zero. */ /* Not referenced if JOBVL = 'N'. */ /* LDVL (input) INTEGER */ /* The leading dimension of the matrix VL. LDVL >= 1, and */ /* if JOBVL = 'V', LDVL >= N. */ /* VR (output) REAL array, dimension (LDVR,N) */ /* If JOBVR = 'V', the right eigenvectors x(j) are stored */ /* in the columns of VR, in the same order as their eigenvalues. */ /* If the j-th eigenvalue is real, then x(j) = VR(:,j). */ /* If the j-th and (j+1)-st eigenvalues form a complex conjugate */ /* pair, then */ /* x(j) = VR(:,j) + i*VR(:,j+1) */ /* and */ /* x(j+1) = VR(:,j) - i*VR(:,j+1). */ /* Each eigenvector is scaled so that its largest component has */ /* abs(real part) + abs(imag. part) = 1, except for eigenvalues */ /* corresponding to an eigenvalue with alpha = beta = 0, which */ /* are set to zero. */ /* Not referenced if JOBVR = 'N'. */ /* LDVR (input) INTEGER */ /* The leading dimension of the matrix VR. LDVR >= 1, and */ /* if JOBVR = 'V', LDVR >= N. */ /* WORK (workspace/output) REAL array, dimension (MAX(1,LWORK)) */ /* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */ /* LWORK (input) INTEGER */ /* The dimension of the array WORK. LWORK >= max(1,8*N). */ /* For good performance, LWORK must generally be larger. */ /* To compute the optimal value of LWORK, call ILAENV to get */ /* blocksizes (for SGEQRF, SORMQR, and SORGQR.) Then compute: */ /* NB -- MAX of the blocksizes for SGEQRF, SORMQR, and SORGQR; */ /* The optimal LWORK is: */ /* 2*N + MAX( 6*N, N*(NB+1) ). */ /* If LWORK = -1, then a workspace query is assumed; the routine */ /* only calculates the optimal size of the WORK array, returns */ /* this value as the first entry of the WORK array, and no error */ /* message related to LWORK is issued by XERBLA. */ /* INFO (output) INTEGER */ /* = 0: successful exit */ /* < 0: if INFO = -i, the i-th argument had an illegal value. */ /* The QZ iteration failed. No eigenvectors have been */ /* calculated, but ALPHAR(j), ALPHAI(j), and BETA(j) */ /* > N: errors that usually indicate LAPACK problems: */ /* =N+1: error return from SGGBAL */ /* =N+2: error return from SGEQRF */ /* =N+3: error return from SORMQR */ /* =N+4: error return from SORGQR */ /* =N+5: error return from SGGHRD */ /* =N+6: error return from SHGEQZ (other than failed */ /* iteration) */ /* =N+7: error return from STGEVC */ /* =N+8: error return from SGGBAK (computing VL) */ /* =N+9: error return from SGGBAK (computing VR) */ /* =N+10: error return from SLASCL (various calls) */ /* Further Details */ /* =============== */ /* Balancing */ /* --------- */ /* This driver calls SGGBAL to both permute and scale rows and columns */ /* of A and B. The permutations PL and PR are chosen so that PL*A*PR */ /* and PL*B*R will be upper triangular except for the diagonal blocks */ /* A(i:j,i:j) and B(i:j,i:j), with i and j as close together as */ /* possible. The diagonal scaling matrices DL and DR are chosen so */ /* that the pair DL*PL*A*PR*DR, DL*PL*B*PR*DR have elements close to */ /* one (except for the elements that start out zero.) */ /* After the eigenvalues and eigenvectors of the balanced matrices */ /* have been computed, SGGBAK transforms the eigenvectors back to what */ /* they would have been (in perfect arithmetic) if they had not been */ /* balanced. */ /* Contents of A and B on Exit */ /* -------- -- - --- - -- ---- */ /* If any eigenvectors are computed (either JOBVL='V' or JOBVR='V' or */ /* both), then on exit the arrays A and B will contain the real Schur */ /* form[*] of the "balanced" versions of A and B. If no eigenvectors */ /* are computed, then only the diagonal blocks will be correct. */ /* [*] See SHGEQZ, SGEGS, or read the book "Matrix Computations", */ /* by Golub & van Loan, pub. by Johns Hopkins U. Press. */ /* ===================================================================== */ /* Decode the input arguments */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; b_dim1 = *ldb; b_offset = 1 + b_dim1; b -= b_offset; --alphar; --alphai; --beta; vl_dim1 = *ldvl; vl_offset = 1 + vl_dim1; vl -= vl_offset; vr_dim1 = *ldvr; vr_offset = 1 + vr_dim1; vr -= vr_offset; --work; /* Function Body */ if (lsame_(jobvl, "N")) { ijobvl = 1; ilvl = FALSE_; } else if (lsame_(jobvl, "V")) { ijobvl = 2; ilvl = TRUE_; } else { ijobvl = -1; ilvl = FALSE_; } if (lsame_(jobvr, "N")) { ijobvr = 1; ilvr = FALSE_; } else if (lsame_(jobvr, "V")) { ijobvr = 2; ilvr = TRUE_; } else { ijobvr = -1; ilvr = FALSE_; } ilv = ilvl || ilvr; /* Test the input arguments */ /* Computing MAX */ i__1 = *n << 3; lwkmin = max(i__1,1); lwkopt = lwkmin; work[1] = (real) lwkopt; lquery = *lwork == -1; *info = 0; if (ijobvl <= 0) { *info = -1; } else if (ijobvr <= 0) { *info = -2; } else if (*n < 0) { *info = -3; } else if (*lda < max(1,*n)) { *info = -5; } else if (*ldb < max(1,*n)) { *info = -7; } else if (*ldvl < 1 || ilvl && *ldvl < *n) { *info = -12; } else if (*ldvr < 1 || ilvr && *ldvr < *n) { *info = -14; } else if (*lwork < lwkmin && ! lquery) { *info = -16; } if (*info == 0) { nb1 = ilaenv_(&c__1, "SGEQRF", " ", n, n, &c_n1, &c_n1); nb2 = ilaenv_(&c__1, "SORMQR", " ", n, n, n, &c_n1); nb3 = ilaenv_(&c__1, "SORGQR", " ", n, n, n, &c_n1); /* Computing MAX */ i__1 = max(nb1,nb2); nb = max(i__1,nb3); /* Computing MAX */ i__1 = *n * 6, i__2 = *n * (nb + 1); lopt = (*n << 1) + max(i__1,i__2); work[1] = (real) lopt; } if (*info != 0) { i__1 = -(*info); xerbla_("SGEGV ", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*n == 0) { return 0; } /* Get machine constants */ eps = slamch_("E") * slamch_("B"); safmin = slamch_("S"); safmin += safmin; safmax = 1.f / safmin; onepls = eps * 4 + 1.f; /* Scale A */ anrm = slange_("M", n, n, &a[a_offset], lda, &work[1]); anrm1 = anrm; anrm2 = 1.f; if (anrm < 1.f) { if (safmax * anrm < 1.f) { anrm1 = safmin; anrm2 = safmax * anrm; } } if (anrm > 0.f) { slascl_("G", &c_n1, &c_n1, &anrm, &c_b27, n, n, &a[a_offset], lda, & iinfo); if (iinfo != 0) { *info = *n + 10; return 0; } } /* Scale B */ bnrm = slange_("M", n, n, &b[b_offset], ldb, &work[1]); bnrm1 = bnrm; bnrm2 = 1.f; if (bnrm < 1.f) { if (safmax * bnrm < 1.f) { bnrm1 = safmin; bnrm2 = safmax * bnrm; } } if (bnrm > 0.f) { slascl_("G", &c_n1, &c_n1, &bnrm, &c_b27, n, n, &b[b_offset], ldb, & iinfo); if (iinfo != 0) { *info = *n + 10; return 0; } } /* Permute the matrix to make it more nearly triangular */ /* Workspace layout: (8*N words -- "work" requires 6*N words) */ ileft = 1; iright = *n + 1; iwork = iright + *n; sggbal_("P", n, &a[a_offset], lda, &b[b_offset], ldb, &ilo, &ihi, &work[ ileft], &work[iright], &work[iwork], &iinfo); if (iinfo != 0) { *info = *n + 1; goto L120; } /* Reduce B to triangular form, and initialize VL and/or VR */ irows = ihi + 1 - ilo; if (ilv) { icols = *n + 1 - ilo; } else { icols = irows; } itau = iwork; iwork = itau + irows; i__1 = *lwork + 1 - iwork; sgeqrf_(&irows, &icols, &b[ilo + ilo * b_dim1], ldb, &work[itau], &work[ iwork], &i__1, &iinfo); if (iinfo >= 0) { /* Computing MAX */ i__1 = lwkopt, i__2 = (integer) work[iwork] + iwork - 1; lwkopt = max(i__1,i__2); } if (iinfo != 0) { *info = *n + 2; goto L120; } i__1 = *lwork + 1 - iwork; sormqr_("L", "T", &irows, &icols, &irows, &b[ilo + ilo * b_dim1], ldb, & work[itau], &a[ilo + ilo * a_dim1], lda, &work[iwork], &i__1, & iinfo); if (iinfo >= 0) { /* Computing MAX */ i__1 = lwkopt, i__2 = (integer) work[iwork] + iwork - 1; lwkopt = max(i__1,i__2); } if (iinfo != 0) { *info = *n + 3; goto L120; } if (ilvl) { slaset_("Full", n, n, &c_b38, &c_b27, &vl[vl_offset], ldvl) ; i__1 = irows - 1; i__2 = irows - 1; slacpy_("L", &i__1, &i__2, &b[ilo + 1 + ilo * b_dim1], ldb, &vl[ilo + 1 + ilo * vl_dim1], ldvl); i__1 = *lwork + 1 - iwork; sorgqr_(&irows, &irows, &irows, &vl[ilo + ilo * vl_dim1], ldvl, &work[ itau], &work[iwork], &i__1, &iinfo); if (iinfo >= 0) { /* Computing MAX */ i__1 = lwkopt, i__2 = (integer) work[iwork] + iwork - 1; lwkopt = max(i__1,i__2); } if (iinfo != 0) { *info = *n + 4; goto L120; } } if (ilvr) { slaset_("Full", n, n, &c_b38, &c_b27, &vr[vr_offset], ldvr) ; } /* Reduce to generalized Hessenberg form */ if (ilv) { /* Eigenvectors requested -- work on whole matrix. */ sgghrd_(jobvl, jobvr, n, &ilo, &ihi, &a[a_offset], lda, &b[b_offset], ldb, &vl[vl_offset], ldvl, &vr[vr_offset], ldvr, &iinfo); } else { sgghrd_("N", "N", &irows, &c__1, &irows, &a[ilo + ilo * a_dim1], lda, &b[ilo + ilo * b_dim1], ldb, &vl[vl_offset], ldvl, &vr[ vr_offset], ldvr, &iinfo); } if (iinfo != 0) { *info = *n + 5; goto L120; } /* Perform QZ algorithm */ iwork = itau; if (ilv) { *(unsigned char *)chtemp = 'S'; } else { *(unsigned char *)chtemp = 'E'; } i__1 = *lwork + 1 - iwork; shgeqz_(chtemp, jobvl, jobvr, n, &ilo, &ihi, &a[a_offset], lda, &b[ b_offset], ldb, &alphar[1], &alphai[1], &beta[1], &vl[vl_offset], ldvl, &vr[vr_offset], ldvr, &work[iwork], &i__1, &iinfo); if (iinfo >= 0) { /* Computing MAX */ i__1 = lwkopt, i__2 = (integer) work[iwork] + iwork - 1; lwkopt = max(i__1,i__2); } if (iinfo != 0) { if (iinfo > 0 && iinfo <= *n) { *info = iinfo; } else if (iinfo > *n && iinfo <= *n << 1) { *info = iinfo - *n; } else { *info = *n + 6; } goto L120; } if (ilv) { /* Compute Eigenvectors (STGEVC requires 6*N words of workspace) */ if (ilvl) { if (ilvr) { *(unsigned char *)chtemp = 'B'; } else { *(unsigned char *)chtemp = 'L'; } } else { *(unsigned char *)chtemp = 'R'; } stgevc_(chtemp, "B", ldumma, n, &a[a_offset], lda, &b[b_offset], ldb, &vl[vl_offset], ldvl, &vr[vr_offset], ldvr, n, &in, &work[ iwork], &iinfo); if (iinfo != 0) { *info = *n + 7; goto L120; } /* Undo balancing on VL and VR, rescale */ if (ilvl) { sggbak_("P", "L", n, &ilo, &ihi, &work[ileft], &work[iright], n, & vl[vl_offset], ldvl, &iinfo); if (iinfo != 0) { *info = *n + 8; goto L120; } i__1 = *n; for (jc = 1; jc <= i__1; ++jc) { if (alphai[jc] < 0.f) { goto L50; } temp = 0.f; if (alphai[jc] == 0.f) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ r__2 = temp, r__3 = (r__1 = vl[jr + jc * vl_dim1], dabs(r__1)); temp = dmax(r__2,r__3); } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ r__3 = temp, r__4 = (r__1 = vl[jr + jc * vl_dim1], dabs(r__1)) + (r__2 = vl[jr + (jc + 1) * vl_dim1], dabs(r__2)); temp = dmax(r__3,r__4); } } if (temp < safmin) { goto L50; } temp = 1.f / temp; if (alphai[jc] == 0.f) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { vl[jr + jc * vl_dim1] *= temp; } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { vl[jr + jc * vl_dim1] *= temp; vl[jr + (jc + 1) * vl_dim1] *= temp; } } L50: ; } } if (ilvr) { sggbak_("P", "R", n, &ilo, &ihi, &work[ileft], &work[iright], n, & vr[vr_offset], ldvr, &iinfo); if (iinfo != 0) { *info = *n + 9; goto L120; } i__1 = *n; for (jc = 1; jc <= i__1; ++jc) { if (alphai[jc] < 0.f) { goto L100; } temp = 0.f; if (alphai[jc] == 0.f) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ r__2 = temp, r__3 = (r__1 = vr[jr + jc * vr_dim1], dabs(r__1)); temp = dmax(r__2,r__3); } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ r__3 = temp, r__4 = (r__1 = vr[jr + jc * vr_dim1], dabs(r__1)) + (r__2 = vr[jr + (jc + 1) * vr_dim1], dabs(r__2)); temp = dmax(r__3,r__4); } } if (temp < safmin) { goto L100; } temp = 1.f / temp; if (alphai[jc] == 0.f) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { vr[jr + jc * vr_dim1] *= temp; } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { vr[jr + jc * vr_dim1] *= temp; vr[jr + (jc + 1) * vr_dim1] *= temp; } } L100: ; } } /* End of eigenvector calculation */ } /* Undo scaling in alpha, beta */ /* Note: this does not give the alpha and beta for the unscaled */ /* problem. */ /* Un-scaling is limited to avoid underflow in alpha and beta */ /* if they are significant. */ i__1 = *n; for (jc = 1; jc <= i__1; ++jc) { absar = (r__1 = alphar[jc], dabs(r__1)); absai = (r__1 = alphai[jc], dabs(r__1)); absb = (r__1 = beta[jc], dabs(r__1)); salfar = anrm * alphar[jc]; salfai = anrm * alphai[jc]; sbeta = bnrm * beta[jc]; ilimit = FALSE_; scale = 1.f; /* Check for significant underflow in ALPHAI */ /* Computing MAX */ r__1 = safmin, r__2 = eps * absar, r__1 = max(r__1,r__2), r__2 = eps * absb; if (dabs(salfai) < safmin && absai >= dmax(r__1,r__2)) { ilimit = TRUE_; /* Computing MAX */ r__1 = onepls * safmin, r__2 = anrm2 * absai; scale = onepls * safmin / anrm1 / dmax(r__1,r__2); } else if (salfai == 0.f) { /* If insignificant underflow in ALPHAI, then make the */ /* conjugate eigenvalue real. */ if (alphai[jc] < 0.f && jc > 1) { alphai[jc - 1] = 0.f; } else if (alphai[jc] > 0.f && jc < *n) { alphai[jc + 1] = 0.f; } } /* Check for significant underflow in ALPHAR */ /* Computing MAX */ r__1 = safmin, r__2 = eps * absai, r__1 = max(r__1,r__2), r__2 = eps * absb; if (dabs(salfar) < safmin && absar >= dmax(r__1,r__2)) { ilimit = TRUE_; /* Computing MAX */ /* Computing MAX */ r__3 = onepls * safmin, r__4 = anrm2 * absar; r__1 = scale, r__2 = onepls * safmin / anrm1 / dmax(r__3,r__4); scale = dmax(r__1,r__2); } /* Check for significant underflow in BETA */ /* Computing MAX */ r__1 = safmin, r__2 = eps * absar, r__1 = max(r__1,r__2), r__2 = eps * absai; if (dabs(sbeta) < safmin && absb >= dmax(r__1,r__2)) { ilimit = TRUE_; /* Computing MAX */ /* Computing MAX */ r__3 = onepls * safmin, r__4 = bnrm2 * absb; r__1 = scale, r__2 = onepls * safmin / bnrm1 / dmax(r__3,r__4); scale = dmax(r__1,r__2); } /* Check for possible overflow when limiting scaling */ if (ilimit) { /* Computing MAX */ r__1 = dabs(salfar), r__2 = dabs(salfai), r__1 = max(r__1,r__2), r__2 = dabs(sbeta); temp = scale * safmin * dmax(r__1,r__2); if (temp > 1.f) { scale /= temp; } if (scale < 1.f) { ilimit = FALSE_; } } /* Recompute un-scaled ALPHAR, ALPHAI, BETA if necessary. */ if (ilimit) { salfar = scale * alphar[jc] * anrm; salfai = scale * alphai[jc] * anrm; sbeta = scale * beta[jc] * bnrm; } alphar[jc] = salfar; alphai[jc] = salfai; beta[jc] = sbeta; } L120: work[1] = (real) lwkopt; return 0; /* End of SGEGV */ } /* sgegv_ */
/* Subroutine */ int sggqrf_(integer *n, integer *m, integer *p, real *a, integer *lda, real *taua, real *b, integer *ldb, real *taub, real * work, integer *lwork, integer *info) { /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, i__1, i__2; /* Local variables */ integer nb, nb1, nb2, nb3, lopt; extern /* Subroutine */ int xerbla_(char *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *); extern /* Subroutine */ int sgeqrf_(integer *, integer *, real *, integer *, real *, real *, integer *, integer *), sgerqf_(integer *, integer *, real *, integer *, real *, real *, integer *, integer * ); integer lwkopt; logical lquery; extern /* Subroutine */ int sormqr_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *); /* -- LAPACK routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SGGQRF computes a generalized QR factorization of an N-by-M matrix A */ /* and an N-by-P matrix B: */ /* A = Q*R, B = Q*T*Z, */ /* where Q is an N-by-N orthogonal matrix, Z is a P-by-P orthogonal */ /* matrix, and R and T assume one of the forms: */ /* if N >= M, R = ( R11 ) M , or if N < M, R = ( R11 R12 ) N, */ /* ( 0 ) N-M N M-N */ /* M */ /* where R11 is upper triangular, and */ /* if N <= P, T = ( 0 T12 ) N, or if N > P, T = ( T11 ) N-P, */ /* P-N N ( T21 ) P */ /* P */ /* where T12 or T21 is upper triangular. */ /* In particular, if B is square and nonsingular, the GQR factorization */ /* of A and B implicitly gives the QR factorization of inv(B)*A: */ /* inv(B)*A = Z'*(inv(T)*R) */ /* where inv(B) denotes the inverse of the matrix B, and Z' denotes the */ /* transpose of the matrix Z. */ /* Arguments */ /* ========= */ /* N (input) INTEGER */ /* The number of rows of the matrices A and B. N >= 0. */ /* M (input) INTEGER */ /* The number of columns of the matrix A. M >= 0. */ /* P (input) INTEGER */ /* The number of columns of the matrix B. P >= 0. */ /* A (input/output) REAL array, dimension (LDA,M) */ /* On entry, the N-by-M matrix A. */ /* On exit, the elements on and above the diagonal of the array */ /* contain the min(N,M)-by-M upper trapezoidal matrix R (R is */ /* upper triangular if N >= M); the elements below the diagonal, */ /* with the array TAUA, represent the orthogonal matrix Q as a */ /* product of min(N,M) elementary reflectors (see Further */ /* Details). */ /* LDA (input) INTEGER */ /* The leading dimension of the array A. LDA >= max(1,N). */ /* TAUA (output) REAL array, dimension (min(N,M)) */ /* The scalar factors of the elementary reflectors which */ /* represent the orthogonal matrix Q (see Further Details). */ /* B (input/output) REAL array, dimension (LDB,P) */ /* On entry, the N-by-P matrix B. */ /* On exit, if N <= P, the upper triangle of the subarray */ /* B(1:N,P-N+1:P) contains the N-by-N upper triangular matrix T; */ /* if N > P, the elements on and above the (N-P)-th subdiagonal */ /* contain the N-by-P upper trapezoidal matrix T; the remaining */ /* elements, with the array TAUB, represent the orthogonal */ /* matrix Z as a product of elementary reflectors (see Further */ /* Details). */ /* LDB (input) INTEGER */ /* The leading dimension of the array B. LDB >= max(1,N). */ /* TAUB (output) REAL array, dimension (min(N,P)) */ /* The scalar factors of the elementary reflectors which */ /* represent the orthogonal matrix Z (see Further Details). */ /* WORK (workspace/output) REAL array, dimension (MAX(1,LWORK)) */ /* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */ /* LWORK (input) INTEGER */ /* The dimension of the array WORK. LWORK >= max(1,N,M,P). */ /* For optimum performance LWORK >= max(N,M,P)*max(NB1,NB2,NB3), */ /* where NB1 is the optimal blocksize for the QR factorization */ /* of an N-by-M matrix, NB2 is the optimal blocksize for the */ /* RQ factorization of an N-by-P matrix, and NB3 is the optimal */ /* blocksize for a call of SORMQR. */ /* If LWORK = -1, then a workspace query is assumed; the routine */ /* only calculates the optimal size of the WORK array, returns */ /* this value as the first entry of the WORK array, and no error */ /* message related to LWORK is issued by XERBLA. */ /* INFO (output) INTEGER */ /* = 0: successful exit */ /* < 0: if INFO = -i, the i-th argument had an illegal value. */ /* Further Details */ /* =============== */ /* The matrix Q is represented as a product of elementary reflectors */ /* Q = H(1) H(2) . . . H(k), where k = min(n,m). */ /* Each H(i) has the form */ /* H(i) = I - taua * v * v' */ /* where taua is a real scalar, and v is a real vector with */ /* v(1:i-1) = 0 and v(i) = 1; v(i+1:n) is stored on exit in A(i+1:n,i), */ /* and taua in TAUA(i). */ /* To form Q explicitly, use LAPACK subroutine SORGQR. */ /* To use Q to update another matrix, use LAPACK subroutine SORMQR. */ /* The matrix Z is represented as a product of elementary reflectors */ /* Z = H(1) H(2) . . . H(k), where k = min(n,p). */ /* Each H(i) has the form */ /* H(i) = I - taub * v * v' */ /* where taub is a real scalar, and v is a real vector with */ /* v(p-k+i+1:p) = 0 and v(p-k+i) = 1; v(1:p-k+i-1) is stored on exit in */ /* B(n-k+i,1:p-k+i-1), and taub in TAUB(i). */ /* To form Z explicitly, use LAPACK subroutine SORGRQ. */ /* To use Z to update another matrix, use LAPACK subroutine SORMRQ. */ /* ===================================================================== */ /* .. Local Scalars .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; --taua; b_dim1 = *ldb; b_offset = 1 + b_dim1; b -= b_offset; --taub; --work; /* Function Body */ *info = 0; nb1 = ilaenv_(&c__1, "SGEQRF", " ", n, m, &c_n1, &c_n1); nb2 = ilaenv_(&c__1, "SGERQF", " ", n, p, &c_n1, &c_n1); nb3 = ilaenv_(&c__1, "SORMQR", " ", n, m, p, &c_n1); /* Computing MAX */ i__1 = max(nb1,nb2); nb = max(i__1,nb3); /* Computing MAX */ i__1 = max(*n,*m); lwkopt = max(i__1,*p) * nb; work[1] = (real) lwkopt; lquery = *lwork == -1; if (*n < 0) { *info = -1; } else if (*m < 0) { *info = -2; } else if (*p < 0) { *info = -3; } else if (*lda < max(1,*n)) { *info = -5; } else if (*ldb < max(1,*n)) { *info = -8; } else /* if(complicated condition) */ { /* Computing MAX */ i__1 = max(1,*n), i__1 = max(i__1,*m); if (*lwork < max(i__1,*p) && ! lquery) { *info = -11; } } if (*info != 0) { i__1 = -(*info); xerbla_("SGGQRF", &i__1); return 0; } else if (lquery) { return 0; } /* QR factorization of N-by-M matrix A: A = Q*R */ sgeqrf_(n, m, &a[a_offset], lda, &taua[1], &work[1], lwork, info); lopt = work[1]; /* Update B := Q'*B. */ i__1 = min(*n,*m); sormqr_("Left", "Transpose", n, p, &i__1, &a[a_offset], lda, &taua[1], &b[ b_offset], ldb, &work[1], lwork, info); /* Computing MAX */ i__1 = lopt, i__2 = (integer) work[1]; lopt = max(i__1,i__2); /* RQ factorization of N-by-P matrix B: B = T*Z. */ sgerqf_(n, p, &b[b_offset], ldb, &taub[1], &work[1], lwork, info); /* Computing MAX */ i__1 = lopt, i__2 = (integer) work[1]; work[1] = (real) max(i__1,i__2); return 0; /* End of SGGQRF */ } /* sggqrf_ */
/* Subroutine */ int sgges_(char *jobvsl, char *jobvsr, char *sort, L_fp selctg, integer *n, real *a, integer *lda, real *b, integer *ldb, integer *sdim, real *alphar, real *alphai, real *beta, real *vsl, integer *ldvsl, real *vsr, integer *ldvsr, real *work, integer *lwork, logical *bwork, integer *info) { /* -- LAPACK driver 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 ======= SGGES computes for a pair of N-by-N real nonsymmetric matrices (A,B), the generalized eigenvalues, the generalized real Schur form (S,T), optionally, the left and/or right matrices of Schur vectors (VSL and VSR). This gives the generalized Schur factorization (A,B) = ( (VSL)*S*(VSR)**T, (VSL)*T*(VSR)**T ) Optionally, it also orders the eigenvalues so that a selected cluster of eigenvalues appears in the leading diagonal blocks of the upper quasi-triangular matrix S and the upper triangular matrix T.The leading columns of VSL and VSR then form an orthonormal basis for the corresponding left and right eigenspaces (deflating subspaces). (If only the generalized eigenvalues are needed, use the driver SGGEV instead, which is faster.) A generalized eigenvalue for a pair of matrices (A,B) is a scalar w or a ratio alpha/beta = w, such that A - w*B is singular. It is usually represented as the pair (alpha,beta), as there is a reasonable interpretation for beta=0 or both being zero. A pair of matrices (S,T) is in generalized real Schur form if T is upper triangular with non-negative diagonal and S is block upper triangular with 1-by-1 and 2-by-2 blocks. 1-by-1 blocks correspond to real generalized eigenvalues, while 2-by-2 blocks of S will be "standardized" by making the corresponding elements of T have the form: [ a 0 ] [ 0 b ] and the pair of corresponding 2-by-2 blocks in S and T will have a complex conjugate pair of generalized eigenvalues. Arguments ========= JOBVSL (input) CHARACTER*1 = 'N': do not compute the left Schur vectors; = 'V': compute the left Schur vectors. JOBVSR (input) CHARACTER*1 = 'N': do not compute the right Schur vectors; = 'V': compute the right Schur vectors. SORT (input) CHARACTER*1 Specifies whether or not to order the eigenvalues on the diagonal of the generalized Schur form. = 'N': Eigenvalues are not ordered; = 'S': Eigenvalues are ordered (see SELCTG); SELCTG (input) LOGICAL FUNCTION of three REAL arguments SELCTG must be declared EXTERNAL in the calling subroutine. If SORT = 'N', SELCTG is not referenced. If SORT = 'S', SELCTG is used to select eigenvalues to sort to the top left of the Schur form. An eigenvalue (ALPHAR(j)+ALPHAI(j))/BETA(j) is selected if SELCTG(ALPHAR(j),ALPHAI(j),BETA(j)) is true; i.e. if either one of a complex conjugate pair of eigenvalues is selected, then both complex eigenvalues are selected. Note that in the ill-conditioned case, a selected complex eigenvalue may no longer satisfy SELCTG(ALPHAR(j),ALPHAI(j), BETA(j)) = .TRUE. after ordering. INFO is to be set to N+2 in this case. N (input) INTEGER The order of the matrices A, B, VSL, and VSR. N >= 0. A (input/output) REAL array, dimension (LDA, N) On entry, the first of the pair of matrices. On exit, A has been overwritten by its generalized Schur form S. LDA (input) INTEGER The leading dimension of A. LDA >= max(1,N). B (input/output) REAL array, dimension (LDB, N) On entry, the second of the pair of matrices. On exit, B has been overwritten by its generalized Schur form T. LDB (input) INTEGER The leading dimension of B. LDB >= max(1,N). SDIM (output) INTEGER If SORT = 'N', SDIM = 0. If SORT = 'S', SDIM = number of eigenvalues (after sorting) for which SELCTG is true. (Complex conjugate pairs for which SELCTG is true for either eigenvalue count as 2.) ALPHAR (output) REAL array, dimension (N) ALPHAI (output) REAL array, dimension (N) BETA (output) REAL array, dimension (N) On exit, (ALPHAR(j) + ALPHAI(j)*i)/BETA(j), j=1,...,N, will be the generalized eigenvalues. ALPHAR(j) + ALPHAI(j)*i, and BETA(j),j=1,...,N are the diagonals of the complex Schur form (S,T) that would result if the 2-by-2 diagonal blocks of the real Schur form of (A,B) were further reduced to triangular form using 2-by-2 complex unitary transformations. If ALPHAI(j) is zero, then the j-th eigenvalue is real; if positive, then the j-th and (j+1)-st eigenvalues are a complex conjugate pair, with ALPHAI(j+1) negative. Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j) may easily over- or underflow, and BETA(j) may even be zero. Thus, the user should avoid naively computing the ratio. However, ALPHAR and ALPHAI will be always less than and usually comparable with norm(A) in magnitude, and BETA always less than and usually comparable with norm(B). VSL (output) REAL array, dimension (LDVSL,N) If JOBVSL = 'V', VSL will contain the left Schur vectors. Not referenced if JOBVSL = 'N'. LDVSL (input) INTEGER The leading dimension of the matrix VSL. LDVSL >=1, and if JOBVSL = 'V', LDVSL >= N. VSR (output) REAL array, dimension (LDVSR,N) If JOBVSR = 'V', VSR will contain the right Schur vectors. Not referenced if JOBVSR = 'N'. LDVSR (input) INTEGER The leading dimension of the matrix VSR. LDVSR >= 1, and if JOBVSR = 'V', LDVSR >= N. WORK (workspace/output) REAL array, dimension (LWORK) On exit, if INFO = 0, WORK(1) returns the optimal LWORK. LWORK (input) INTEGER The dimension of the array WORK. LWORK >= 8*N+16. If LWORK = -1, then a workspace query is assumed; the routine only calculates the optimal size of the WORK array, returns this value as the first entry of the WORK array, and no error message related to LWORK is issued by XERBLA. BWORK (workspace) LOGICAL array, dimension (N) Not referenced if SORT = 'N'. INFO (output) INTEGER = 0: successful exit < 0: if INFO = -i, the i-th argument had an illegal value. = 1,...,N: The QZ iteration failed. (A,B) are not in Schur form, but ALPHAR(j), ALPHAI(j), and BETA(j) should be correct for j=INFO+1,...,N. > N: =N+1: other than QZ iteration failed in SHGEQZ. =N+2: after reordering, roundoff changed values of some complex eigenvalues so that leading eigenvalues in the Generalized Schur form no longer satisfy SELCTG=.TRUE. This could also be caused due to scaling. =N+3: reordering failed in STGSEN. ===================================================================== Decode the input arguments Parameter adjustments */ /* Table of constant values */ static integer c__1 = 1; static integer c__0 = 0; static integer c_n1 = -1; static real c_b33 = 0.f; static real c_b34 = 1.f; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, vsl_dim1, vsl_offset, vsr_dim1, vsr_offset, i__1, i__2; real r__1; /* Builtin functions */ double sqrt(doublereal); /* Local variables */ static real anrm, bnrm; static integer idum[1], ierr, itau, iwrk; static real pvsl, pvsr; static integer i__; extern logical lsame_(char *, char *); static integer ileft, icols; static logical cursl, ilvsl, ilvsr; static integer irows; static logical lst2sl; extern /* Subroutine */ int slabad_(real *, real *); static integer ip; extern /* Subroutine */ int sggbak_(char *, char *, integer *, integer *, integer *, real *, real *, integer *, real *, integer *, integer * ), sggbal_(char *, integer *, real *, integer *, real *, integer *, integer *, integer *, real *, real *, real *, integer *); static logical ilascl, ilbscl; extern doublereal slamch_(char *), slange_(char *, integer *, integer *, real *, integer *, real *); static real safmin; extern /* Subroutine */ int sgghrd_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, integer *, real *, integer * , real *, integer *, integer *); static real safmax; extern /* Subroutine */ int xerbla_(char *, integer *); static real bignum; extern /* Subroutine */ int slascl_(char *, integer *, integer *, real *, real *, integer *, integer *, real *, integer *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *, ftnlen, ftnlen); static integer ijobvl, iright; extern /* Subroutine */ int sgeqrf_(integer *, integer *, real *, integer *, real *, real *, integer *, integer *); static integer ijobvr; extern /* Subroutine */ int slacpy_(char *, integer *, integer *, real *, integer *, real *, integer *), slaset_(char *, integer *, integer *, real *, real *, real *, integer *); static real anrmto, bnrmto; static logical lastsl; extern /* Subroutine */ int shgeqz_(char *, char *, char *, integer *, integer *, integer *, real *, integer *, real *, integer *, real * , real *, real *, real *, integer *, real *, integer *, real *, integer *, integer *), stgsen_(integer *, logical *, logical *, logical *, integer *, real *, integer *, real *, integer *, real *, real *, real *, real *, integer *, real *, integer *, integer *, real *, real *, real *, real *, integer *, integer *, integer *, integer *); static integer minwrk, maxwrk; static real smlnum; extern /* Subroutine */ int sorgqr_(integer *, integer *, integer *, real *, integer *, real *, real *, integer *, integer *); static logical wantst, lquery; extern /* Subroutine */ int sormqr_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *); static real dif[2]; static integer ihi, ilo; static real eps; #define a_ref(a_1,a_2) a[(a_2)*a_dim1 + a_1] #define b_ref(a_1,a_2) b[(a_2)*b_dim1 + a_1] #define vsl_ref(a_1,a_2) vsl[(a_2)*vsl_dim1 + a_1] a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; b_dim1 = *ldb; b_offset = 1 + b_dim1 * 1; b -= b_offset; --alphar; --alphai; --beta; vsl_dim1 = *ldvsl; vsl_offset = 1 + vsl_dim1 * 1; vsl -= vsl_offset; vsr_dim1 = *ldvsr; vsr_offset = 1 + vsr_dim1 * 1; vsr -= vsr_offset; --work; --bwork; /* Function Body */ if (lsame_(jobvsl, "N")) { ijobvl = 1; ilvsl = FALSE_; } else if (lsame_(jobvsl, "V")) { ijobvl = 2; ilvsl = TRUE_; } else { ijobvl = -1; ilvsl = FALSE_; } if (lsame_(jobvsr, "N")) { ijobvr = 1; ilvsr = FALSE_; } else if (lsame_(jobvsr, "V")) { ijobvr = 2; ilvsr = TRUE_; } else { ijobvr = -1; ilvsr = FALSE_; } wantst = lsame_(sort, "S"); /* Test the input arguments */ *info = 0; lquery = *lwork == -1; if (ijobvl <= 0) { *info = -1; } else if (ijobvr <= 0) { *info = -2; } else if (! wantst && ! lsame_(sort, "N")) { *info = -3; } else if (*n < 0) { *info = -5; } else if (*lda < max(1,*n)) { *info = -7; } else if (*ldb < max(1,*n)) { *info = -9; } else if (*ldvsl < 1 || ilvsl && *ldvsl < *n) { *info = -15; } else if (*ldvsr < 1 || ilvsr && *ldvsr < *n) { *info = -17; } /* Compute workspace (Note: Comments in the code beginning "Workspace:" describe the minimal amount of workspace needed at that point in the code, as well as the preferred amount for good performance. NB refers to the optimal block size for the immediately following subroutine, as returned by ILAENV.) */ minwrk = 1; if (*info == 0 && (*lwork >= 1 || lquery)) { minwrk = (*n + 1) * 7 + 16; maxwrk = (*n + 1) * 7 + *n * ilaenv_(&c__1, "SGEQRF", " ", n, &c__1, n, &c__0, (ftnlen)6, (ftnlen)1) + 16; if (ilvsl) { /* Computing MAX */ i__1 = maxwrk, i__2 = (*n + 1) * 7 + *n * ilaenv_(&c__1, "SORGQR", " ", n, &c__1, n, &c_n1, (ftnlen)6, (ftnlen)1); maxwrk = max(i__1,i__2); } work[1] = (real) maxwrk; } if (*lwork < minwrk && ! lquery) { *info = -19; } if (*info != 0) { i__1 = -(*info); xerbla_("SGGES ", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*n == 0) { *sdim = 0; return 0; } /* Get machine constants */ eps = slamch_("P"); safmin = slamch_("S"); safmax = 1.f / safmin; slabad_(&safmin, &safmax); smlnum = sqrt(safmin) / eps; bignum = 1.f / smlnum; /* Scale A if max element outside range [SMLNUM,BIGNUM] */ anrm = slange_("M", n, n, &a[a_offset], lda, &work[1]); ilascl = FALSE_; if (anrm > 0.f && anrm < smlnum) { anrmto = smlnum; ilascl = TRUE_; } else if (anrm > bignum) { anrmto = bignum; ilascl = TRUE_; } if (ilascl) { slascl_("G", &c__0, &c__0, &anrm, &anrmto, n, n, &a[a_offset], lda, & ierr); } /* Scale B if max element outside range [SMLNUM,BIGNUM] */ bnrm = slange_("M", n, n, &b[b_offset], ldb, &work[1]); ilbscl = FALSE_; if (bnrm > 0.f && bnrm < smlnum) { bnrmto = smlnum; ilbscl = TRUE_; } else if (bnrm > bignum) { bnrmto = bignum; ilbscl = TRUE_; } if (ilbscl) { slascl_("G", &c__0, &c__0, &bnrm, &bnrmto, n, n, &b[b_offset], ldb, & ierr); } /* Permute the matrix to make it more nearly triangular (Workspace: need 6*N + 2*N space for storing balancing factors) */ ileft = 1; iright = *n + 1; iwrk = iright + *n; sggbal_("P", n, &a[a_offset], lda, &b[b_offset], ldb, &ilo, &ihi, &work[ ileft], &work[iright], &work[iwrk], &ierr); /* Reduce B to triangular form (QR decomposition of B) (Workspace: need N, prefer N*NB) */ irows = ihi + 1 - ilo; icols = *n + 1 - ilo; itau = iwrk; iwrk = itau + irows; i__1 = *lwork + 1 - iwrk; sgeqrf_(&irows, &icols, &b_ref(ilo, ilo), ldb, &work[itau], &work[iwrk], & i__1, &ierr); /* Apply the orthogonal transformation to matrix A (Workspace: need N, prefer N*NB) */ i__1 = *lwork + 1 - iwrk; sormqr_("L", "T", &irows, &icols, &irows, &b_ref(ilo, ilo), ldb, &work[ itau], &a_ref(ilo, ilo), lda, &work[iwrk], &i__1, &ierr); /* Initialize VSL (Workspace: need N, prefer N*NB) */ if (ilvsl) { slaset_("Full", n, n, &c_b33, &c_b34, &vsl[vsl_offset], ldvsl); i__1 = irows - 1; i__2 = irows - 1; slacpy_("L", &i__1, &i__2, &b_ref(ilo + 1, ilo), ldb, &vsl_ref(ilo + 1, ilo), ldvsl); i__1 = *lwork + 1 - iwrk; sorgqr_(&irows, &irows, &irows, &vsl_ref(ilo, ilo), ldvsl, &work[itau] , &work[iwrk], &i__1, &ierr); } /* Initialize VSR */ if (ilvsr) { slaset_("Full", n, n, &c_b33, &c_b34, &vsr[vsr_offset], ldvsr); } /* Reduce to generalized Hessenberg form (Workspace: none needed) */ sgghrd_(jobvsl, jobvsr, n, &ilo, &ihi, &a[a_offset], lda, &b[b_offset], ldb, &vsl[vsl_offset], ldvsl, &vsr[vsr_offset], ldvsr, &ierr); /* Perform QZ algorithm, computing Schur vectors if desired (Workspace: need N) */ iwrk = itau; i__1 = *lwork + 1 - iwrk; shgeqz_("S", jobvsl, jobvsr, n, &ilo, &ihi, &a[a_offset], lda, &b[ b_offset], ldb, &alphar[1], &alphai[1], &beta[1], &vsl[vsl_offset] , ldvsl, &vsr[vsr_offset], ldvsr, &work[iwrk], &i__1, &ierr); if (ierr != 0) { if (ierr > 0 && ierr <= *n) { *info = ierr; } else if (ierr > *n && ierr <= *n << 1) { *info = ierr - *n; } else { *info = *n + 1; } goto L40; } /* Sort eigenvalues ALPHA/BETA if desired (Workspace: need 4*N+16 ) */ *sdim = 0; if (wantst) { /* Undo scaling on eigenvalues before SELCTGing */ if (ilascl) { slascl_("G", &c__0, &c__0, &anrmto, &anrm, n, &c__1, &alphar[1], n, &ierr); slascl_("G", &c__0, &c__0, &anrmto, &anrm, n, &c__1, &alphai[1], n, &ierr); } if (ilbscl) { slascl_("G", &c__0, &c__0, &bnrmto, &bnrm, n, &c__1, &beta[1], n, &ierr); } /* Select eigenvalues */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { bwork[i__] = (*selctg)(&alphar[i__], &alphai[i__], &beta[i__]); /* L10: */ } i__1 = *lwork - iwrk + 1; stgsen_(&c__0, &ilvsl, &ilvsr, &bwork[1], n, &a[a_offset], lda, &b[ b_offset], ldb, &alphar[1], &alphai[1], &beta[1], &vsl[ vsl_offset], ldvsl, &vsr[vsr_offset], ldvsr, sdim, &pvsl, & pvsr, dif, &work[iwrk], &i__1, idum, &c__1, &ierr); if (ierr == 1) { *info = *n + 3; } } /* Apply back-permutation to VSL and VSR (Workspace: none needed) */ if (ilvsl) { sggbak_("P", "L", n, &ilo, &ihi, &work[ileft], &work[iright], n, &vsl[ vsl_offset], ldvsl, &ierr); } if (ilvsr) { sggbak_("P", "R", n, &ilo, &ihi, &work[ileft], &work[iright], n, &vsr[ vsr_offset], ldvsr, &ierr); } /* Check if unscaling would cause over/underflow, if so, rescale (ALPHAR(I),ALPHAI(I),BETA(I)) so BETA(I) is on the order of B(I,I) and ALPHAR(I) and ALPHAI(I) are on the order of A(I,I) */ if (ilascl) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (alphai[i__] != 0.f) { if (alphar[i__] / safmax > anrmto / anrm || safmin / alphar[ i__] > anrm / anrmto) { work[1] = (r__1 = a_ref(i__, i__) / alphar[i__], dabs( r__1)); beta[i__] *= work[1]; alphar[i__] *= work[1]; alphai[i__] *= work[1]; } else if (alphai[i__] / safmax > anrmto / anrm || safmin / alphai[i__] > anrm / anrmto) { work[1] = (r__1 = a_ref(i__, i__ + 1) / alphai[i__], dabs( r__1)); beta[i__] *= work[1]; alphar[i__] *= work[1]; alphai[i__] *= work[1]; } } /* L50: */ } } if (ilbscl) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (alphai[i__] != 0.f) { if (beta[i__] / safmax > bnrmto / bnrm || safmin / beta[i__] > bnrm / bnrmto) { work[1] = (r__1 = b_ref(i__, i__) / beta[i__], dabs(r__1)) ; beta[i__] *= work[1]; alphar[i__] *= work[1]; alphai[i__] *= work[1]; } } /* L60: */ } } /* Undo scaling */ if (ilascl) { slascl_("H", &c__0, &c__0, &anrmto, &anrm, n, n, &a[a_offset], lda, & ierr); slascl_("G", &c__0, &c__0, &anrmto, &anrm, n, &c__1, &alphar[1], n, & ierr); slascl_("G", &c__0, &c__0, &anrmto, &anrm, n, &c__1, &alphai[1], n, & ierr); } if (ilbscl) { slascl_("U", &c__0, &c__0, &bnrmto, &bnrm, n, n, &b[b_offset], ldb, & ierr); slascl_("G", &c__0, &c__0, &bnrmto, &bnrm, n, &c__1, &beta[1], n, & ierr); } if (wantst) { /* Check if reordering is correct */ lastsl = TRUE_; lst2sl = TRUE_; *sdim = 0; ip = 0; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { cursl = (*selctg)(&alphar[i__], &alphai[i__], &beta[i__]); if (alphai[i__] == 0.f) { if (cursl) { ++(*sdim); } ip = 0; if (cursl && ! lastsl) { *info = *n + 2; } } else { if (ip == 1) { /* Last eigenvalue of conjugate pair */ cursl = cursl || lastsl; lastsl = cursl; if (cursl) { *sdim += 2; } ip = -1; if (cursl && ! lst2sl) { *info = *n + 2; } } else { /* First eigenvalue of conjugate pair */ ip = 1; } } lst2sl = lastsl; lastsl = cursl; /* L30: */ } } L40: work[1] = (real) maxwrk; return 0; /* End of SGGES */ } /* sgges_ */
/* Subroutine */ int sgels_(char *trans, integer *m, integer *n, integer * nrhs, real *a, integer *lda, real *b, integer *ldb, real *work, integer *lwork, integer *info) { /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, i__1, i__2; /* Local variables */ integer i__, j, nb, mn; real anrm, bnrm; integer brow; logical tpsd; integer iascl, ibscl; extern logical lsame_(char *, char *); integer wsize; real rwork[1]; extern /* Subroutine */ int slabad_(real *, real *); extern doublereal slamch_(char *), slange_(char *, integer *, integer *, real *, integer *, real *); extern /* Subroutine */ int xerbla_(char *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *); integer scllen; real bignum; extern /* Subroutine */ int sgelqf_(integer *, integer *, real *, integer *, real *, real *, integer *, integer *), slascl_(char *, integer *, integer *, real *, real *, integer *, integer *, real *, integer *, integer *), sgeqrf_(integer *, integer *, real *, integer *, real *, real *, integer *, integer *), slaset_(char *, integer *, integer *, real *, real *, real *, integer *); real smlnum; extern /* Subroutine */ int sormlq_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *); logical lquery; extern /* Subroutine */ int sormqr_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *), strtrs_(char *, char *, char *, integer *, integer *, real *, integer *, real *, integer * , integer *); /* -- LAPACK driver routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SGELS solves overdetermined or underdetermined real linear systems */ /* involving an M-by-N matrix A, or its transpose, using a QR or LQ */ /* factorization of A. It is assumed that A has full rank. */ /* The following options are provided: */ /* 1. If TRANS = 'N' and m >= n: find the least squares solution of */ /* an overdetermined system, i.e., solve the least squares problem */ /* minimize || B - A*X ||. */ /* 2. If TRANS = 'N' and m < n: find the minimum norm solution of */ /* an underdetermined system A * X = B. */ /* 3. If TRANS = 'T' and m >= n: find the minimum norm solution of */ /* an undetermined system A**T * X = B. */ /* 4. If TRANS = 'T' and m < n: find the least squares solution of */ /* an overdetermined system, i.e., solve the least squares problem */ /* minimize || B - A**T * X ||. */ /* Several right hand side vectors b and solution vectors x can be */ /* handled in a single call; they are stored as the columns of the */ /* M-by-NRHS right hand side matrix B and the N-by-NRHS solution */ /* matrix X. */ /* Arguments */ /* ========= */ /* TRANS (input) CHARACTER*1 */ /* = 'N': the linear system involves A; */ /* = 'T': the linear system involves A**T. */ /* M (input) INTEGER */ /* The number of rows of the matrix A. M >= 0. */ /* N (input) INTEGER */ /* The number of columns of the matrix A. N >= 0. */ /* NRHS (input) INTEGER */ /* The number of right hand sides, i.e., the number of */ /* columns of the matrices B and X. NRHS >=0. */ /* A (input/output) REAL array, dimension (LDA,N) */ /* On entry, the M-by-N matrix A. */ /* On exit, */ /* if M >= N, A is overwritten by details of its QR */ /* factorization as returned by SGEQRF; */ /* if M < N, A is overwritten by details of its LQ */ /* factorization as returned by SGELQF. */ /* LDA (input) INTEGER */ /* The leading dimension of the array A. LDA >= max(1,M). */ /* B (input/output) REAL array, dimension (LDB,NRHS) */ /* On entry, the matrix B of right hand side vectors, stored */ /* columnwise; B is M-by-NRHS if TRANS = 'N', or N-by-NRHS */ /* if TRANS = 'T'. */ /* On exit, if INFO = 0, B is overwritten by the solution */ /* vectors, stored columnwise: */ /* if TRANS = 'N' and m >= n, rows 1 to n of B contain the least */ /* squares solution vectors; the residual sum of squares for the */ /* solution in each column is given by the sum of squares of */ /* elements N+1 to M in that column; */ /* if TRANS = 'N' and m < n, rows 1 to N of B contain the */ /* minimum norm solution vectors; */ /* if TRANS = 'T' and m >= n, rows 1 to M of B contain the */ /* minimum norm solution vectors; */ /* if TRANS = 'T' and m < n, rows 1 to M of B contain the */ /* least squares solution vectors; the residual sum of squares */ /* for the solution in each column is given by the sum of */ /* squares of elements M+1 to N in that column. */ /* LDB (input) INTEGER */ /* The leading dimension of the array B. LDB >= MAX(1,M,N). */ /* WORK (workspace/output) REAL array, dimension (MAX(1,LWORK)) */ /* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */ /* LWORK (input) INTEGER */ /* The dimension of the array WORK. */ /* LWORK >= max( 1, MN + max( MN, NRHS ) ). */ /* For optimal performance, */ /* LWORK >= max( 1, MN + max( MN, NRHS )*NB ). */ /* where MN = min(M,N) and NB is the optimum block size. */ /* If LWORK = -1, then a workspace query is assumed; the routine */ /* only calculates the optimal size of the WORK array, returns */ /* this value as the first entry of the WORK array, and no error */ /* message related to LWORK is issued by XERBLA. */ /* INFO (output) INTEGER */ /* = 0: successful exit */ /* < 0: if INFO = -i, the i-th argument had an illegal value */ /* > 0: if INFO = i, the i-th diagonal element of the */ /* triangular factor of A is zero, so that A does not have */ /* full rank; the least squares solution could not be */ /* computed. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. Local Arrays .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input arguments. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; b_dim1 = *ldb; b_offset = 1 + b_dim1; b -= b_offset; --work; /* Function Body */ *info = 0; mn = min(*m,*n); lquery = *lwork == -1; if (! (lsame_(trans, "N") || lsame_(trans, "T"))) { *info = -1; } else if (*m < 0) { *info = -2; } else if (*n < 0) { *info = -3; } else if (*nrhs < 0) { *info = -4; } else if (*lda < max(1,*m)) { *info = -6; } else /* if(complicated condition) */ { /* Computing MAX */ i__1 = max(1,*m); if (*ldb < max(i__1,*n)) { *info = -8; } else /* if(complicated condition) */ { /* Computing MAX */ i__1 = 1, i__2 = mn + max(mn,*nrhs); if (*lwork < max(i__1,i__2) && ! lquery) { *info = -10; } } } /* Figure out optimal block size */ if (*info == 0 || *info == -10) { tpsd = TRUE_; if (lsame_(trans, "N")) { tpsd = FALSE_; } if (*m >= *n) { nb = ilaenv_(&c__1, "SGEQRF", " ", m, n, &c_n1, &c_n1); if (tpsd) { /* Computing MAX */ i__1 = nb, i__2 = ilaenv_(&c__1, "SORMQR", "LN", m, nrhs, n, & c_n1); nb = max(i__1,i__2); } else { /* Computing MAX */ i__1 = nb, i__2 = ilaenv_(&c__1, "SORMQR", "LT", m, nrhs, n, & c_n1); nb = max(i__1,i__2); } } else { nb = ilaenv_(&c__1, "SGELQF", " ", m, n, &c_n1, &c_n1); if (tpsd) { /* Computing MAX */ i__1 = nb, i__2 = ilaenv_(&c__1, "SORMLQ", "LT", n, nrhs, m, & c_n1); nb = max(i__1,i__2); } else { /* Computing MAX */ i__1 = nb, i__2 = ilaenv_(&c__1, "SORMLQ", "LN", n, nrhs, m, & c_n1); nb = max(i__1,i__2); } } /* Computing MAX */ i__1 = 1, i__2 = mn + max(mn,*nrhs) * nb; wsize = max(i__1,i__2); work[1] = (real) wsize; } if (*info != 0) { i__1 = -(*info); xerbla_("SGELS ", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ /* Computing MIN */ i__1 = min(*m,*n); if (min(i__1,*nrhs) == 0) { i__1 = max(*m,*n); slaset_("Full", &i__1, nrhs, &c_b33, &c_b33, &b[b_offset], ldb); return 0; } /* Get machine parameters */ smlnum = slamch_("S") / slamch_("P"); bignum = 1.f / smlnum; slabad_(&smlnum, &bignum); /* Scale A, B if max element outside range [SMLNUM,BIGNUM] */ anrm = slange_("M", m, n, &a[a_offset], lda, rwork); iascl = 0; if (anrm > 0.f && anrm < smlnum) { /* Scale matrix norm up to SMLNUM */ slascl_("G", &c__0, &c__0, &anrm, &smlnum, m, n, &a[a_offset], lda, info); iascl = 1; } else if (anrm > bignum) { /* Scale matrix norm down to BIGNUM */ slascl_("G", &c__0, &c__0, &anrm, &bignum, m, n, &a[a_offset], lda, info); iascl = 2; } else if (anrm == 0.f) { /* Matrix all zero. Return zero solution. */ i__1 = max(*m,*n); slaset_("F", &i__1, nrhs, &c_b33, &c_b33, &b[b_offset], ldb); goto L50; } brow = *m; if (tpsd) { brow = *n; } bnrm = slange_("M", &brow, nrhs, &b[b_offset], ldb, rwork); ibscl = 0; if (bnrm > 0.f && bnrm < smlnum) { /* Scale matrix norm up to SMLNUM */ slascl_("G", &c__0, &c__0, &bnrm, &smlnum, &brow, nrhs, &b[b_offset], ldb, info); ibscl = 1; } else if (bnrm > bignum) { /* Scale matrix norm down to BIGNUM */ slascl_("G", &c__0, &c__0, &bnrm, &bignum, &brow, nrhs, &b[b_offset], ldb, info); ibscl = 2; } if (*m >= *n) { /* compute QR factorization of A */ i__1 = *lwork - mn; sgeqrf_(m, n, &a[a_offset], lda, &work[1], &work[mn + 1], &i__1, info) ; /* workspace at least N, optimally N*NB */ if (! tpsd) { /* Least-Squares Problem min || A * X - B || */ /* B(1:M,1:NRHS) := Q' * B(1:M,1:NRHS) */ i__1 = *lwork - mn; sormqr_("Left", "Transpose", m, nrhs, n, &a[a_offset], lda, &work[ 1], &b[b_offset], ldb, &work[mn + 1], &i__1, info); /* workspace at least NRHS, optimally NRHS*NB */ /* B(1:N,1:NRHS) := inv(R) * B(1:N,1:NRHS) */ strtrs_("Upper", "No transpose", "Non-unit", n, nrhs, &a[a_offset] , lda, &b[b_offset], ldb, info); if (*info > 0) { return 0; } scllen = *n; } else { /* Overdetermined system of equations A' * X = B */ /* B(1:N,1:NRHS) := inv(R') * B(1:N,1:NRHS) */ strtrs_("Upper", "Transpose", "Non-unit", n, nrhs, &a[a_offset], lda, &b[b_offset], ldb, info); if (*info > 0) { return 0; } /* B(N+1:M,1:NRHS) = ZERO */ i__1 = *nrhs; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = *n + 1; i__ <= i__2; ++i__) { b[i__ + j * b_dim1] = 0.f; /* L10: */ } /* L20: */ } /* B(1:M,1:NRHS) := Q(1:N,:) * B(1:N,1:NRHS) */ i__1 = *lwork - mn; sormqr_("Left", "No transpose", m, nrhs, n, &a[a_offset], lda, & work[1], &b[b_offset], ldb, &work[mn + 1], &i__1, info); /* workspace at least NRHS, optimally NRHS*NB */ scllen = *m; } } else { /* Compute LQ factorization of A */ i__1 = *lwork - mn; sgelqf_(m, n, &a[a_offset], lda, &work[1], &work[mn + 1], &i__1, info) ; /* workspace at least M, optimally M*NB. */ if (! tpsd) { /* underdetermined system of equations A * X = B */ /* B(1:M,1:NRHS) := inv(L) * B(1:M,1:NRHS) */ strtrs_("Lower", "No transpose", "Non-unit", m, nrhs, &a[a_offset] , lda, &b[b_offset], ldb, info); if (*info > 0) { return 0; } /* B(M+1:N,1:NRHS) = 0 */ i__1 = *nrhs; for (j = 1; j <= i__1; ++j) { i__2 = *n; for (i__ = *m + 1; i__ <= i__2; ++i__) { b[i__ + j * b_dim1] = 0.f; /* L30: */ } /* L40: */ } /* B(1:N,1:NRHS) := Q(1:N,:)' * B(1:M,1:NRHS) */ i__1 = *lwork - mn; sormlq_("Left", "Transpose", n, nrhs, m, &a[a_offset], lda, &work[ 1], &b[b_offset], ldb, &work[mn + 1], &i__1, info); /* workspace at least NRHS, optimally NRHS*NB */ scllen = *n; } else { /* overdetermined system min || A' * X - B || */ /* B(1:N,1:NRHS) := Q * B(1:N,1:NRHS) */ i__1 = *lwork - mn; sormlq_("Left", "No transpose", n, nrhs, m, &a[a_offset], lda, & work[1], &b[b_offset], ldb, &work[mn + 1], &i__1, info); /* workspace at least NRHS, optimally NRHS*NB */ /* B(1:M,1:NRHS) := inv(L') * B(1:M,1:NRHS) */ strtrs_("Lower", "Transpose", "Non-unit", m, nrhs, &a[a_offset], lda, &b[b_offset], ldb, info); if (*info > 0) { return 0; } scllen = *m; } } /* Undo scaling */ if (iascl == 1) { slascl_("G", &c__0, &c__0, &anrm, &smlnum, &scllen, nrhs, &b[b_offset] , ldb, info); } else if (iascl == 2) { slascl_("G", &c__0, &c__0, &anrm, &bignum, &scllen, nrhs, &b[b_offset] , ldb, info); } if (ibscl == 1) { slascl_("G", &c__0, &c__0, &smlnum, &bnrm, &scllen, nrhs, &b[b_offset] , ldb, info); } else if (ibscl == 2) { slascl_("G", &c__0, &c__0, &bignum, &bnrm, &scllen, nrhs, &b[b_offset] , ldb, info); } L50: work[1] = (real) wsize; return 0; /* End of SGELS */ } /* sgels_ */
/* Subroutine */ int sgeqrs_(integer *m, integer *n, integer *nrhs, real *a, integer *lda, real *tau, real *b, integer *ldb, real *work, integer * lwork, integer *info) { /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, i__1; /* Local variables */ extern /* Subroutine */ int strsm_(char *, char *, char *, char *, integer *, integer *, real *, real *, integer *, real *, integer * ), xerbla_(char *, integer *), sormqr_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *); /* -- LAPACK routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* Solve the least squares problem */ /* min || A*X - B || */ /* using the QR factorization */ /* A = Q*R */ /* computed by SGEQRF. */ /* Arguments */ /* ========= */ /* M (input) INTEGER */ /* The number of rows of the matrix A. M >= 0. */ /* N (input) INTEGER */ /* The number of columns of the matrix A. M >= N >= 0. */ /* NRHS (input) INTEGER */ /* The number of columns of B. NRHS >= 0. */ /* A (input) REAL array, dimension (LDA,N) */ /* Details of the QR factorization of the original matrix A as */ /* returned by SGEQRF. */ /* LDA (input) INTEGER */ /* The leading dimension of the array A. LDA >= M. */ /* TAU (input) REAL array, dimension (N) */ /* Details of the orthogonal matrix Q. */ /* B (input/output) REAL array, dimension (LDB,NRHS) */ /* On entry, the m-by-nrhs right hand side matrix B. */ /* On exit, the n-by-nrhs solution matrix X. */ /* LDB (input) INTEGER */ /* The leading dimension of the array B. LDB >= M. */ /* WORK (workspace) REAL array, dimension (LWORK) */ /* LWORK (input) INTEGER */ /* The length of the array WORK. LWORK must be at least NRHS, */ /* and should be at least NRHS*NB, where NB is the block size */ /* for this environment. */ /* INFO (output) INTEGER */ /* = 0: successful exit */ /* < 0: if INFO = -i, the i-th argument had an illegal value */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input arguments. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; --tau; b_dim1 = *ldb; b_offset = 1 + b_dim1; b -= b_offset; --work; /* Function Body */ *info = 0; if (*m < 0) { *info = -1; } else if (*n < 0 || *n > *m) { *info = -2; } else if (*nrhs < 0) { *info = -3; } else if (*lda < max(1,*m)) { *info = -5; } else if (*ldb < max(1,*m)) { *info = -8; } else if (*lwork < 1 || *lwork < *nrhs && *m > 0 && *n > 0) { *info = -10; } if (*info != 0) { i__1 = -(*info); xerbla_("SGEQRS", &i__1); return 0; } /* Quick return if possible */ if (*n == 0 || *nrhs == 0 || *m == 0) { return 0; } /* B := Q' * B */ sormqr_("Left", "Transpose", m, nrhs, n, &a[a_offset], lda, &tau[1], &b[ b_offset], ldb, &work[1], lwork, info); /* Solve R*X = B(1:n,:) */ strsm_("Left", "Upper", "No transpose", "Non-unit", n, nrhs, &c_b9, &a[ a_offset], lda, &b[b_offset], ldb); return 0; /* End of SGEQRS */ } /* sgeqrs_ */
/* Subroutine */ int sgegv_(char *jobvl, char *jobvr, integer *n, real *a, integer *lda, real *b, integer *ldb, real *alphar, real *alphai, real *beta, real *vl, integer *ldvl, real *vr, integer *ldvr, real *work, integer *lwork, integer *info) { /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, vl_dim1, vl_offset, vr_dim1, vr_offset, i__1, i__2; real r__1, r__2, r__3, r__4; /* Local variables */ integer jc, nb, in, jr, nb1, nb2, nb3, ihi, ilo; real eps; logical ilv; real absb, anrm, bnrm; integer itau; real temp; logical ilvl, ilvr; integer lopt; real anrm1, anrm2, bnrm1, bnrm2, absai, scale, absar, sbeta; extern logical lsame_(char *, char *); integer ileft, iinfo, icols, iwork, irows; real salfai; extern /* Subroutine */ int sggbak_(char *, char *, integer *, integer *, integer *, real *, real *, integer *, real *, integer *, integer * ), sggbal_(char *, integer *, real *, integer *, real *, integer *, integer *, integer *, real *, real *, real *, integer *); real salfar; extern real slamch_(char *), slange_(char *, integer *, integer *, real *, integer *, real *); real safmin; extern /* Subroutine */ int sgghrd_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, integer *, real *, integer * , real *, integer *, integer *); real safmax; char chtemp[1]; logical ldumma[1]; extern /* Subroutine */ int slascl_(char *, integer *, integer *, real *, real *, integer *, integer *, real *, integer *, integer *), xerbla_(char *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *); integer ijobvl, iright; logical ilimit; extern /* Subroutine */ int sgeqrf_(integer *, integer *, real *, integer *, real *, real *, integer *, integer *); integer ijobvr; extern /* Subroutine */ int slacpy_(char *, integer *, integer *, real *, integer *, real *, integer *), slaset_(char *, integer *, integer *, real *, real *, real *, integer *), stgevc_( char *, char *, logical *, integer *, real *, integer *, real *, integer *, real *, integer *, real *, integer *, integer *, integer *, real *, integer *); real onepls; integer lwkmin; extern /* Subroutine */ int shgeqz_(char *, char *, char *, integer *, integer *, integer *, real *, integer *, real *, integer *, real * , real *, real *, real *, integer *, real *, integer *, real *, integer *, integer *), sorgqr_(integer *, integer *, integer *, real *, integer *, real *, real *, integer * , integer *); integer lwkopt; logical lquery; extern /* Subroutine */ int sormqr_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *); /* -- LAPACK driver routine (version 3.4.0) -- */ /* -- LAPACK is a software package provided by Univ. of Tennessee, -- */ /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */ /* November 2011 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. Local Arrays .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Decode the input arguments */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; b_dim1 = *ldb; b_offset = 1 + b_dim1; b -= b_offset; --alphar; --alphai; --beta; vl_dim1 = *ldvl; vl_offset = 1 + vl_dim1; vl -= vl_offset; vr_dim1 = *ldvr; vr_offset = 1 + vr_dim1; vr -= vr_offset; --work; /* Function Body */ if (lsame_(jobvl, "N")) { ijobvl = 1; ilvl = FALSE_; } else if (lsame_(jobvl, "V")) { ijobvl = 2; ilvl = TRUE_; } else { ijobvl = -1; ilvl = FALSE_; } if (lsame_(jobvr, "N")) { ijobvr = 1; ilvr = FALSE_; } else if (lsame_(jobvr, "V")) { ijobvr = 2; ilvr = TRUE_; } else { ijobvr = -1; ilvr = FALSE_; } ilv = ilvl || ilvr; /* Test the input arguments */ /* Computing MAX */ i__1 = *n << 3; lwkmin = max(i__1,1); lwkopt = lwkmin; work[1] = (real) lwkopt; lquery = *lwork == -1; *info = 0; if (ijobvl <= 0) { *info = -1; } else if (ijobvr <= 0) { *info = -2; } else if (*n < 0) { *info = -3; } else if (*lda < max(1,*n)) { *info = -5; } else if (*ldb < max(1,*n)) { *info = -7; } else if (*ldvl < 1 || ilvl && *ldvl < *n) { *info = -12; } else if (*ldvr < 1 || ilvr && *ldvr < *n) { *info = -14; } else if (*lwork < lwkmin && ! lquery) { *info = -16; } if (*info == 0) { nb1 = ilaenv_(&c__1, "SGEQRF", " ", n, n, &c_n1, &c_n1); nb2 = ilaenv_(&c__1, "SORMQR", " ", n, n, n, &c_n1); nb3 = ilaenv_(&c__1, "SORGQR", " ", n, n, n, &c_n1); /* Computing MAX */ i__1 = max(nb1,nb2); nb = max(i__1,nb3); /* Computing MAX */ i__1 = *n * 6; i__2 = *n * (nb + 1); // , expr subst lopt = (*n << 1) + max(i__1,i__2); work[1] = (real) lopt; } if (*info != 0) { i__1 = -(*info); xerbla_("SGEGV ", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*n == 0) { return 0; } /* Get machine constants */ eps = slamch_("E") * slamch_("B"); safmin = slamch_("S"); safmin += safmin; safmax = 1.f / safmin; onepls = eps * 4 + 1.f; /* Scale A */ anrm = slange_("M", n, n, &a[a_offset], lda, &work[1]); anrm1 = anrm; anrm2 = 1.f; if (anrm < 1.f) { if (safmax * anrm < 1.f) { anrm1 = safmin; anrm2 = safmax * anrm; } } if (anrm > 0.f) { slascl_("G", &c_n1, &c_n1, &anrm, &c_b27, n, n, &a[a_offset], lda, & iinfo); if (iinfo != 0) { *info = *n + 10; return 0; } } /* Scale B */ bnrm = slange_("M", n, n, &b[b_offset], ldb, &work[1]); bnrm1 = bnrm; bnrm2 = 1.f; if (bnrm < 1.f) { if (safmax * bnrm < 1.f) { bnrm1 = safmin; bnrm2 = safmax * bnrm; } } if (bnrm > 0.f) { slascl_("G", &c_n1, &c_n1, &bnrm, &c_b27, n, n, &b[b_offset], ldb, & iinfo); if (iinfo != 0) { *info = *n + 10; return 0; } } /* Permute the matrix to make it more nearly triangular */ /* Workspace layout: (8*N words -- "work" requires 6*N words) */ /* left_permutation, right_permutation, work... */ ileft = 1; iright = *n + 1; iwork = iright + *n; sggbal_("P", n, &a[a_offset], lda, &b[b_offset], ldb, &ilo, &ihi, &work[ ileft], &work[iright], &work[iwork], &iinfo); if (iinfo != 0) { *info = *n + 1; goto L120; } /* Reduce B to triangular form, and initialize VL and/or VR */ /* Workspace layout: ("work..." must have at least N words) */ /* left_permutation, right_permutation, tau, work... */ irows = ihi + 1 - ilo; if (ilv) { icols = *n + 1 - ilo; } else { icols = irows; } itau = iwork; iwork = itau + irows; i__1 = *lwork + 1 - iwork; sgeqrf_(&irows, &icols, &b[ilo + ilo * b_dim1], ldb, &work[itau], &work[ iwork], &i__1, &iinfo); if (iinfo >= 0) { /* Computing MAX */ i__1 = lwkopt; i__2 = (integer) work[iwork] + iwork - 1; // , expr subst lwkopt = max(i__1,i__2); } if (iinfo != 0) { *info = *n + 2; goto L120; } i__1 = *lwork + 1 - iwork; sormqr_("L", "T", &irows, &icols, &irows, &b[ilo + ilo * b_dim1], ldb, & work[itau], &a[ilo + ilo * a_dim1], lda, &work[iwork], &i__1, & iinfo); if (iinfo >= 0) { /* Computing MAX */ i__1 = lwkopt; i__2 = (integer) work[iwork] + iwork - 1; // , expr subst lwkopt = max(i__1,i__2); } if (iinfo != 0) { *info = *n + 3; goto L120; } if (ilvl) { slaset_("Full", n, n, &c_b38, &c_b27, &vl[vl_offset], ldvl) ; i__1 = irows - 1; i__2 = irows - 1; slacpy_("L", &i__1, &i__2, &b[ilo + 1 + ilo * b_dim1], ldb, &vl[ilo + 1 + ilo * vl_dim1], ldvl); i__1 = *lwork + 1 - iwork; sorgqr_(&irows, &irows, &irows, &vl[ilo + ilo * vl_dim1], ldvl, &work[ itau], &work[iwork], &i__1, &iinfo); if (iinfo >= 0) { /* Computing MAX */ i__1 = lwkopt; i__2 = (integer) work[iwork] + iwork - 1; // , expr subst lwkopt = max(i__1,i__2); } if (iinfo != 0) { *info = *n + 4; goto L120; } } if (ilvr) { slaset_("Full", n, n, &c_b38, &c_b27, &vr[vr_offset], ldvr) ; } /* Reduce to generalized Hessenberg form */ if (ilv) { /* Eigenvectors requested -- work on whole matrix. */ sgghrd_(jobvl, jobvr, n, &ilo, &ihi, &a[a_offset], lda, &b[b_offset], ldb, &vl[vl_offset], ldvl, &vr[vr_offset], ldvr, &iinfo); } else { sgghrd_("N", "N", &irows, &c__1, &irows, &a[ilo + ilo * a_dim1], lda, &b[ilo + ilo * b_dim1], ldb, &vl[vl_offset], ldvl, &vr[ vr_offset], ldvr, &iinfo); } if (iinfo != 0) { *info = *n + 5; goto L120; } /* Perform QZ algorithm */ /* Workspace layout: ("work..." must have at least 1 word) */ /* left_permutation, right_permutation, work... */ iwork = itau; if (ilv) { *(unsigned char *)chtemp = 'S'; } else { *(unsigned char *)chtemp = 'E'; } i__1 = *lwork + 1 - iwork; shgeqz_(chtemp, jobvl, jobvr, n, &ilo, &ihi, &a[a_offset], lda, &b[ b_offset], ldb, &alphar[1], &alphai[1], &beta[1], &vl[vl_offset], ldvl, &vr[vr_offset], ldvr, &work[iwork], &i__1, &iinfo); if (iinfo >= 0) { /* Computing MAX */ i__1 = lwkopt; i__2 = (integer) work[iwork] + iwork - 1; // , expr subst lwkopt = max(i__1,i__2); } if (iinfo != 0) { if (iinfo > 0 && iinfo <= *n) { *info = iinfo; } else if (iinfo > *n && iinfo <= *n << 1) { *info = iinfo - *n; } else { *info = *n + 6; } goto L120; } if (ilv) { /* Compute Eigenvectors (STGEVC requires 6*N words of workspace) */ if (ilvl) { if (ilvr) { *(unsigned char *)chtemp = 'B'; } else { *(unsigned char *)chtemp = 'L'; } } else { *(unsigned char *)chtemp = 'R'; } stgevc_(chtemp, "B", ldumma, n, &a[a_offset], lda, &b[b_offset], ldb, &vl[vl_offset], ldvl, &vr[vr_offset], ldvr, n, &in, &work[ iwork], &iinfo); if (iinfo != 0) { *info = *n + 7; goto L120; } /* Undo balancing on VL and VR, rescale */ if (ilvl) { sggbak_("P", "L", n, &ilo, &ihi, &work[ileft], &work[iright], n, & vl[vl_offset], ldvl, &iinfo); if (iinfo != 0) { *info = *n + 8; goto L120; } i__1 = *n; for (jc = 1; jc <= i__1; ++jc) { if (alphai[jc] < 0.f) { goto L50; } temp = 0.f; if (alphai[jc] == 0.f) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ r__2 = temp; r__3 = (r__1 = vl[jr + jc * vl_dim1], f2c_abs(r__1)); // , expr subst temp = max(r__2,r__3); /* L10: */ } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ r__3 = temp; r__4 = (r__1 = vl[jr + jc * vl_dim1], f2c_abs(r__1)) + (r__2 = vl[jr + (jc + 1) * vl_dim1], f2c_abs(r__2)); // , expr subst temp = max(r__3,r__4); /* L20: */ } } if (temp < safmin) { goto L50; } temp = 1.f / temp; if (alphai[jc] == 0.f) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { vl[jr + jc * vl_dim1] *= temp; /* L30: */ } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { vl[jr + jc * vl_dim1] *= temp; vl[jr + (jc + 1) * vl_dim1] *= temp; /* L40: */ } } L50: ; } } if (ilvr) { sggbak_("P", "R", n, &ilo, &ihi, &work[ileft], &work[iright], n, & vr[vr_offset], ldvr, &iinfo); if (iinfo != 0) { *info = *n + 9; goto L120; } i__1 = *n; for (jc = 1; jc <= i__1; ++jc) { if (alphai[jc] < 0.f) { goto L100; } temp = 0.f; if (alphai[jc] == 0.f) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ r__2 = temp; r__3 = (r__1 = vr[jr + jc * vr_dim1], f2c_abs(r__1)); // , expr subst temp = max(r__2,r__3); /* L60: */ } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ r__3 = temp; r__4 = (r__1 = vr[jr + jc * vr_dim1], f2c_abs(r__1)) + (r__2 = vr[jr + (jc + 1) * vr_dim1], f2c_abs(r__2)); // , expr subst temp = max(r__3,r__4); /* L70: */ } } if (temp < safmin) { goto L100; } temp = 1.f / temp; if (alphai[jc] == 0.f) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { vr[jr + jc * vr_dim1] *= temp; /* L80: */ } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { vr[jr + jc * vr_dim1] *= temp; vr[jr + (jc + 1) * vr_dim1] *= temp; /* L90: */ } } L100: ; } } /* End of eigenvector calculation */ } /* Undo scaling in alpha, beta */ /* Note: this does not give the alpha and beta for the unscaled */ /* problem. */ /* Un-scaling is limited to avoid underflow in alpha and beta */ /* if they are significant. */ i__1 = *n; for (jc = 1; jc <= i__1; ++jc) { absar = (r__1 = alphar[jc], f2c_abs(r__1)); absai = (r__1 = alphai[jc], f2c_abs(r__1)); absb = (r__1 = beta[jc], f2c_abs(r__1)); salfar = anrm * alphar[jc]; salfai = anrm * alphai[jc]; sbeta = bnrm * beta[jc]; ilimit = FALSE_; scale = 1.f; /* Check for significant underflow in ALPHAI */ /* Computing MAX */ r__1 = safmin, r__2 = eps * absar; r__1 = max(r__1,r__2); r__2 = eps * absb; // ; expr subst if (f2c_abs(salfai) < safmin && absai >= max(r__1,r__2)) { ilimit = TRUE_; /* Computing MAX */ r__1 = onepls * safmin; r__2 = anrm2 * absai; // , expr subst scale = onepls * safmin / anrm1 / max(r__1,r__2); } else if (salfai == 0.f) { /* If insignificant underflow in ALPHAI, then make the */ /* conjugate eigenvalue real. */ if (alphai[jc] < 0.f && jc > 1) { alphai[jc - 1] = 0.f; } else if (alphai[jc] > 0.f && jc < *n) { alphai[jc + 1] = 0.f; } } /* Check for significant underflow in ALPHAR */ /* Computing MAX */ r__1 = safmin, r__2 = eps * absai; r__1 = max(r__1,r__2); r__2 = eps * absb; // ; expr subst if (f2c_abs(salfar) < safmin && absar >= max(r__1,r__2)) { ilimit = TRUE_; /* Computing MAX */ /* Computing MAX */ r__3 = onepls * safmin; r__4 = anrm2 * absar; // , expr subst r__1 = scale; r__2 = onepls * safmin / anrm1 / max(r__3,r__4); // , expr subst scale = max(r__1,r__2); } /* Check for significant underflow in BETA */ /* Computing MAX */ r__1 = safmin, r__2 = eps * absar; r__1 = max(r__1,r__2); r__2 = eps * absai; // ; expr subst if (f2c_abs(sbeta) < safmin && absb >= max(r__1,r__2)) { ilimit = TRUE_; /* Computing MAX */ /* Computing MAX */ r__3 = onepls * safmin; r__4 = bnrm2 * absb; // , expr subst r__1 = scale; r__2 = onepls * safmin / bnrm1 / max(r__3,r__4); // , expr subst scale = max(r__1,r__2); } /* Check for possible overflow when limiting scaling */ if (ilimit) { /* Computing MAX */ r__1 = f2c_abs(salfar), r__2 = f2c_abs(salfai); r__1 = max(r__1,r__2); r__2 = f2c_abs(sbeta); // ; expr subst temp = scale * safmin * max(r__1,r__2); if (temp > 1.f) { scale /= temp; } if (scale < 1.f) { ilimit = FALSE_; } } /* Recompute un-scaled ALPHAR, ALPHAI, BETA if necessary. */ if (ilimit) { salfar = scale * alphar[jc] * anrm; salfai = scale * alphai[jc] * anrm; sbeta = scale * beta[jc] * bnrm; } alphar[jc] = salfar; alphai[jc] = salfai; beta[jc] = sbeta; /* L110: */ } L120: work[1] = (real) lwkopt; return 0; /* End of SGEGV */ }
/* Subroutine */ int sggev_(char *jobvl, char *jobvr, integer *n, real *a, integer *lda, real *b, integer *ldb, real *alphar, real *alphai, real *beta, real *vl, integer *ldvl, real *vr, integer *ldvr, real *work, integer *lwork, integer *info) { /* -- LAPACK driver 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 ======= SGGEV computes for a pair of N-by-N real nonsymmetric matrices (A,B) the generalized eigenvalues, and optionally, the left and/or right generalized eigenvectors. A generalized eigenvalue for a pair of matrices (A,B) is a scalar lambda or a ratio alpha/beta = lambda, such that A - lambda*B is singular. It is usually represented as the pair (alpha,beta), as there is a reasonable interpretation for beta=0, and even for both being zero. The right eigenvector v(j) corresponding to the eigenvalue lambda(j) of (A,B) satisfies A * v(j) = lambda(j) * B * v(j). The left eigenvector u(j) corresponding to the eigenvalue lambda(j) of (A,B) satisfies u(j)**H * A = lambda(j) * u(j)**H * B . where u(j)**H is the conjugate-transpose of u(j). Arguments ========= JOBVL (input) CHARACTER*1 = 'N': do not compute the left generalized eigenvectors; = 'V': compute the left generalized eigenvectors. JOBVR (input) CHARACTER*1 = 'N': do not compute the right generalized eigenvectors; = 'V': compute the right generalized eigenvectors. N (input) INTEGER The order of the matrices A, B, VL, and VR. N >= 0. A (input/output) REAL array, dimension (LDA, N) On entry, the matrix A in the pair (A,B). On exit, A has been overwritten. LDA (input) INTEGER The leading dimension of A. LDA >= max(1,N). B (input/output) REAL array, dimension (LDB, N) On entry, the matrix B in the pair (A,B). On exit, B has been overwritten. LDB (input) INTEGER The leading dimension of B. LDB >= max(1,N). ALPHAR (output) REAL array, dimension (N) ALPHAI (output) REAL array, dimension (N) BETA (output) REAL array, dimension (N) On exit, (ALPHAR(j) + ALPHAI(j)*i)/BETA(j), j=1,...,N, will be the generalized eigenvalues. If ALPHAI(j) is zero, then the j-th eigenvalue is real; if positive, then the j-th and (j+1)-st eigenvalues are a complex conjugate pair, with ALPHAI(j+1) negative. Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j) may easily over- or underflow, and BETA(j) may even be zero. Thus, the user should avoid naively computing the ratio alpha/beta. However, ALPHAR and ALPHAI will be always less than and usually comparable with norm(A) in magnitude, and BETA always less than and usually comparable with norm(B). VL (output) REAL array, dimension (LDVL,N) If JOBVL = 'V', the left eigenvectors u(j) are stored one after another in the columns of VL, in the same order as their eigenvalues. If the j-th eigenvalue is real, then u(j) = VL(:,j), the j-th column of VL. If the j-th and (j+1)-th eigenvalues form a complex conjugate pair, then u(j) = VL(:,j)+i*VL(:,j+1) and u(j+1) = VL(:,j)-i*VL(:,j+1). Each eigenvector will be scaled so the largest component have abs(real part)+abs(imag. part)=1. Not referenced if JOBVL = 'N'. LDVL (input) INTEGER The leading dimension of the matrix VL. LDVL >= 1, and if JOBVL = 'V', LDVL >= N. VR (output) REAL array, dimension (LDVR,N) If JOBVR = 'V', the right eigenvectors v(j) are stored one after another in the columns of VR, in the same order as their eigenvalues. If the j-th eigenvalue is real, then v(j) = VR(:,j), the j-th column of VR. If the j-th and (j+1)-th eigenvalues form a complex conjugate pair, then v(j) = VR(:,j)+i*VR(:,j+1) and v(j+1) = VR(:,j)-i*VR(:,j+1). Each eigenvector will be scaled so the largest component have abs(real part)+abs(imag. part)=1. Not referenced if JOBVR = 'N'. LDVR (input) INTEGER The leading dimension of the matrix VR. LDVR >= 1, and if JOBVR = 'V', LDVR >= N. WORK (workspace/output) REAL array, dimension (LWORK) On exit, if INFO = 0, WORK(1) returns the optimal LWORK. LWORK (input) INTEGER The dimension of the array WORK. LWORK >= max(1,8*N). For good performance, LWORK must generally be larger. If LWORK = -1, then a workspace query is assumed; the routine only calculates the optimal size of the WORK array, returns this value as the first entry of the WORK array, and no error message related to LWORK is issued by XERBLA. INFO (output) INTEGER = 0: successful exit < 0: if INFO = -i, the i-th argument had an illegal value. = 1,...,N: The QZ iteration failed. No eigenvectors have been calculated, but ALPHAR(j), ALPHAI(j), and BETA(j) should be correct for j=INFO+1,...,N. > N: =N+1: other than QZ iteration failed in SHGEQZ. =N+2: error return from STGEVC. ===================================================================== Decode the input arguments Parameter adjustments */ /* Table of constant values */ static integer c__1 = 1; static integer c__0 = 0; static real c_b26 = 0.f; static real c_b27 = 1.f; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, vl_dim1, vl_offset, vr_dim1, vr_offset, i__1, i__2; real r__1, r__2, r__3, r__4; /* Builtin functions */ double sqrt(doublereal); /* Local variables */ static real anrm, bnrm; static integer ierr, itau; static real temp; static logical ilvl, ilvr; static integer iwrk; extern logical lsame_(char *, char *); static integer ileft, icols, irows, jc; extern /* Subroutine */ int slabad_(real *, real *); static integer in, jr; extern /* Subroutine */ int sggbak_(char *, char *, integer *, integer *, integer *, real *, real *, integer *, real *, integer *, integer * ), sggbal_(char *, integer *, real *, integer *, real *, integer *, integer *, integer *, real *, real *, real *, integer *); static logical ilascl, ilbscl; extern doublereal slamch_(char *), slange_(char *, integer *, integer *, real *, integer *, real *); extern /* Subroutine */ int xerbla_(char *, integer *), sgghrd_( char *, char *, integer *, integer *, integer *, real *, integer * , real *, integer *, real *, integer *, real *, integer *, integer *); static logical ldumma[1]; static char chtemp[1]; static real bignum; extern /* Subroutine */ int slascl_(char *, integer *, integer *, real *, real *, integer *, integer *, real *, integer *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *, ftnlen, ftnlen); static integer ijobvl, iright; extern /* Subroutine */ int sgeqrf_(integer *, integer *, real *, integer *, real *, real *, integer *, integer *); static integer ijobvr; extern /* Subroutine */ int slacpy_(char *, integer *, integer *, real *, integer *, real *, integer *), slaset_(char *, integer *, integer *, real *, real *, real *, integer *), stgevc_( char *, char *, logical *, integer *, real *, integer *, real *, integer *, real *, integer *, real *, integer *, integer *, integer *, real *, integer *); static real anrmto, bnrmto; extern /* Subroutine */ int shgeqz_(char *, char *, char *, integer *, integer *, integer *, real *, integer *, real *, integer *, real * , real *, real *, real *, integer *, real *, integer *, real *, integer *, integer *); static integer minwrk, maxwrk; static real smlnum; extern /* Subroutine */ int sorgqr_(integer *, integer *, integer *, real *, integer *, real *, real *, integer *, integer *); static logical lquery; extern /* Subroutine */ int sormqr_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *); static integer ihi, ilo; static real eps; static logical ilv; #define a_ref(a_1,a_2) a[(a_2)*a_dim1 + a_1] #define b_ref(a_1,a_2) b[(a_2)*b_dim1 + a_1] #define vl_ref(a_1,a_2) vl[(a_2)*vl_dim1 + a_1] #define vr_ref(a_1,a_2) vr[(a_2)*vr_dim1 + a_1] a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; b_dim1 = *ldb; b_offset = 1 + b_dim1 * 1; b -= b_offset; --alphar; --alphai; --beta; vl_dim1 = *ldvl; vl_offset = 1 + vl_dim1 * 1; vl -= vl_offset; vr_dim1 = *ldvr; vr_offset = 1 + vr_dim1 * 1; vr -= vr_offset; --work; /* Function Body */ if (lsame_(jobvl, "N")) { ijobvl = 1; ilvl = FALSE_; } else if (lsame_(jobvl, "V")) { ijobvl = 2; ilvl = TRUE_; } else { ijobvl = -1; ilvl = FALSE_; } if (lsame_(jobvr, "N")) { ijobvr = 1; ilvr = FALSE_; } else if (lsame_(jobvr, "V")) { ijobvr = 2; ilvr = TRUE_; } else { ijobvr = -1; ilvr = FALSE_; } ilv = ilvl || ilvr; /* Test the input arguments */ *info = 0; lquery = *lwork == -1; if (ijobvl <= 0) { *info = -1; } else if (ijobvr <= 0) { *info = -2; } else if (*n < 0) { *info = -3; } else if (*lda < max(1,*n)) { *info = -5; } else if (*ldb < max(1,*n)) { *info = -7; } else if (*ldvl < 1 || ilvl && *ldvl < *n) { *info = -12; } else if (*ldvr < 1 || ilvr && *ldvr < *n) { *info = -14; } /* Compute workspace (Note: Comments in the code beginning "Workspace:" describe the minimal amount of workspace needed at that point in the code, as well as the preferred amount for good performance. NB refers to the optimal block size for the immediately following subroutine, as returned by ILAENV. The workspace is computed assuming ILO = 1 and IHI = N, the worst case.) */ minwrk = 1; if (*info == 0 && (*lwork >= 1 || lquery)) { maxwrk = *n * 7 + *n * ilaenv_(&c__1, "SGEQRF", " ", n, &c__1, n, & c__0, (ftnlen)6, (ftnlen)1); /* Computing MAX */ i__1 = 1, i__2 = *n << 3; minwrk = max(i__1,i__2); work[1] = (real) maxwrk; } if (*lwork < minwrk && ! lquery) { *info = -16; } if (*info != 0) { i__1 = -(*info); xerbla_("SGGEV ", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*n == 0) { return 0; } /* Get machine constants */ eps = slamch_("P"); smlnum = slamch_("S"); bignum = 1.f / smlnum; slabad_(&smlnum, &bignum); smlnum = sqrt(smlnum) / eps; bignum = 1.f / smlnum; /* Scale A if max element outside range [SMLNUM,BIGNUM] */ anrm = slange_("M", n, n, &a[a_offset], lda, &work[1]); ilascl = FALSE_; if (anrm > 0.f && anrm < smlnum) { anrmto = smlnum; ilascl = TRUE_; } else if (anrm > bignum) { anrmto = bignum; ilascl = TRUE_; } if (ilascl) { slascl_("G", &c__0, &c__0, &anrm, &anrmto, n, n, &a[a_offset], lda, & ierr); } /* Scale B if max element outside range [SMLNUM,BIGNUM] */ bnrm = slange_("M", n, n, &b[b_offset], ldb, &work[1]); ilbscl = FALSE_; if (bnrm > 0.f && bnrm < smlnum) { bnrmto = smlnum; ilbscl = TRUE_; } else if (bnrm > bignum) { bnrmto = bignum; ilbscl = TRUE_; } if (ilbscl) { slascl_("G", &c__0, &c__0, &bnrm, &bnrmto, n, n, &b[b_offset], ldb, & ierr); } /* Permute the matrices A, B to isolate eigenvalues if possible (Workspace: need 6*N) */ ileft = 1; iright = *n + 1; iwrk = iright + *n; sggbal_("P", n, &a[a_offset], lda, &b[b_offset], ldb, &ilo, &ihi, &work[ ileft], &work[iright], &work[iwrk], &ierr); /* Reduce B to triangular form (QR decomposition of B) (Workspace: need N, prefer N*NB) */ irows = ihi + 1 - ilo; if (ilv) { icols = *n + 1 - ilo; } else { icols = irows; } itau = iwrk; iwrk = itau + irows; i__1 = *lwork + 1 - iwrk; sgeqrf_(&irows, &icols, &b_ref(ilo, ilo), ldb, &work[itau], &work[iwrk], & i__1, &ierr); /* Apply the orthogonal transformation to matrix A (Workspace: need N, prefer N*NB) */ i__1 = *lwork + 1 - iwrk; sormqr_("L", "T", &irows, &icols, &irows, &b_ref(ilo, ilo), ldb, &work[ itau], &a_ref(ilo, ilo), lda, &work[iwrk], &i__1, &ierr); /* Initialize VL (Workspace: need N, prefer N*NB) */ if (ilvl) { slaset_("Full", n, n, &c_b26, &c_b27, &vl[vl_offset], ldvl) ; i__1 = irows - 1; i__2 = irows - 1; slacpy_("L", &i__1, &i__2, &b_ref(ilo + 1, ilo), ldb, &vl_ref(ilo + 1, ilo), ldvl); i__1 = *lwork + 1 - iwrk; sorgqr_(&irows, &irows, &irows, &vl_ref(ilo, ilo), ldvl, &work[itau], &work[iwrk], &i__1, &ierr); } /* Initialize VR */ if (ilvr) { slaset_("Full", n, n, &c_b26, &c_b27, &vr[vr_offset], ldvr) ; } /* Reduce to generalized Hessenberg form (Workspace: none needed) */ if (ilv) { /* Eigenvectors requested -- work on whole matrix. */ sgghrd_(jobvl, jobvr, n, &ilo, &ihi, &a[a_offset], lda, &b[b_offset], ldb, &vl[vl_offset], ldvl, &vr[vr_offset], ldvr, &ierr); } else { sgghrd_("N", "N", &irows, &c__1, &irows, &a_ref(ilo, ilo), lda, & b_ref(ilo, ilo), ldb, &vl[vl_offset], ldvl, &vr[vr_offset], ldvr, &ierr); } /* Perform QZ algorithm (Compute eigenvalues, and optionally, the Schur forms and Schur vectors) (Workspace: need N) */ iwrk = itau; if (ilv) { *(unsigned char *)chtemp = 'S'; } else { *(unsigned char *)chtemp = 'E'; } i__1 = *lwork + 1 - iwrk; shgeqz_(chtemp, jobvl, jobvr, n, &ilo, &ihi, &a[a_offset], lda, &b[ b_offset], ldb, &alphar[1], &alphai[1], &beta[1], &vl[vl_offset], ldvl, &vr[vr_offset], ldvr, &work[iwrk], &i__1, &ierr); if (ierr != 0) { if (ierr > 0 && ierr <= *n) { *info = ierr; } else if (ierr > *n && ierr <= *n << 1) { *info = ierr - *n; } else { *info = *n + 1; } goto L110; } /* Compute Eigenvectors (Workspace: need 6*N) */ if (ilv) { if (ilvl) { if (ilvr) { *(unsigned char *)chtemp = 'B'; } else { *(unsigned char *)chtemp = 'L'; } } else { *(unsigned char *)chtemp = 'R'; } stgevc_(chtemp, "B", ldumma, n, &a[a_offset], lda, &b[b_offset], ldb, &vl[vl_offset], ldvl, &vr[vr_offset], ldvr, n, &in, &work[ iwrk], &ierr); if (ierr != 0) { *info = *n + 2; goto L110; } /* Undo balancing on VL and VR and normalization (Workspace: none needed) */ if (ilvl) { sggbak_("P", "L", n, &ilo, &ihi, &work[ileft], &work[iright], n, & vl[vl_offset], ldvl, &ierr); i__1 = *n; for (jc = 1; jc <= i__1; ++jc) { if (alphai[jc] < 0.f) { goto L50; } temp = 0.f; if (alphai[jc] == 0.f) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ r__2 = temp, r__3 = (r__1 = vl_ref(jr, jc), dabs(r__1) ); temp = dmax(r__2,r__3); /* L10: */ } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ r__3 = temp, r__4 = (r__1 = vl_ref(jr, jc), dabs(r__1) ) + (r__2 = vl_ref(jr, jc + 1), dabs(r__2)); temp = dmax(r__3,r__4); /* L20: */ } } if (temp < smlnum) { goto L50; } temp = 1.f / temp; if (alphai[jc] == 0.f) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { vl_ref(jr, jc) = vl_ref(jr, jc) * temp; /* L30: */ } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { vl_ref(jr, jc) = vl_ref(jr, jc) * temp; vl_ref(jr, jc + 1) = vl_ref(jr, jc + 1) * temp; /* L40: */ } } L50: ; } } if (ilvr) { sggbak_("P", "R", n, &ilo, &ihi, &work[ileft], &work[iright], n, & vr[vr_offset], ldvr, &ierr); i__1 = *n; for (jc = 1; jc <= i__1; ++jc) { if (alphai[jc] < 0.f) { goto L100; } temp = 0.f; if (alphai[jc] == 0.f) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ r__2 = temp, r__3 = (r__1 = vr_ref(jr, jc), dabs(r__1) ); temp = dmax(r__2,r__3); /* L60: */ } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ r__3 = temp, r__4 = (r__1 = vr_ref(jr, jc), dabs(r__1) ) + (r__2 = vr_ref(jr, jc + 1), dabs(r__2)); temp = dmax(r__3,r__4); /* L70: */ } } if (temp < smlnum) { goto L100; } temp = 1.f / temp; if (alphai[jc] == 0.f) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { vr_ref(jr, jc) = vr_ref(jr, jc) * temp; /* L80: */ } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { vr_ref(jr, jc) = vr_ref(jr, jc) * temp; vr_ref(jr, jc + 1) = vr_ref(jr, jc + 1) * temp; /* L90: */ } } L100: ; } } /* End of eigenvector calculation */ } /* Undo scaling if necessary */ if (ilascl) { slascl_("G", &c__0, &c__0, &anrmto, &anrm, n, &c__1, &alphar[1], n, & ierr); slascl_("G", &c__0, &c__0, &anrmto, &anrm, n, &c__1, &alphai[1], n, & ierr); } if (ilbscl) { slascl_("G", &c__0, &c__0, &bnrmto, &bnrm, n, &c__1, &beta[1], n, & ierr); } L110: work[1] = (real) maxwrk; return 0; /* End of SGGEV */ } /* sggev_ */
/* Subroutine */ int sgelss_(integer *m, integer *n, integer *nrhs, real *a, integer *lda, real *b, integer *ldb, real *s, real *rcond, integer * rank, real *work, integer *lwork, integer *info) { /* -- LAPACK driver routine (version 2.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University September 30, 1994 Purpose ======= SGELSS computes the minimum norm solution to a real linear least squares problem: Minimize 2-norm(| b - A*x |). using the singular value decomposition (SVD) of A. A is an M-by-N matrix which may be rank-deficient. Several right hand side vectors b and solution vectors x can be handled in a single call; they are stored as the columns of the M-by-NRHS right hand side matrix B and the N-by-NRHS solution matrix X. The effective rank of A is determined by treating as zero those singular values which are less than RCOND times the largest singular value. Arguments ========= M (input) INTEGER The number of rows of the matrix A. M >= 0. N (input) INTEGER The number of columns of the matrix A. N >= 0. NRHS (input) INTEGER The number of right hand sides, i.e., the number of columns of the matrices B and X. NRHS >= 0. A (input/output) REAL array, dimension (LDA,N) On entry, the M-by-N matrix A. On exit, the first min(m,n) rows of A are overwritten with its right singular vectors, stored rowwise. LDA (input) INTEGER The leading dimension of the array A. LDA >= max(1,M). B (input/output) REAL array, dimension (LDB,NRHS) On entry, the M-by-NRHS right hand side matrix B. On exit, B is overwritten by the N-by-NRHS solution matrix X. If m >= n and RANK = n, the residual sum-of-squares for the solution in the i-th column is given by the sum of squares of elements n+1:m in that column. LDB (input) INTEGER The leading dimension of the array B. LDB >= max(1,max(M,N)). S (output) REAL array, dimension (min(M,N)) The singular values of A in decreasing order. The condition number of A in the 2-norm = S(1)/S(min(m,n)). RCOND (input) REAL RCOND is used to determine the effective rank of A. Singular values S(i) <= RCOND*S(1) are treated as zero. If RCOND < 0, machine precision is used instead. RANK (output) INTEGER The effective rank of A, i.e., the number of singular values which are greater than RCOND*S(1). WORK (workspace/output) REAL array, dimension (LWORK) On exit, if INFO = 0, WORK(1) returns the optimal LWORK. LWORK (input) INTEGER The dimension of the array WORK. LWORK >= 1, and also: LWORK >= 3*min(M,N) + max( 2*min(M,N), max(M,N), NRHS ) For good performance, LWORK should generally be larger. INFO (output) INTEGER = 0: successful exit < 0: if INFO = -i, the i-th argument had an illegal value. > 0: the algorithm for computing the SVD failed to converge; if INFO = i, i off-diagonal elements of an intermediate bidiagonal form did not converge to zero. ===================================================================== Test the input arguments Parameter adjustments Function Body */ /* Table of constant values */ static integer c__6 = 6; static integer c_n1 = -1; static integer c__1 = 1; static integer c__0 = 0; static real c_b74 = 0.f; static real c_b108 = 1.f; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, i__1, i__2, i__3, i__4; real r__1; /* Local variables */ static real anrm, bnrm; static integer itau; static real vdum[1]; static integer i, iascl, ibscl, chunk; extern /* Subroutine */ int sgemm_(char *, char *, integer *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *); static real sfmin; static integer minmn, maxmn; extern /* Subroutine */ int sgemv_(char *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *); static integer itaup, itauq; extern /* Subroutine */ int srscl_(integer *, real *, real *, integer *); static integer mnthr, iwork; extern /* Subroutine */ int scopy_(integer *, real *, integer *, real *, integer *); static integer bl, ie, il; extern /* Subroutine */ int slabad_(real *, real *); static integer mm, bdspac; extern /* Subroutine */ int sgebrd_(integer *, integer *, real *, integer *, real *, real *, real *, real *, real *, integer *, integer *); extern doublereal slamch_(char *), slange_(char *, integer *, integer *, real *, integer *, real *); extern /* Subroutine */ int xerbla_(char *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *, ftnlen, ftnlen); static real bignum; extern /* Subroutine */ int sgelqf_(integer *, integer *, real *, integer *, real *, real *, integer *, integer *), slascl_(char *, integer *, integer *, real *, real *, integer *, integer *, real *, integer *, integer *), sgeqrf_(integer *, integer *, real *, integer *, real *, real *, integer *, integer *), slacpy_(char *, integer *, integer *, real *, integer *, real *, integer *), slaset_(char *, integer *, integer *, real *, real *, real *, integer *), sbdsqr_(char *, integer *, integer *, integer *, integer *, real *, real *, real *, integer *, real *, integer *, real *, integer *, real *, integer *), sorgbr_( char *, integer *, integer *, integer *, real *, integer *, real * , real *, integer *, integer *); static integer ldwork; extern /* Subroutine */ int sormbr_(char *, char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer * , real *, integer *, integer *); static integer minwrk, maxwrk; static real smlnum; extern /* Subroutine */ int sormlq_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *), sormqr_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real * , integer *, real *, integer *, integer *); static real eps, thr; #define S(I) s[(I)-1] #define WORK(I) work[(I)-1] #define A(I,J) a[(I)-1 + ((J)-1)* ( *lda)] #define B(I,J) b[(I)-1 + ((J)-1)* ( *ldb)] *info = 0; minmn = min(*m,*n); maxmn = max(*m,*n); mnthr = ilaenv_(&c__6, "SGELSS", " ", m, n, nrhs, &c_n1, 6L, 1L); if (*m < 0) { *info = -1; } else if (*n < 0) { *info = -2; } else if (*nrhs < 0) { *info = -3; } else if (*lda < max(1,*m)) { *info = -5; } else if (*ldb < max(1,maxmn)) { *info = -7; } /* Compute workspace (Note: Comments in the code beginning "Workspace:" describe the minimal amount of workspace needed at that point in the code, as well as the preferred amount for good performance. NB refers to the optimal block size for the immediately following subroutine, as returned by ILAENV.) */ minwrk = 1; if (*info == 0 && *lwork >= 1) { maxwrk = 0; mm = *m; if (*m >= *n && *m >= mnthr) { /* Path 1a - overdetermined, with many more rows than co lumns */ mm = *n; /* Computing MAX */ i__1 = maxwrk, i__2 = *n + *n * ilaenv_(&c__1, "SGEQRF", " ", m, n, &c_n1, &c_n1, 6L, 1L); maxwrk = max(i__1,i__2); /* Computing MAX */ i__1 = maxwrk, i__2 = *n + *nrhs * ilaenv_(&c__1, "SORMQR", "LT", m, nrhs, n, &c_n1, 6L, 2L); maxwrk = max(i__1,i__2); } if (*m >= *n) { /* Path 1 - overdetermined or exactly determined Compute workspace neede for SBDSQR Computing MAX */ i__1 = 1, i__2 = *n * 5 - 4; bdspac = max(i__1,i__2); /* Computing MAX */ i__1 = maxwrk, i__2 = *n * 3 + (mm + *n) * ilaenv_(&c__1, "SGEBRD" , " ", &mm, n, &c_n1, &c_n1, 6L, 1L); maxwrk = max(i__1,i__2); /* Computing MAX */ i__1 = maxwrk, i__2 = *n * 3 + *nrhs * ilaenv_(&c__1, "SORMBR", "QLT", &mm, nrhs, n, &c_n1, 6L, 3L); maxwrk = max(i__1,i__2); /* Computing MAX */ i__1 = maxwrk, i__2 = *n * 3 + (*n - 1) * ilaenv_(&c__1, "SORGBR", "P", n, n, n, &c_n1, 6L, 1L); maxwrk = max(i__1,i__2); maxwrk = max(maxwrk,bdspac); /* Computing MAX */ i__1 = maxwrk, i__2 = *n * *nrhs; maxwrk = max(i__1,i__2); /* Computing MAX */ i__1 = *n * 3 + mm, i__2 = *n * 3 + *nrhs, i__1 = max(i__1,i__2); minwrk = max(i__1,bdspac); maxwrk = max(minwrk,maxwrk); } if (*n > *m) { /* Compute workspace neede for SBDSQR Computing MAX */ i__1 = 1, i__2 = *m * 5 - 4; bdspac = max(i__1,i__2); /* Computing MAX */ i__1 = *m * 3 + *nrhs, i__2 = *m * 3 + *n, i__1 = max(i__1,i__2); minwrk = max(i__1,bdspac); if (*n >= mnthr) { /* Path 2a - underdetermined, with many more colu mns than rows */ maxwrk = *m + *m * ilaenv_(&c__1, "SGELQF", " ", m, n, &c_n1, &c_n1, 6L, 1L); /* Computing MAX */ i__1 = maxwrk, i__2 = *m * *m + (*m << 2) + (*m << 1) * ilaenv_(&c__1, "SGEBRD", " ", m, m, &c_n1, &c_n1, 6L, 1L); maxwrk = max(i__1,i__2); /* Computing MAX */ i__1 = maxwrk, i__2 = *m * *m + (*m << 2) + *nrhs * ilaenv_(& c__1, "SORMBR", "QLT", m, nrhs, m, &c_n1, 6L, 3L); maxwrk = max(i__1,i__2); /* Computing MAX */ i__1 = maxwrk, i__2 = *m * *m + (*m << 2) + (*m - 1) * ilaenv_(&c__1, "SORGBR", "P", m, m, m, &c_n1, 6L, 1L); maxwrk = max(i__1,i__2); /* Computing MAX */ i__1 = maxwrk, i__2 = *m * *m + *m + bdspac; maxwrk = max(i__1,i__2); if (*nrhs > 1) { /* Computing MAX */ i__1 = maxwrk, i__2 = *m * *m + *m + *m * *nrhs; maxwrk = max(i__1,i__2); } else { /* Computing MAX */ i__1 = maxwrk, i__2 = *m * *m + (*m << 1); maxwrk = max(i__1,i__2); } /* Computing MAX */ i__1 = maxwrk, i__2 = *m + *nrhs * ilaenv_(&c__1, "SORMLQ", "LT", n, nrhs, m, &c_n1, 6L, 2L); maxwrk = max(i__1,i__2); } else { /* Path 2 - underdetermined */ maxwrk = *m * 3 + (*n + *m) * ilaenv_(&c__1, "SGEBRD", " ", m, n, &c_n1, &c_n1, 6L, 1L); /* Computing MAX */ i__1 = maxwrk, i__2 = *m * 3 + *nrhs * ilaenv_(&c__1, "SORMBR" , "QLT", m, nrhs, m, &c_n1, 6L, 3L); maxwrk = max(i__1,i__2); /* Computing MAX */ i__1 = maxwrk, i__2 = *m * 3 + *m * ilaenv_(&c__1, "SORGBR", "P", m, n, m, &c_n1, 6L, 1L); maxwrk = max(i__1,i__2); maxwrk = max(maxwrk,bdspac); /* Computing MAX */ i__1 = maxwrk, i__2 = *n * *nrhs; maxwrk = max(i__1,i__2); } } maxwrk = max(minwrk,maxwrk); WORK(1) = (real) maxwrk; } minwrk = max(minwrk,1); if (*lwork < minwrk) { *info = -12; } if (*info != 0) { i__1 = -(*info); xerbla_("SGELSS", &i__1); return 0; } /* Quick return if possible */ if (*m == 0 || *n == 0) { *rank = 0; return 0; } /* Get machine parameters */ eps = slamch_("P"); sfmin = slamch_("S"); smlnum = sfmin / eps; bignum = 1.f / smlnum; slabad_(&smlnum, &bignum); /* Scale A if max element outside range [SMLNUM,BIGNUM] */ anrm = slange_("M", m, n, &A(1,1), lda, &WORK(1)); iascl = 0; if (anrm > 0.f && anrm < smlnum) { /* Scale matrix norm up to SMLNUM */ slascl_("G", &c__0, &c__0, &anrm, &smlnum, m, n, &A(1,1), lda, info); iascl = 1; } else if (anrm > bignum) { /* Scale matrix norm down to BIGNUM */ slascl_("G", &c__0, &c__0, &anrm, &bignum, m, n, &A(1,1), lda, info); iascl = 2; } else if (anrm == 0.f) { /* VISMatrix all zero. Return zero solution. */ i__1 = max(*m,*n); slaset_("F", &i__1, nrhs, &c_b74, &c_b74, &B(1,1), ldb); slaset_("F", &minmn, &c__1, &c_b74, &c_b74, &S(1), &c__1); *rank = 0; goto L70; } /* Scale B if max element outside range [SMLNUM,BIGNUM] */ bnrm = slange_("M", m, nrhs, &B(1,1), ldb, &WORK(1)); ibscl = 0; if (bnrm > 0.f && bnrm < smlnum) { /* Scale matrix norm up to SMLNUM */ slascl_("G", &c__0, &c__0, &bnrm, &smlnum, m, nrhs, &B(1,1), ldb, info); ibscl = 1; } else if (bnrm > bignum) { /* Scale matrix norm down to BIGNUM */ slascl_("G", &c__0, &c__0, &bnrm, &bignum, m, nrhs, &B(1,1), ldb, info); ibscl = 2; } /* Overdetermined case */ if (*m >= *n) { /* Path 1 - overdetermined or exactly determined */ mm = *m; if (*m >= mnthr) { /* Path 1a - overdetermined, with many more rows than co lumns */ mm = *n; itau = 1; iwork = itau + *n; /* Compute A=Q*R (Workspace: need 2*N, prefer N+N*NB) */ i__1 = *lwork - iwork + 1; sgeqrf_(m, n, &A(1,1), lda, &WORK(itau), &WORK(iwork), &i__1, info); /* Multiply B by transpose(Q) (Workspace: need N+NRHS, prefer N+NRHS*NB) */ i__1 = *lwork - iwork + 1; sormqr_("L", "T", m, nrhs, n, &A(1,1), lda, &WORK(itau), &B(1,1), ldb, &WORK(iwork), &i__1, info); /* Zero out below R */ if (*n > 1) { i__1 = *n - 1; i__2 = *n - 1; slaset_("L", &i__1, &i__2, &c_b74, &c_b74, &A(2,1), lda); } } ie = 1; itauq = ie + *n; itaup = itauq + *n; iwork = itaup + *n; /* Bidiagonalize R in A (Workspace: need 3*N+MM, prefer 3*N+(MM+N)*NB) */ i__1 = *lwork - iwork + 1; sgebrd_(&mm, n, &A(1,1), lda, &S(1), &WORK(ie), &WORK(itauq), & WORK(itaup), &WORK(iwork), &i__1, info); /* Multiply B by transpose of left bidiagonalizing vectors of R (Workspace: need 3*N+NRHS, prefer 3*N+NRHS*NB) */ i__1 = *lwork - iwork + 1; sormbr_("Q", "L", "T", &mm, nrhs, n, &A(1,1), lda, &WORK(itauq), &B(1,1), ldb, &WORK(iwork), &i__1, info); /* Generate right bidiagonalizing vectors of R in A (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB) */ i__1 = *lwork - iwork + 1; sorgbr_("P", n, n, n, &A(1,1), lda, &WORK(itaup), &WORK(iwork), & i__1, info); iwork = ie + *n; /* Perform bidiagonal QR iteration multiply B by transpose of left singular vectors compute right singular vectors in A (Workspace: need BDSPAC) */ sbdsqr_("U", n, n, &c__0, nrhs, &S(1), &WORK(ie), &A(1,1), lda, vdum, &c__1, &B(1,1), ldb, &WORK(iwork), info); if (*info != 0) { goto L70; } /* Multiply B by reciprocals of singular values Computing MAX */ r__1 = *rcond * S(1); thr = dmax(r__1,sfmin); if (*rcond < 0.f) { /* Computing MAX */ r__1 = eps * S(1); thr = dmax(r__1,sfmin); } *rank = 0; i__1 = *n; for (i = 1; i <= *n; ++i) { if (S(i) > thr) { srscl_(nrhs, &S(i), &B(i,1), ldb); ++(*rank); } else { slaset_("F", &c__1, nrhs, &c_b74, &c_b74, &B(i,1), ldb); } /* L10: */ } /* Multiply B by right singular vectors (Workspace: need N, prefer N*NRHS) */ if (*lwork >= *ldb * *nrhs && *nrhs > 1) { sgemm_("T", "N", n, nrhs, n, &c_b108, &A(1,1), lda, &B(1,1), ldb, &c_b74, &WORK(1), ldb); slacpy_("G", n, nrhs, &WORK(1), ldb, &B(1,1), ldb); } else if (*nrhs > 1) { chunk = *lwork / *n; i__1 = *nrhs; i__2 = chunk; for (i = 1; chunk < 0 ? i >= *nrhs : i <= *nrhs; i += chunk) { /* Computing MIN */ i__3 = *nrhs - i + 1; bl = min(i__3,chunk); sgemm_("T", "N", n, &bl, n, &c_b108, &A(1,1), lda, &B(1,1), ldb, &c_b74, &WORK(1), n); slacpy_("G", n, &bl, &WORK(1), n, &B(1,1), ldb); /* L20: */ } } else { sgemv_("T", n, n, &c_b108, &A(1,1), lda, &B(1,1), &c__1, &c_b74, &WORK(1), &c__1); scopy_(n, &WORK(1), &c__1, &B(1,1), &c__1); } } else /* if(complicated condition) */ { /* Computing MAX */ i__2 = *m, i__1 = (*m << 1) - 4, i__2 = max(i__2,i__1), i__2 = max( i__2,*nrhs), i__1 = *n - *m * 3; if (*n >= mnthr && *lwork >= (*m << 2) + *m * *m + max(i__2,i__1)) { /* Path 2a - underdetermined, with many more columns than r ows and sufficient workspace for an efficient algorithm */ ldwork = *m; /* Computing MAX Computing MAX */ i__3 = *m, i__4 = (*m << 1) - 4, i__3 = max(i__3,i__4), i__3 = max(i__3,*nrhs), i__4 = *n - *m * 3; i__2 = (*m << 2) + *m * *lda + max(i__3,i__4), i__1 = *m * *lda + *m + *m * *nrhs; if (*lwork >= max(i__2,i__1)) { ldwork = *lda; } itau = 1; iwork = *m + 1; /* Compute A=L*Q (Workspace: need 2*M, prefer M+M*NB) */ i__2 = *lwork - iwork + 1; sgelqf_(m, n, &A(1,1), lda, &WORK(itau), &WORK(iwork), &i__2, info); il = iwork; /* Copy L to WORK(IL), zeroing out above it */ slacpy_("L", m, m, &A(1,1), lda, &WORK(il), &ldwork); i__2 = *m - 1; i__1 = *m - 1; slaset_("U", &i__2, &i__1, &c_b74, &c_b74, &WORK(il + ldwork), & ldwork); ie = il + ldwork * *m; itauq = ie + *m; itaup = itauq + *m; iwork = itaup + *m; /* Bidiagonalize L in WORK(IL) (Workspace: need M*M+5*M, prefer M*M+4*M+2*M*NB) */ i__2 = *lwork - iwork + 1; sgebrd_(m, m, &WORK(il), &ldwork, &S(1), &WORK(ie), &WORK(itauq), &WORK(itaup), &WORK(iwork), &i__2, info); /* Multiply B by transpose of left bidiagonalizing vectors of L (Workspace: need M*M+4*M+NRHS, prefer M*M+4*M+NRHS*NB) */ i__2 = *lwork - iwork + 1; sormbr_("Q", "L", "T", m, nrhs, m, &WORK(il), &ldwork, &WORK( itauq), &B(1,1), ldb, &WORK(iwork), &i__2, info); /* Generate right bidiagonalizing vectors of R in WORK(IL) (Workspace: need M*M+5*M-1, prefer M*M+4*M+(M-1)*NB) */ i__2 = *lwork - iwork + 1; sorgbr_("P", m, m, m, &WORK(il), &ldwork, &WORK(itaup), &WORK( iwork), &i__2, info); iwork = ie + *m; /* Perform bidiagonal QR iteration, computing right singular vectors of L in WORK(IL) and multiplying B by transpose of left singular vectors (Workspace: need M*M+M+BDSPAC) */ sbdsqr_("U", m, m, &c__0, nrhs, &S(1), &WORK(ie), &WORK(il), & ldwork, &A(1,1), lda, &B(1,1), ldb, &WORK(iwork) , info); if (*info != 0) { goto L70; } /* Multiply B by reciprocals of singular values Computing MAX */ r__1 = *rcond * S(1); thr = dmax(r__1,sfmin); if (*rcond < 0.f) { /* Computing MAX */ r__1 = eps * S(1); thr = dmax(r__1,sfmin); } *rank = 0; i__2 = *m; for (i = 1; i <= *m; ++i) { if (S(i) > thr) { srscl_(nrhs, &S(i), &B(i,1), ldb); ++(*rank); } else { slaset_("F", &c__1, nrhs, &c_b74, &c_b74, &B(i,1), ldb); } /* L30: */ } iwork = ie; /* Multiply B by right singular vectors of L in WORK(IL) (Workspace: need M*M+2*M, prefer M*M+M+M*NRHS) */ if (*lwork >= *ldb * *nrhs + iwork - 1 && *nrhs > 1) { sgemm_("T", "N", m, nrhs, m, &c_b108, &WORK(il), &ldwork, &B(1,1), ldb, &c_b74, &WORK(iwork), ldb); slacpy_("G", m, nrhs, &WORK(iwork), ldb, &B(1,1), ldb); } else if (*nrhs > 1) { chunk = (*lwork - iwork + 1) / *m; i__2 = *nrhs; i__1 = chunk; for (i = 1; chunk < 0 ? i >= *nrhs : i <= *nrhs; i += chunk) { /* Computing MIN */ i__3 = *nrhs - i + 1; bl = min(i__3,chunk); sgemm_("T", "N", m, &bl, m, &c_b108, &WORK(il), &ldwork, & B(1,i), ldb, &c_b74, &WORK(iwork), n); slacpy_("G", m, &bl, &WORK(iwork), n, &B(1,1), ldb); /* L40: */ } } else { sgemv_("T", m, m, &c_b108, &WORK(il), &ldwork, &B(1,1), &c__1, &c_b74, &WORK(iwork), &c__1); scopy_(m, &WORK(iwork), &c__1, &B(1,1), &c__1); } /* Zero out below first M rows of B */ i__1 = *n - *m; slaset_("F", &i__1, nrhs, &c_b74, &c_b74, &B(*m+1,1), ldb); iwork = itau + *m; /* Multiply transpose(Q) by B (Workspace: need M+NRHS, prefer M+NRHS*NB) */ i__1 = *lwork - iwork + 1; sormlq_("L", "T", n, nrhs, m, &A(1,1), lda, &WORK(itau), &B(1,1), ldb, &WORK(iwork), &i__1, info); } else { /* Path 2 - remaining underdetermined cases */ ie = 1; itauq = ie + *m; itaup = itauq + *m; iwork = itaup + *m; /* Bidiagonalize A (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB) */ i__1 = *lwork - iwork + 1; sgebrd_(m, n, &A(1,1), lda, &S(1), &WORK(ie), &WORK(itauq), & WORK(itaup), &WORK(iwork), &i__1, info); /* Multiply B by transpose of left bidiagonalizing vectors (Workspace: need 3*M+NRHS, prefer 3*M+NRHS*NB) */ i__1 = *lwork - iwork + 1; sormbr_("Q", "L", "T", m, nrhs, n, &A(1,1), lda, &WORK(itauq) , &B(1,1), ldb, &WORK(iwork), &i__1, info); /* Generate right bidiagonalizing vectors in A (Workspace: need 4*M, prefer 3*M+M*NB) */ i__1 = *lwork - iwork + 1; sorgbr_("P", m, n, m, &A(1,1), lda, &WORK(itaup), &WORK( iwork), &i__1, info); iwork = ie + *m; /* Perform bidiagonal QR iteration, computing right singular vectors of A in A and multiplying B by transpose of left singular vectors (Workspace: need BDSPAC) */ sbdsqr_("L", m, n, &c__0, nrhs, &S(1), &WORK(ie), &A(1,1), lda, vdum, &c__1, &B(1,1), ldb, &WORK(iwork), info); if (*info != 0) { goto L70; } /* Multiply B by reciprocals of singular values Computing MAX */ r__1 = *rcond * S(1); thr = dmax(r__1,sfmin); if (*rcond < 0.f) { /* Computing MAX */ r__1 = eps * S(1); thr = dmax(r__1,sfmin); } *rank = 0; i__1 = *m; for (i = 1; i <= *m; ++i) { if (S(i) > thr) { srscl_(nrhs, &S(i), &B(i,1), ldb); ++(*rank); } else { slaset_("F", &c__1, nrhs, &c_b74, &c_b74, &B(i,1), ldb); } /* L50: */ } /* Multiply B by right singular vectors of A (Workspace: need N, prefer N*NRHS) */ if (*lwork >= *ldb * *nrhs && *nrhs > 1) { sgemm_("T", "N", n, nrhs, m, &c_b108, &A(1,1), lda, &B(1,1), ldb, &c_b74, &WORK(1), ldb); slacpy_("F", n, nrhs, &WORK(1), ldb, &B(1,1), ldb); } else if (*nrhs > 1) { chunk = *lwork / *n; i__1 = *nrhs; i__2 = chunk; for (i = 1; chunk < 0 ? i >= *nrhs : i <= *nrhs; i += chunk) { /* Computing MIN */ i__3 = *nrhs - i + 1; bl = min(i__3,chunk); sgemm_("T", "N", n, &bl, m, &c_b108, &A(1,1), lda, & B(1,i), ldb, &c_b74, &WORK(1), n); slacpy_("F", n, &bl, &WORK(1), n, &B(1,i), ldb); /* L60: */ } } else { sgemv_("T", m, n, &c_b108, &A(1,1), lda, &B(1,1), & c__1, &c_b74, &WORK(1), &c__1); scopy_(n, &WORK(1), &c__1, &B(1,1), &c__1); } } } /* Undo scaling */ if (iascl == 1) { slascl_("G", &c__0, &c__0, &anrm, &smlnum, n, nrhs, &B(1,1), ldb, info); slascl_("G", &c__0, &c__0, &smlnum, &anrm, &minmn, &c__1, &S(1), & minmn, info); } else if (iascl == 2) { slascl_("G", &c__0, &c__0, &anrm, &bignum, n, nrhs, &B(1,1), ldb, info); slascl_("G", &c__0, &c__0, &bignum, &anrm, &minmn, &c__1, &S(1), & minmn, info); } if (ibscl == 1) { slascl_("G", &c__0, &c__0, &smlnum, &bnrm, n, nrhs, &B(1,1), ldb, info); } else if (ibscl == 2) { slascl_("G", &c__0, &c__0, &bignum, &bnrm, n, nrhs, &B(1,1), ldb, info); } L70: WORK(1) = (real) maxwrk; return 0; /* End of SGELSS */ } /* sgelss_ */
/* Subroutine */ int sgelsy_(integer *m, integer *n, integer *nrhs, real *a, integer *lda, real *b, integer *ldb, integer *jpvt, real *rcond, integer *rank, real *work, integer *lwork, integer *info) { /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, i__1, i__2; real r__1, r__2; /* Local variables */ integer i__, j; real c1, c2, s1, s2; integer nb, mn, nb1, nb2, nb3, nb4; real anrm, bnrm, smin, smax; integer iascl, ibscl, ismin, ismax; extern /* Subroutine */ int scopy_(integer *, real *, integer *, real *, integer *); real wsize; extern /* Subroutine */ int strsm_(char *, char *, char *, char *, integer *, integer *, real *, real *, integer *, real *, integer * ), slaic1_(integer *, integer *, real *, real *, real *, real *, real *, real *, real *), sgeqp3_( integer *, integer *, real *, integer *, integer *, real *, real * , integer *, integer *), slabad_(real *, real *); extern doublereal slamch_(char *), slange_(char *, integer *, integer *, real *, integer *, real *); extern /* Subroutine */ int xerbla_(char *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *); real bignum; extern /* Subroutine */ int slascl_(char *, integer *, integer *, real *, real *, integer *, integer *, real *, integer *, integer *), slaset_(char *, integer *, integer *, real *, real *, real *, integer *); integer lwkmin; real sminpr, smaxpr, smlnum; integer lwkopt; logical lquery; extern /* Subroutine */ int sormqr_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *), sormrz_(char *, char *, integer *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *), stzrzf_(integer *, integer *, real *, integer *, real *, real *, integer *, integer *); /* -- LAPACK driver routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SGELSY computes the minimum-norm solution to a real linear least */ /* squares problem: */ /* minimize || A * X - B || */ /* using a complete orthogonal factorization of A. A is an M-by-N */ /* matrix which may be rank-deficient. */ /* Several right hand side vectors b and solution vectors x can be */ /* handled in a single call; they are stored as the columns of the */ /* M-by-NRHS right hand side matrix B and the N-by-NRHS solution */ /* matrix X. */ /* The routine first computes a QR factorization with column pivoting: */ /* A * P = Q * [ R11 R12 ] */ /* [ 0 R22 ] */ /* with R11 defined as the largest leading submatrix whose estimated */ /* condition number is less than 1/RCOND. The order of R11, RANK, */ /* is the effective rank of A. */ /* Then, R22 is considered to be negligible, and R12 is annihilated */ /* by orthogonal transformations from the right, arriving at the */ /* complete orthogonal factorization: */ /* A * P = Q * [ T11 0 ] * Z */ /* [ 0 0 ] */ /* The minimum-norm solution is then */ /* X = P * Z' [ inv(T11)*Q1'*B ] */ /* [ 0 ] */ /* where Q1 consists of the first RANK columns of Q. */ /* This routine is basically identical to the original xGELSX except */ /* three differences: */ /* o The call to the subroutine xGEQPF has been substituted by the */ /* the call to the subroutine xGEQP3. This subroutine is a Blas-3 */ /* version of the QR factorization with column pivoting. */ /* o Matrix B (the right hand side) is updated with Blas-3. */ /* o The permutation of matrix B (the right hand side) is faster and */ /* more simple. */ /* Arguments */ /* ========= */ /* M (input) INTEGER */ /* The number of rows of the matrix A. M >= 0. */ /* N (input) INTEGER */ /* The number of columns of the matrix A. N >= 0. */ /* NRHS (input) INTEGER */ /* The number of right hand sides, i.e., the number of */ /* columns of matrices B and X. NRHS >= 0. */ /* A (input/output) REAL array, dimension (LDA,N) */ /* On entry, the M-by-N matrix A. */ /* On exit, A has been overwritten by details of its */ /* complete orthogonal factorization. */ /* LDA (input) INTEGER */ /* The leading dimension of the array A. LDA >= max(1,M). */ /* B (input/output) REAL array, dimension (LDB,NRHS) */ /* On entry, the M-by-NRHS right hand side matrix B. */ /* On exit, the N-by-NRHS solution matrix X. */ /* LDB (input) INTEGER */ /* The leading dimension of the array B. LDB >= max(1,M,N). */ /* JPVT (input/output) INTEGER array, dimension (N) */ /* On entry, if JPVT(i) .ne. 0, the i-th column of A is permuted */ /* to the front of AP, otherwise column i is a free column. */ /* On exit, if JPVT(i) = k, then the i-th column of AP */ /* was the k-th column of A. */ /* RCOND (input) REAL */ /* RCOND is used to determine the effective rank of A, which */ /* is defined as the order of the largest leading triangular */ /* submatrix R11 in the QR factorization with pivoting of A, */ /* whose estimated condition number < 1/RCOND. */ /* RANK (output) INTEGER */ /* The effective rank of A, i.e., the order of the submatrix */ /* R11. This is the same as the order of the submatrix T11 */ /* in the complete orthogonal factorization of A. */ /* WORK (workspace/output) REAL array, dimension (MAX(1,LWORK)) */ /* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */ /* LWORK (input) INTEGER */ /* The dimension of the array WORK. */ /* The unblocked strategy requires that: */ /* LWORK >= MAX( MN+3*N+1, 2*MN+NRHS ), */ /* where MN = min( M, N ). */ /* The block algorithm requires that: */ /* LWORK >= MAX( MN+2*N+NB*(N+1), 2*MN+NB*NRHS ), */ /* where NB is an upper bound on the blocksize returned */ /* by ILAENV for the routines SGEQP3, STZRZF, STZRQF, SORMQR, */ /* and SORMRZ. */ /* If LWORK = -1, then a workspace query is assumed; the routine */ /* only calculates the optimal size of the WORK array, returns */ /* this value as the first entry of the WORK array, and no error */ /* message related to LWORK is issued by XERBLA. */ /* INFO (output) INTEGER */ /* = 0: successful exit */ /* < 0: If INFO = -i, the i-th argument had an illegal value. */ /* Further Details */ /* =============== */ /* Based on contributions by */ /* A. Petitet, Computer Science Dept., Univ. of Tenn., Knoxville, USA */ /* E. Quintana-Orti, Depto. de Informatica, Universidad Jaime I, Spain */ /* G. Quintana-Orti, Depto. de Informatica, Universidad Jaime I, Spain */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; b_dim1 = *ldb; b_offset = 1 + b_dim1; b -= b_offset; --jpvt; --work; /* Function Body */ mn = min(*m,*n); ismin = mn + 1; ismax = (mn << 1) + 1; /* Test the input arguments. */ *info = 0; lquery = *lwork == -1; if (*m < 0) { *info = -1; } else if (*n < 0) { *info = -2; } else if (*nrhs < 0) { *info = -3; } else if (*lda < max(1,*m)) { *info = -5; } else /* if(complicated condition) */ { /* Computing MAX */ i__1 = max(1,*m); if (*ldb < max(i__1,*n)) { *info = -7; } } /* Figure out optimal block size */ if (*info == 0) { if (mn == 0 || *nrhs == 0) { lwkmin = 1; lwkopt = 1; } else { nb1 = ilaenv_(&c__1, "SGEQRF", " ", m, n, &c_n1, &c_n1); nb2 = ilaenv_(&c__1, "SGERQF", " ", m, n, &c_n1, &c_n1); nb3 = ilaenv_(&c__1, "SORMQR", " ", m, n, nrhs, &c_n1); nb4 = ilaenv_(&c__1, "SORMRQ", " ", m, n, nrhs, &c_n1); /* Computing MAX */ i__1 = max(nb1,nb2), i__1 = max(i__1,nb3); nb = max(i__1,nb4); /* Computing MAX */ i__1 = mn << 1, i__2 = *n + 1, i__1 = max(i__1,i__2), i__2 = mn + *nrhs; lwkmin = mn + max(i__1,i__2); /* Computing MAX */ i__1 = lwkmin, i__2 = mn + (*n << 1) + nb * (*n + 1), i__1 = max( i__1,i__2), i__2 = (mn << 1) + nb * *nrhs; lwkopt = max(i__1,i__2); } work[1] = (real) lwkopt; if (*lwork < lwkmin && ! lquery) { *info = -12; } } if (*info != 0) { i__1 = -(*info); xerbla_("SGELSY", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (mn == 0 || *nrhs == 0) { *rank = 0; return 0; } /* Get machine parameters */ smlnum = slamch_("S") / slamch_("P"); bignum = 1.f / smlnum; slabad_(&smlnum, &bignum); /* Scale A, B if max entries outside range [SMLNUM,BIGNUM] */ anrm = slange_("M", m, n, &a[a_offset], lda, &work[1]); iascl = 0; if (anrm > 0.f && anrm < smlnum) { /* Scale matrix norm up to SMLNUM */ slascl_("G", &c__0, &c__0, &anrm, &smlnum, m, n, &a[a_offset], lda, info); iascl = 1; } else if (anrm > bignum) { /* Scale matrix norm down to BIGNUM */ slascl_("G", &c__0, &c__0, &anrm, &bignum, m, n, &a[a_offset], lda, info); iascl = 2; } else if (anrm == 0.f) { /* Matrix all zero. Return zero solution. */ i__1 = max(*m,*n); slaset_("F", &i__1, nrhs, &c_b31, &c_b31, &b[b_offset], ldb); *rank = 0; goto L70; } bnrm = slange_("M", m, nrhs, &b[b_offset], ldb, &work[1]); ibscl = 0; if (bnrm > 0.f && bnrm < smlnum) { /* Scale matrix norm up to SMLNUM */ slascl_("G", &c__0, &c__0, &bnrm, &smlnum, m, nrhs, &b[b_offset], ldb, info); ibscl = 1; } else if (bnrm > bignum) { /* Scale matrix norm down to BIGNUM */ slascl_("G", &c__0, &c__0, &bnrm, &bignum, m, nrhs, &b[b_offset], ldb, info); ibscl = 2; } /* Compute QR factorization with column pivoting of A: */ /* A * P = Q * R */ i__1 = *lwork - mn; sgeqp3_(m, n, &a[a_offset], lda, &jpvt[1], &work[1], &work[mn + 1], &i__1, info); wsize = mn + work[mn + 1]; /* workspace: MN+2*N+NB*(N+1). */ /* Details of Householder rotations stored in WORK(1:MN). */ /* Determine RANK using incremental condition estimation */ work[ismin] = 1.f; work[ismax] = 1.f; smax = (r__1 = a[a_dim1 + 1], dabs(r__1)); smin = smax; if ((r__1 = a[a_dim1 + 1], dabs(r__1)) == 0.f) { *rank = 0; i__1 = max(*m,*n); slaset_("F", &i__1, nrhs, &c_b31, &c_b31, &b[b_offset], ldb); goto L70; } else { *rank = 1; } L10: if (*rank < mn) { i__ = *rank + 1; slaic1_(&c__2, rank, &work[ismin], &smin, &a[i__ * a_dim1 + 1], &a[ i__ + i__ * a_dim1], &sminpr, &s1, &c1); slaic1_(&c__1, rank, &work[ismax], &smax, &a[i__ * a_dim1 + 1], &a[ i__ + i__ * a_dim1], &smaxpr, &s2, &c2); if (smaxpr * *rcond <= sminpr) { i__1 = *rank; for (i__ = 1; i__ <= i__1; ++i__) { work[ismin + i__ - 1] = s1 * work[ismin + i__ - 1]; work[ismax + i__ - 1] = s2 * work[ismax + i__ - 1]; /* L20: */ } work[ismin + *rank] = c1; work[ismax + *rank] = c2; smin = sminpr; smax = smaxpr; ++(*rank); goto L10; } } /* workspace: 3*MN. */ /* Logically partition R = [ R11 R12 ] */ /* [ 0 R22 ] */ /* where R11 = R(1:RANK,1:RANK) */ /* [R11,R12] = [ T11, 0 ] * Y */ if (*rank < *n) { i__1 = *lwork - (mn << 1); stzrzf_(rank, n, &a[a_offset], lda, &work[mn + 1], &work[(mn << 1) + 1], &i__1, info); } /* workspace: 2*MN. */ /* Details of Householder rotations stored in WORK(MN+1:2*MN) */ /* B(1:M,1:NRHS) := Q' * B(1:M,1:NRHS) */ i__1 = *lwork - (mn << 1); sormqr_("Left", "Transpose", m, nrhs, &mn, &a[a_offset], lda, &work[1], & b[b_offset], ldb, &work[(mn << 1) + 1], &i__1, info); /* Computing MAX */ r__1 = wsize, r__2 = (mn << 1) + work[(mn << 1) + 1]; wsize = dmax(r__1,r__2); /* workspace: 2*MN+NB*NRHS. */ /* B(1:RANK,1:NRHS) := inv(T11) * B(1:RANK,1:NRHS) */ strsm_("Left", "Upper", "No transpose", "Non-unit", rank, nrhs, &c_b54, & a[a_offset], lda, &b[b_offset], ldb); i__1 = *nrhs; for (j = 1; j <= i__1; ++j) { i__2 = *n; for (i__ = *rank + 1; i__ <= i__2; ++i__) { b[i__ + j * b_dim1] = 0.f; /* L30: */ } /* L40: */ } /* B(1:N,1:NRHS) := Y' * B(1:N,1:NRHS) */ if (*rank < *n) { i__1 = *n - *rank; i__2 = *lwork - (mn << 1); sormrz_("Left", "Transpose", n, nrhs, rank, &i__1, &a[a_offset], lda, &work[mn + 1], &b[b_offset], ldb, &work[(mn << 1) + 1], &i__2, info); } /* workspace: 2*MN+NRHS. */ /* B(1:N,1:NRHS) := P * B(1:N,1:NRHS) */ i__1 = *nrhs; for (j = 1; j <= i__1; ++j) { i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { work[jpvt[i__]] = b[i__ + j * b_dim1]; /* L50: */ } scopy_(n, &work[1], &c__1, &b[j * b_dim1 + 1], &c__1); /* L60: */ } /* workspace: N. */ /* Undo scaling */ if (iascl == 1) { slascl_("G", &c__0, &c__0, &anrm, &smlnum, n, nrhs, &b[b_offset], ldb, info); slascl_("U", &c__0, &c__0, &smlnum, &anrm, rank, rank, &a[a_offset], lda, info); } else if (iascl == 2) { slascl_("G", &c__0, &c__0, &anrm, &bignum, n, nrhs, &b[b_offset], ldb, info); slascl_("U", &c__0, &c__0, &bignum, &anrm, rank, rank, &a[a_offset], lda, info); } if (ibscl == 1) { slascl_("G", &c__0, &c__0, &smlnum, &bnrm, n, nrhs, &b[b_offset], ldb, info); } else if (ibscl == 2) { slascl_("G", &c__0, &c__0, &bignum, &bnrm, n, nrhs, &b[b_offset], ldb, info); } L70: work[1] = (real) lwkopt; return 0; /* End of SGELSY */ } /* sgelsy_ */
/* Subroutine */ int sgelsd_(integer *m, integer *n, integer *nrhs, real *a, integer *lda, real *b, integer *ldb, real *s, real *rcond, integer * rank, real *work, integer *lwork, integer *iwork, integer *info) { /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, i__1, i__2, i__3, i__4; /* Builtin functions */ double log(doublereal); /* Local variables */ static real anrm, bnrm; static integer itau, nlvl, iascl, ibscl; static real sfmin; static integer minmn, maxmn, itaup, itauq, mnthr, nwork, ie, il; extern /* Subroutine */ int slabad_(real *, real *); static integer mm; extern /* Subroutine */ int sgebrd_(integer *, integer *, real *, integer *, real *, real *, real *, real *, real *, integer *, integer *); extern doublereal slamch_(char *), slange_(char *, integer *, integer *, real *, integer *, real *); extern /* Subroutine */ int xerbla_(char *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *, ftnlen, ftnlen); static real bignum; extern /* Subroutine */ int sgelqf_(integer *, integer *, real *, integer *, real *, real *, integer *, integer *), slalsd_(char *, integer *, integer *, integer *, real *, real *, real *, integer *, real * , integer *, real *, integer *, integer *), slascl_(char * , integer *, integer *, real *, real *, integer *, integer *, real *, integer *, integer *); static integer wlalsd; extern /* Subroutine */ int sgeqrf_(integer *, integer *, real *, integer *, real *, real *, integer *, integer *), slacpy_(char *, integer *, integer *, real *, integer *, real *, integer *), slaset_(char *, integer *, integer *, real *, real *, real *, integer *); static integer ldwork; extern /* Subroutine */ int sormbr_(char *, char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer * , real *, integer *, integer *); static integer minwrk, maxwrk; static real smlnum; extern /* Subroutine */ int sormlq_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *); static logical lquery; static integer smlsiz; extern /* Subroutine */ int sormqr_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *); static real eps; #define a_ref(a_1,a_2) a[(a_2)*a_dim1 + a_1] #define b_ref(a_1,a_2) b[(a_2)*b_dim1 + a_1] /* -- LAPACK driver routine (version 3.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University October 31, 1999 Purpose ======= SGELSD computes the minimum-norm solution to a real linear least squares problem: minimize 2-norm(| b - A*x |) using the singular value decomposition (SVD) of A. A is an M-by-N matrix which may be rank-deficient. Several right hand side vectors b and solution vectors x can be handled in a single call; they are stored as the columns of the M-by-NRHS right hand side matrix B and the N-by-NRHS solution matrix X. The problem is solved in three steps: (1) Reduce the coefficient matrix A to bidiagonal form with Householder transformations, reducing the original problem into a "bidiagonal least squares problem" (BLS) (2) Solve the BLS using a divide and conquer approach. (3) Apply back all the Householder tranformations to solve the original least squares problem. The effective rank of A is determined by treating as zero those singular values which are less than RCOND times the largest singular value. The divide and conquer algorithm makes very mild assumptions about floating point arithmetic. It will work on machines with a guard digit in add/subtract, or on those binary machines without guard digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or Cray-2. It could conceivably fail on hexadecimal or decimal machines without guard digits, but we know of none. Arguments ========= M (input) INTEGER The number of rows of A. M >= 0. N (input) INTEGER The number of columns of A. N >= 0. NRHS (input) INTEGER The number of right hand sides, i.e., the number of columns of the matrices B and X. NRHS >= 0. A (input) REAL array, dimension (LDA,N) On entry, the M-by-N matrix A. On exit, A has been destroyed. LDA (input) INTEGER The leading dimension of the array A. LDA >= max(1,M). B (input/output) REAL array, dimension (LDB,NRHS) On entry, the M-by-NRHS right hand side matrix B. On exit, B is overwritten by the N-by-NRHS solution matrix X. If m >= n and RANK = n, the residual sum-of-squares for the solution in the i-th column is given by the sum of squares of elements n+1:m in that column. LDB (input) INTEGER The leading dimension of the array B. LDB >= max(1,max(M,N)). S (output) REAL array, dimension (min(M,N)) The singular values of A in decreasing order. The condition number of A in the 2-norm = S(1)/S(min(m,n)). RCOND (input) REAL RCOND is used to determine the effective rank of A. Singular values S(i) <= RCOND*S(1) are treated as zero. If RCOND < 0, machine precision is used instead. RANK (output) INTEGER The effective rank of A, i.e., the number of singular values which are greater than RCOND*S(1). WORK (workspace/output) REAL array, dimension (LWORK) On exit, if INFO = 0, WORK(1) returns the optimal LWORK. LWORK (input) INTEGER The dimension of the array WORK. LWORK must be at least 1. The exact minimum amount of workspace needed depends on M, N and NRHS. As long as LWORK is at least 12*N + 2*N*SMLSIZ + 8*N*NLVL + N*NRHS + (SMLSIZ+1)**2, if M is greater than or equal to N or 12*M + 2*M*SMLSIZ + 8*M*NLVL + M*NRHS + (SMLSIZ+1)**2, if M is less than N, the code will execute correctly. SMLSIZ is returned by ILAENV and is equal to the maximum size of the subproblems at the bottom of the computation tree (usually about 25), and NLVL = MAX( 0, INT( LOG_2( MIN( M,N )/(SMLSIZ+1) ) ) + 1 ) For good performance, LWORK should generally be larger. If LWORK = -1, then a workspace query is assumed; the routine only calculates the optimal size of the WORK array, returns this value as the first entry of the WORK array, and no error message related to LWORK is issued by XERBLA. IWORK (workspace) INTEGER array, dimension (LIWORK) LIWORK >= 3 * MINMN * NLVL + 11 * MINMN, where MINMN = MIN( M,N ). INFO (output) INTEGER = 0: successful exit < 0: if INFO = -i, the i-th argument had an illegal value. > 0: the algorithm for computing the SVD failed to converge; if INFO = i, i off-diagonal elements of an intermediate bidiagonal form did not converge to zero. 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 arguments. Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; b_dim1 = *ldb; b_offset = 1 + b_dim1 * 1; b -= b_offset; --s; --work; --iwork; /* Function Body */ *info = 0; minmn = min(*m,*n); maxmn = max(*m,*n); mnthr = ilaenv_(&c__6, "SGELSD", " ", m, n, nrhs, &c_n1, (ftnlen)6, ( ftnlen)1); lquery = *lwork == -1; if (*m < 0) { *info = -1; } else if (*n < 0) { *info = -2; } else if (*nrhs < 0) { *info = -3; } else if (*lda < max(1,*m)) { *info = -5; } else if (*ldb < max(1,maxmn)) { *info = -7; } smlsiz = ilaenv_(&c__9, "SGELSD", " ", &c__0, &c__0, &c__0, &c__0, ( ftnlen)6, (ftnlen)1); /* Compute workspace. (Note: Comments in the code beginning "Workspace:" describe the minimal amount of workspace needed at that point in the code, as well as the preferred amount for good performance. NB refers to the optimal block size for the immediately following subroutine, as returned by ILAENV.) */ minwrk = 1; minmn = max(1,minmn); /* Computing MAX */ i__1 = (integer) (log((real) minmn / (real) (smlsiz + 1)) / log(2.f)) + 1; nlvl = max(i__1,0); if (*info == 0) { maxwrk = 0; mm = *m; if (*m >= *n && *m >= mnthr) { /* Path 1a - overdetermined, with many more rows than columns. */ mm = *n; /* Computing MAX */ i__1 = maxwrk, i__2 = *n + *n * ilaenv_(&c__1, "SGEQRF", " ", m, n, &c_n1, &c_n1, (ftnlen)6, (ftnlen)1); maxwrk = max(i__1,i__2); /* Computing MAX */ i__1 = maxwrk, i__2 = *n + *nrhs * ilaenv_(&c__1, "SORMQR", "LT", m, nrhs, n, &c_n1, (ftnlen)6, (ftnlen)2); maxwrk = max(i__1,i__2); } if (*m >= *n) { /* Path 1 - overdetermined or exactly determined. Computing MAX */ i__1 = maxwrk, i__2 = *n * 3 + (mm + *n) * ilaenv_(&c__1, "SGEBRD" , " ", &mm, n, &c_n1, &c_n1, (ftnlen)6, (ftnlen)1); maxwrk = max(i__1,i__2); /* Computing MAX */ i__1 = maxwrk, i__2 = *n * 3 + *nrhs * ilaenv_(&c__1, "SORMBR", "QLT", &mm, nrhs, n, &c_n1, (ftnlen)6, (ftnlen)3); maxwrk = max(i__1,i__2); /* Computing MAX */ i__1 = maxwrk, i__2 = *n * 3 + (*n - 1) * ilaenv_(&c__1, "SORMBR", "PLN", n, nrhs, n, &c_n1, (ftnlen)6, (ftnlen)3); maxwrk = max(i__1,i__2); /* Computing 2nd power */ i__1 = smlsiz + 1; wlalsd = *n * 9 + (*n << 1) * smlsiz + (*n << 3) * nlvl + *n * * nrhs + i__1 * i__1; /* Computing MAX */ i__1 = maxwrk, i__2 = *n * 3 + wlalsd; maxwrk = max(i__1,i__2); /* Computing MAX */ i__1 = *n * 3 + mm, i__2 = *n * 3 + *nrhs, i__1 = max(i__1,i__2), i__2 = *n * 3 + wlalsd; minwrk = max(i__1,i__2); } if (*n > *m) { /* Computing 2nd power */ i__1 = smlsiz + 1; wlalsd = *m * 9 + (*m << 1) * smlsiz + (*m << 3) * nlvl + *m * * nrhs + i__1 * i__1; if (*n >= mnthr) { /* Path 2a - underdetermined, with many more columns than rows. */ maxwrk = *m + *m * ilaenv_(&c__1, "SGELQF", " ", m, n, &c_n1, &c_n1, (ftnlen)6, (ftnlen)1); /* Computing MAX */ i__1 = maxwrk, i__2 = *m * *m + (*m << 2) + (*m << 1) * ilaenv_(&c__1, "SGEBRD", " ", m, m, &c_n1, &c_n1, ( ftnlen)6, (ftnlen)1); maxwrk = max(i__1,i__2); /* Computing MAX */ i__1 = maxwrk, i__2 = *m * *m + (*m << 2) + *nrhs * ilaenv_(& c__1, "SORMBR", "QLT", m, nrhs, m, &c_n1, (ftnlen)6, ( ftnlen)3); maxwrk = max(i__1,i__2); /* Computing MAX */ i__1 = maxwrk, i__2 = *m * *m + (*m << 2) + (*m - 1) * ilaenv_(&c__1, "SORMBR", "PLN", m, nrhs, m, &c_n1, ( ftnlen)6, (ftnlen)3); maxwrk = max(i__1,i__2); if (*nrhs > 1) { /* Computing MAX */ i__1 = maxwrk, i__2 = *m * *m + *m + *m * *nrhs; maxwrk = max(i__1,i__2); } else { /* Computing MAX */ i__1 = maxwrk, i__2 = *m * *m + (*m << 1); maxwrk = max(i__1,i__2); } /* Computing MAX */ i__1 = maxwrk, i__2 = *m + *nrhs * ilaenv_(&c__1, "SORMLQ", "LT", n, nrhs, m, &c_n1, (ftnlen)6, (ftnlen)2); maxwrk = max(i__1,i__2); /* Computing MAX */ i__1 = maxwrk, i__2 = *m * *m + (*m << 2) + wlalsd; maxwrk = max(i__1,i__2); } else { /* Path 2 - remaining underdetermined cases. */ maxwrk = *m * 3 + (*n + *m) * ilaenv_(&c__1, "SGEBRD", " ", m, n, &c_n1, &c_n1, (ftnlen)6, (ftnlen)1); /* Computing MAX */ i__1 = maxwrk, i__2 = *m * 3 + *nrhs * ilaenv_(&c__1, "SORMBR" , "QLT", m, nrhs, n, &c_n1, (ftnlen)6, (ftnlen)3); maxwrk = max(i__1,i__2); /* Computing MAX */ i__1 = maxwrk, i__2 = *m * 3 + *m * ilaenv_(&c__1, "SORMBR", "PLN", n, nrhs, m, &c_n1, (ftnlen)6, (ftnlen)3); maxwrk = max(i__1,i__2); /* Computing MAX */ i__1 = maxwrk, i__2 = *m * 3 + wlalsd; maxwrk = max(i__1,i__2); } /* Computing MAX */ i__1 = *m * 3 + *nrhs, i__2 = *m * 3 + *m, i__1 = max(i__1,i__2), i__2 = *m * 3 + wlalsd; minwrk = max(i__1,i__2); } minwrk = min(minwrk,maxwrk); work[1] = (real) maxwrk; if (*lwork < minwrk && ! lquery) { *info = -12; } } if (*info != 0) { i__1 = -(*info); xerbla_("SGELSD", &i__1); return 0; } else if (lquery) { goto L10; } /* Quick return if possible. */ if (*m == 0 || *n == 0) { *rank = 0; return 0; } /* Get machine parameters. */ eps = slamch_("P"); sfmin = slamch_("S"); smlnum = sfmin / eps; bignum = 1.f / smlnum; slabad_(&smlnum, &bignum); /* Scale A if max entry outside range [SMLNUM,BIGNUM]. */ anrm = slange_("M", m, n, &a[a_offset], lda, &work[1]); iascl = 0; if (anrm > 0.f && anrm < smlnum) { /* Scale matrix norm up to SMLNUM. */ slascl_("G", &c__0, &c__0, &anrm, &smlnum, m, n, &a[a_offset], lda, info); iascl = 1; } else if (anrm > bignum) { /* Scale matrix norm down to BIGNUM. */ slascl_("G", &c__0, &c__0, &anrm, &bignum, m, n, &a[a_offset], lda, info); iascl = 2; } else if (anrm == 0.f) { /* Matrix all zero. Return zero solution. */ i__1 = max(*m,*n); slaset_("F", &i__1, nrhs, &c_b82, &c_b82, &b[b_offset], ldb); slaset_("F", &minmn, &c__1, &c_b82, &c_b82, &s[1], &c__1); *rank = 0; goto L10; } /* Scale B if max entry outside range [SMLNUM,BIGNUM]. */ bnrm = slange_("M", m, nrhs, &b[b_offset], ldb, &work[1]); ibscl = 0; if (bnrm > 0.f && bnrm < smlnum) { /* Scale matrix norm up to SMLNUM. */ slascl_("G", &c__0, &c__0, &bnrm, &smlnum, m, nrhs, &b[b_offset], ldb, info); ibscl = 1; } else if (bnrm > bignum) { /* Scale matrix norm down to BIGNUM. */ slascl_("G", &c__0, &c__0, &bnrm, &bignum, m, nrhs, &b[b_offset], ldb, info); ibscl = 2; } /* If M < N make sure certain entries of B are zero. */ if (*m < *n) { i__1 = *n - *m; slaset_("F", &i__1, nrhs, &c_b82, &c_b82, &b_ref(*m + 1, 1), ldb); } /* Overdetermined case. */ if (*m >= *n) { /* Path 1 - overdetermined or exactly determined. */ mm = *m; if (*m >= mnthr) { /* Path 1a - overdetermined, with many more rows than columns. */ mm = *n; itau = 1; nwork = itau + *n; /* Compute A=Q*R. (Workspace: need 2*N, prefer N+N*NB) */ i__1 = *lwork - nwork + 1; sgeqrf_(m, n, &a[a_offset], lda, &work[itau], &work[nwork], &i__1, info); /* Multiply B by transpose(Q). (Workspace: need N+NRHS, prefer N+NRHS*NB) */ i__1 = *lwork - nwork + 1; sormqr_("L", "T", m, nrhs, n, &a[a_offset], lda, &work[itau], &b[ b_offset], ldb, &work[nwork], &i__1, info); /* Zero out below R. */ if (*n > 1) { i__1 = *n - 1; i__2 = *n - 1; slaset_("L", &i__1, &i__2, &c_b82, &c_b82, &a_ref(2, 1), lda); } } ie = 1; itauq = ie + *n; itaup = itauq + *n; nwork = itaup + *n; /* Bidiagonalize R in A. (Workspace: need 3*N+MM, prefer 3*N+(MM+N)*NB) */ i__1 = *lwork - nwork + 1; sgebrd_(&mm, n, &a[a_offset], lda, &s[1], &work[ie], &work[itauq], & work[itaup], &work[nwork], &i__1, info); /* Multiply B by transpose of left bidiagonalizing vectors of R. (Workspace: need 3*N+NRHS, prefer 3*N+NRHS*NB) */ i__1 = *lwork - nwork + 1; sormbr_("Q", "L", "T", &mm, nrhs, n, &a[a_offset], lda, &work[itauq], &b[b_offset], ldb, &work[nwork], &i__1, info); /* Solve the bidiagonal least squares problem. */ slalsd_("U", &smlsiz, n, nrhs, &s[1], &work[ie], &b[b_offset], ldb, rcond, rank, &work[nwork], &iwork[1], info); if (*info != 0) { goto L10; } /* Multiply B by right bidiagonalizing vectors of R. */ i__1 = *lwork - nwork + 1; sormbr_("P", "L", "N", n, nrhs, n, &a[a_offset], lda, &work[itaup], & b[b_offset], ldb, &work[nwork], &i__1, info); } else /* if(complicated condition) */ { /* Computing MAX */ i__1 = *m, i__2 = (*m << 1) - 4, i__1 = max(i__1,i__2), i__1 = max( i__1,*nrhs), i__2 = *n - *m * 3; if (*n >= mnthr && *lwork >= (*m << 2) + *m * *m + max(i__1,i__2)) { /* Path 2a - underdetermined, with many more columns than rows and sufficient workspace for an efficient algorithm. */ ldwork = *m; /* Computing MAX Computing MAX */ i__3 = *m, i__4 = (*m << 1) - 4, i__3 = max(i__3,i__4), i__3 = max(i__3,*nrhs), i__4 = *n - *m * 3; i__1 = (*m << 2) + *m * *lda + max(i__3,i__4), i__2 = *m * *lda + *m + *m * *nrhs; if (*lwork >= max(i__1,i__2)) { ldwork = *lda; } itau = 1; nwork = *m + 1; /* Compute A=L*Q. (Workspace: need 2*M, prefer M+M*NB) */ i__1 = *lwork - nwork + 1; sgelqf_(m, n, &a[a_offset], lda, &work[itau], &work[nwork], &i__1, info); il = nwork; /* Copy L to WORK(IL), zeroing out above its diagonal. */ slacpy_("L", m, m, &a[a_offset], lda, &work[il], &ldwork); i__1 = *m - 1; i__2 = *m - 1; slaset_("U", &i__1, &i__2, &c_b82, &c_b82, &work[il + ldwork], & ldwork); ie = il + ldwork * *m; itauq = ie + *m; itaup = itauq + *m; nwork = itaup + *m; /* Bidiagonalize L in WORK(IL). (Workspace: need M*M+5*M, prefer M*M+4*M+2*M*NB) */ i__1 = *lwork - nwork + 1; sgebrd_(m, m, &work[il], &ldwork, &s[1], &work[ie], &work[itauq], &work[itaup], &work[nwork], &i__1, info); /* Multiply B by transpose of left bidiagonalizing vectors of L. (Workspace: need M*M+4*M+NRHS, prefer M*M+4*M+NRHS*NB) */ i__1 = *lwork - nwork + 1; sormbr_("Q", "L", "T", m, nrhs, m, &work[il], &ldwork, &work[ itauq], &b[b_offset], ldb, &work[nwork], &i__1, info); /* Solve the bidiagonal least squares problem. */ slalsd_("U", &smlsiz, m, nrhs, &s[1], &work[ie], &b[b_offset], ldb, rcond, rank, &work[nwork], &iwork[1], info); if (*info != 0) { goto L10; } /* Multiply B by right bidiagonalizing vectors of L. */ i__1 = *lwork - nwork + 1; sormbr_("P", "L", "N", m, nrhs, m, &work[il], &ldwork, &work[ itaup], &b[b_offset], ldb, &work[nwork], &i__1, info); /* Zero out below first M rows of B. */ i__1 = *n - *m; slaset_("F", &i__1, nrhs, &c_b82, &c_b82, &b_ref(*m + 1, 1), ldb); nwork = itau + *m; /* Multiply transpose(Q) by B. (Workspace: need M+NRHS, prefer M+NRHS*NB) */ i__1 = *lwork - nwork + 1; sormlq_("L", "T", n, nrhs, m, &a[a_offset], lda, &work[itau], &b[ b_offset], ldb, &work[nwork], &i__1, info); } else { /* Path 2 - remaining underdetermined cases. */ ie = 1; itauq = ie + *m; itaup = itauq + *m; nwork = itaup + *m; /* Bidiagonalize A. (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB) */ i__1 = *lwork - nwork + 1; sgebrd_(m, n, &a[a_offset], lda, &s[1], &work[ie], &work[itauq], & work[itaup], &work[nwork], &i__1, info); /* Multiply B by transpose of left bidiagonalizing vectors. (Workspace: need 3*M+NRHS, prefer 3*M+NRHS*NB) */ i__1 = *lwork - nwork + 1; sormbr_("Q", "L", "T", m, nrhs, n, &a[a_offset], lda, &work[itauq] , &b[b_offset], ldb, &work[nwork], &i__1, info); /* Solve the bidiagonal least squares problem. */ slalsd_("L", &smlsiz, m, nrhs, &s[1], &work[ie], &b[b_offset], ldb, rcond, rank, &work[nwork], &iwork[1], info); if (*info != 0) { goto L10; } /* Multiply B by right bidiagonalizing vectors of A. */ i__1 = *lwork - nwork + 1; sormbr_("P", "L", "N", n, nrhs, m, &a[a_offset], lda, &work[itaup] , &b[b_offset], ldb, &work[nwork], &i__1, info); } } /* Undo scaling. */ if (iascl == 1) { slascl_("G", &c__0, &c__0, &anrm, &smlnum, n, nrhs, &b[b_offset], ldb, info); slascl_("G", &c__0, &c__0, &smlnum, &anrm, &minmn, &c__1, &s[1], & minmn, info); } else if (iascl == 2) { slascl_("G", &c__0, &c__0, &anrm, &bignum, n, nrhs, &b[b_offset], ldb, info); slascl_("G", &c__0, &c__0, &bignum, &anrm, &minmn, &c__1, &s[1], & minmn, info); } if (ibscl == 1) { slascl_("G", &c__0, &c__0, &smlnum, &bnrm, n, nrhs, &b[b_offset], ldb, info); } else if (ibscl == 2) { slascl_("G", &c__0, &c__0, &bignum, &bnrm, n, nrhs, &b[b_offset], ldb, info); } L10: work[1] = (real) maxwrk; return 0; /* End of SGELSD */ } /* sgelsd_ */
/* Subroutine */ int sgegs_(char *jobvsl, char *jobvsr, integer *n, real *a, integer *lda, real *b, integer *ldb, real *alphar, real *alphai, real *beta, real *vsl, integer *ldvsl, real *vsr, integer *ldvsr, real * work, integer *lwork, integer *info) { /* -- LAPACK driver 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 ======= This routine is deprecated and has been replaced by routine SGGES. SGEGS computes for a pair of N-by-N real nonsymmetric matrices A, B: the generalized eigenvalues (alphar +/- alphai*i, beta), the real Schur form (A, B), and optionally left and/or right Schur vectors (VSL and VSR). (If only the generalized eigenvalues are needed, use the driver SGEGV instead.) A generalized eigenvalue for a pair of matrices (A,B) is, roughly speaking, a scalar w or a ratio alpha/beta = w, such that A - w*B is singular. It is usually represented as the pair (alpha,beta), as there is a reasonable interpretation for beta=0, and even for both being zero. A good beginning reference is the book, "Matrix Computations", by G. Golub & C. van Loan (Johns Hopkins U. Press) The (generalized) Schur form of a pair of matrices is the result of multiplying both matrices on the left by one orthogonal matrix and both on the right by another orthogonal matrix, these two orthogonal matrices being chosen so as to bring the pair of matrices into (real) Schur form. A pair of matrices A, B is in generalized real Schur form if B is upper triangular with non-negative diagonal and A is block upper triangular with 1-by-1 and 2-by-2 blocks. 1-by-1 blocks correspond to real generalized eigenvalues, while 2-by-2 blocks of A will be "standardized" by making the corresponding elements of B have the form: [ a 0 ] [ 0 b ] and the pair of corresponding 2-by-2 blocks in A and B will have a complex conjugate pair of generalized eigenvalues. The left and right Schur vectors are the columns of VSL and VSR, respectively, where VSL and VSR are the orthogonal matrices which reduce A and B to Schur form: Schur form of (A,B) = ( (VSL)**T A (VSR), (VSL)**T B (VSR) ) Arguments ========= JOBVSL (input) CHARACTER*1 = 'N': do not compute the left Schur vectors; = 'V': compute the left Schur vectors. JOBVSR (input) CHARACTER*1 = 'N': do not compute the right Schur vectors; = 'V': compute the right Schur vectors. N (input) INTEGER The order of the matrices A, B, VSL, and VSR. N >= 0. A (input/output) REAL array, dimension (LDA, N) On entry, the first of the pair of matrices whose generalized eigenvalues and (optionally) Schur vectors are to be computed. On exit, the generalized Schur form of A. Note: to avoid overflow, the Frobenius norm of the matrix A should be less than the overflow threshold. LDA (input) INTEGER The leading dimension of A. LDA >= max(1,N). B (input/output) REAL array, dimension (LDB, N) On entry, the second of the pair of matrices whose generalized eigenvalues and (optionally) Schur vectors are to be computed. On exit, the generalized Schur form of B. Note: to avoid overflow, the Frobenius norm of the matrix B should be less than the overflow threshold. LDB (input) INTEGER The leading dimension of B. LDB >= max(1,N). ALPHAR (output) REAL array, dimension (N) ALPHAI (output) REAL array, dimension (N) BETA (output) REAL array, dimension (N) On exit, (ALPHAR(j) + ALPHAI(j)*i)/BETA(j), j=1,...,N, will be the generalized eigenvalues. ALPHAR(j) + ALPHAI(j)*i, j=1,...,N and BETA(j),j=1,...,N are the diagonals of the complex Schur form (A,B) that would result if the 2-by-2 diagonal blocks of the real Schur form of (A,B) were further reduced to triangular form using 2-by-2 complex unitary transformations. If ALPHAI(j) is zero, then the j-th eigenvalue is real; if positive, then the j-th and (j+1)-st eigenvalues are a complex conjugate pair, with ALPHAI(j+1) negative. Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j) may easily over- or underflow, and BETA(j) may even be zero. Thus, the user should avoid naively computing the ratio alpha/beta. However, ALPHAR and ALPHAI will be always less than and usually comparable with norm(A) in magnitude, and BETA always less than and usually comparable with norm(B). VSL (output) REAL array, dimension (LDVSL,N) If JOBVSL = 'V', VSL will contain the left Schur vectors. (See "Purpose", above.) Not referenced if JOBVSL = 'N'. LDVSL (input) INTEGER The leading dimension of the matrix VSL. LDVSL >=1, and if JOBVSL = 'V', LDVSL >= N. VSR (output) REAL array, dimension (LDVSR,N) If JOBVSR = 'V', VSR will contain the right Schur vectors. (See "Purpose", above.) Not referenced if JOBVSR = 'N'. LDVSR (input) INTEGER The leading dimension of the matrix VSR. LDVSR >= 1, and if JOBVSR = 'V', LDVSR >= N. WORK (workspace/output) REAL array, dimension (LWORK) On exit, if INFO = 0, WORK(1) returns the optimal LWORK. LWORK (input) INTEGER The dimension of the array WORK. LWORK >= max(1,4*N). For good performance, LWORK must generally be larger. To compute the optimal value of LWORK, call ILAENV to get blocksizes (for SGEQRF, SORMQR, and SORGQR.) Then compute: NB -- MAX of the blocksizes for SGEQRF, SORMQR, and SORGQR The optimal LWORK is 2*N + N*(NB+1). If LWORK = -1, then a workspace query is assumed; the routine only calculates the optimal size of the WORK array, returns this value as the first entry of the WORK array, and no error message related to LWORK is issued by XERBLA. INFO (output) INTEGER = 0: successful exit < 0: if INFO = -i, the i-th argument had an illegal value. = 1,...,N: The QZ iteration failed. (A,B) are not in Schur form, but ALPHAR(j), ALPHAI(j), and BETA(j) should be correct for j=INFO+1,...,N. > N: errors that usually indicate LAPACK problems: =N+1: error return from SGGBAL =N+2: error return from SGEQRF =N+3: error return from SORMQR =N+4: error return from SORGQR =N+5: error return from SGGHRD =N+6: error return from SHGEQZ (other than failed iteration) =N+7: error return from SGGBAK (computing VSL) =N+8: error return from SGGBAK (computing VSR) =N+9: error return from SLASCL (various places) ===================================================================== Decode the input arguments Parameter adjustments */ /* Table of constant values */ static integer c__1 = 1; static integer c_n1 = -1; static real c_b36 = 0.f; static real c_b37 = 1.f; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, vsl_dim1, vsl_offset, vsr_dim1, vsr_offset, i__1, i__2; /* Local variables */ static real anrm, bnrm; static integer itau, lopt; extern logical lsame_(char *, char *); static integer ileft, iinfo, icols; static logical ilvsl; static integer iwork; static logical ilvsr; static integer irows, nb; extern /* Subroutine */ int sggbak_(char *, char *, integer *, integer *, integer *, real *, real *, integer *, real *, integer *, integer * ), sggbal_(char *, integer *, real *, integer *, real *, integer *, integer *, integer *, real *, real *, real *, integer *); static logical ilascl, ilbscl; extern doublereal slamch_(char *), slange_(char *, integer *, integer *, real *, integer *, real *); static real safmin; extern /* Subroutine */ int sgghrd_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, integer *, real *, integer * , real *, integer *, integer *), xerbla_(char *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *, ftnlen, ftnlen); static real bignum; extern /* Subroutine */ int slascl_(char *, integer *, integer *, real *, real *, integer *, integer *, real *, integer *, integer *); static integer ijobvl, iright; extern /* Subroutine */ int sgeqrf_(integer *, integer *, real *, integer *, real *, real *, integer *, integer *); static integer ijobvr; extern /* Subroutine */ int slacpy_(char *, integer *, integer *, real *, integer *, real *, integer *), slaset_(char *, integer *, integer *, real *, real *, real *, integer *); static real anrmto; static integer lwkmin, nb1, nb2, nb3; static real bnrmto; extern /* Subroutine */ int shgeqz_(char *, char *, char *, integer *, integer *, integer *, real *, integer *, real *, integer *, real * , real *, real *, real *, integer *, real *, integer *, real *, integer *, integer *); static real smlnum; extern /* Subroutine */ int sorgqr_(integer *, integer *, integer *, real *, integer *, real *, real *, integer *, integer *); static integer lwkopt; static logical lquery; extern /* Subroutine */ int sormqr_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *); static integer ihi, ilo; static real eps; #define a_ref(a_1,a_2) a[(a_2)*a_dim1 + a_1] #define b_ref(a_1,a_2) b[(a_2)*b_dim1 + a_1] #define vsl_ref(a_1,a_2) vsl[(a_2)*vsl_dim1 + a_1] a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; b_dim1 = *ldb; b_offset = 1 + b_dim1 * 1; b -= b_offset; --alphar; --alphai; --beta; vsl_dim1 = *ldvsl; vsl_offset = 1 + vsl_dim1 * 1; vsl -= vsl_offset; vsr_dim1 = *ldvsr; vsr_offset = 1 + vsr_dim1 * 1; vsr -= vsr_offset; --work; /* Function Body */ if (lsame_(jobvsl, "N")) { ijobvl = 1; ilvsl = FALSE_; } else if (lsame_(jobvsl, "V")) { ijobvl = 2; ilvsl = TRUE_; } else { ijobvl = -1; ilvsl = FALSE_; } if (lsame_(jobvsr, "N")) { ijobvr = 1; ilvsr = FALSE_; } else if (lsame_(jobvsr, "V")) { ijobvr = 2; ilvsr = TRUE_; } else { ijobvr = -1; ilvsr = FALSE_; } /* Test the input arguments Computing MAX */ i__1 = *n << 2; lwkmin = max(i__1,1); lwkopt = lwkmin; work[1] = (real) lwkopt; lquery = *lwork == -1; *info = 0; if (ijobvl <= 0) { *info = -1; } else if (ijobvr <= 0) { *info = -2; } else if (*n < 0) { *info = -3; } else if (*lda < max(1,*n)) { *info = -5; } else if (*ldb < max(1,*n)) { *info = -7; } else if (*ldvsl < 1 || ilvsl && *ldvsl < *n) { *info = -12; } else if (*ldvsr < 1 || ilvsr && *ldvsr < *n) { *info = -14; } else if (*lwork < lwkmin && ! lquery) { *info = -16; } if (*info == 0) { nb1 = ilaenv_(&c__1, "SGEQRF", " ", n, n, &c_n1, &c_n1, (ftnlen)6, ( ftnlen)1); nb2 = ilaenv_(&c__1, "SORMQR", " ", n, n, n, &c_n1, (ftnlen)6, ( ftnlen)1); nb3 = ilaenv_(&c__1, "SORGQR", " ", n, n, n, &c_n1, (ftnlen)6, ( ftnlen)1); /* Computing MAX */ i__1 = max(nb1,nb2); nb = max(i__1,nb3); lopt = (*n << 1) + *n * (nb + 1); work[1] = (real) lopt; } if (*info != 0) { i__1 = -(*info); xerbla_("SGEGS ", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*n == 0) { return 0; } /* Get machine constants */ eps = slamch_("E") * slamch_("B"); safmin = slamch_("S"); smlnum = *n * safmin / eps; bignum = 1.f / smlnum; /* Scale A if max element outside range [SMLNUM,BIGNUM] */ anrm = slange_("M", n, n, &a[a_offset], lda, &work[1]); ilascl = FALSE_; if (anrm > 0.f && anrm < smlnum) { anrmto = smlnum; ilascl = TRUE_; } else if (anrm > bignum) { anrmto = bignum; ilascl = TRUE_; } if (ilascl) { slascl_("G", &c_n1, &c_n1, &anrm, &anrmto, n, n, &a[a_offset], lda, & iinfo); if (iinfo != 0) { *info = *n + 9; return 0; } } /* Scale B if max element outside range [SMLNUM,BIGNUM] */ bnrm = slange_("M", n, n, &b[b_offset], ldb, &work[1]); ilbscl = FALSE_; if (bnrm > 0.f && bnrm < smlnum) { bnrmto = smlnum; ilbscl = TRUE_; } else if (bnrm > bignum) { bnrmto = bignum; ilbscl = TRUE_; } if (ilbscl) { slascl_("G", &c_n1, &c_n1, &bnrm, &bnrmto, n, n, &b[b_offset], ldb, & iinfo); if (iinfo != 0) { *info = *n + 9; return 0; } } /* Permute the matrix to make it more nearly triangular Workspace layout: (2*N words -- "work..." not actually used) left_permutation, right_permutation, work... */ ileft = 1; iright = *n + 1; iwork = iright + *n; sggbal_("P", n, &a[a_offset], lda, &b[b_offset], ldb, &ilo, &ihi, &work[ ileft], &work[iright], &work[iwork], &iinfo); if (iinfo != 0) { *info = *n + 1; goto L10; } /* Reduce B to triangular form, and initialize VSL and/or VSR Workspace layout: ("work..." must have at least N words) left_permutation, right_permutation, tau, work... */ irows = ihi + 1 - ilo; icols = *n + 1 - ilo; itau = iwork; iwork = itau + irows; i__1 = *lwork + 1 - iwork; sgeqrf_(&irows, &icols, &b_ref(ilo, ilo), ldb, &work[itau], &work[iwork], &i__1, &iinfo); if (iinfo >= 0) { /* Computing MAX */ i__1 = lwkopt, i__2 = (integer) work[iwork] + iwork - 1; lwkopt = max(i__1,i__2); } if (iinfo != 0) { *info = *n + 2; goto L10; } i__1 = *lwork + 1 - iwork; sormqr_("L", "T", &irows, &icols, &irows, &b_ref(ilo, ilo), ldb, &work[ itau], &a_ref(ilo, ilo), lda, &work[iwork], &i__1, &iinfo); if (iinfo >= 0) { /* Computing MAX */ i__1 = lwkopt, i__2 = (integer) work[iwork] + iwork - 1; lwkopt = max(i__1,i__2); } if (iinfo != 0) { *info = *n + 3; goto L10; } if (ilvsl) { slaset_("Full", n, n, &c_b36, &c_b37, &vsl[vsl_offset], ldvsl); i__1 = irows - 1; i__2 = irows - 1; slacpy_("L", &i__1, &i__2, &b_ref(ilo + 1, ilo), ldb, &vsl_ref(ilo + 1, ilo), ldvsl); i__1 = *lwork + 1 - iwork; sorgqr_(&irows, &irows, &irows, &vsl_ref(ilo, ilo), ldvsl, &work[itau] , &work[iwork], &i__1, &iinfo); if (iinfo >= 0) { /* Computing MAX */ i__1 = lwkopt, i__2 = (integer) work[iwork] + iwork - 1; lwkopt = max(i__1,i__2); } if (iinfo != 0) { *info = *n + 4; goto L10; } } if (ilvsr) { slaset_("Full", n, n, &c_b36, &c_b37, &vsr[vsr_offset], ldvsr); } /* Reduce to generalized Hessenberg form */ sgghrd_(jobvsl, jobvsr, n, &ilo, &ihi, &a[a_offset], lda, &b[b_offset], ldb, &vsl[vsl_offset], ldvsl, &vsr[vsr_offset], ldvsr, &iinfo); if (iinfo != 0) { *info = *n + 5; goto L10; } /* Perform QZ algorithm, computing Schur vectors if desired Workspace layout: ("work..." must have at least 1 word) left_permutation, right_permutation, work... */ iwork = itau; i__1 = *lwork + 1 - iwork; shgeqz_("S", jobvsl, jobvsr, n, &ilo, &ihi, &a[a_offset], lda, &b[ b_offset], ldb, &alphar[1], &alphai[1], &beta[1], &vsl[vsl_offset] , ldvsl, &vsr[vsr_offset], ldvsr, &work[iwork], &i__1, &iinfo); if (iinfo >= 0) { /* Computing MAX */ i__1 = lwkopt, i__2 = (integer) work[iwork] + iwork - 1; lwkopt = max(i__1,i__2); } if (iinfo != 0) { if (iinfo > 0 && iinfo <= *n) { *info = iinfo; } else if (iinfo > *n && iinfo <= *n << 1) { *info = iinfo - *n; } else { *info = *n + 6; } goto L10; } /* Apply permutation to VSL and VSR */ if (ilvsl) { sggbak_("P", "L", n, &ilo, &ihi, &work[ileft], &work[iright], n, &vsl[ vsl_offset], ldvsl, &iinfo); if (iinfo != 0) { *info = *n + 7; goto L10; } } if (ilvsr) { sggbak_("P", "R", n, &ilo, &ihi, &work[ileft], &work[iright], n, &vsr[ vsr_offset], ldvsr, &iinfo); if (iinfo != 0) { *info = *n + 8; goto L10; } } /* Undo scaling */ if (ilascl) { slascl_("H", &c_n1, &c_n1, &anrmto, &anrm, n, n, &a[a_offset], lda, & iinfo); if (iinfo != 0) { *info = *n + 9; return 0; } slascl_("G", &c_n1, &c_n1, &anrmto, &anrm, n, &c__1, &alphar[1], n, & iinfo); if (iinfo != 0) { *info = *n + 9; return 0; } slascl_("G", &c_n1, &c_n1, &anrmto, &anrm, n, &c__1, &alphai[1], n, & iinfo); if (iinfo != 0) { *info = *n + 9; return 0; } } if (ilbscl) { slascl_("U", &c_n1, &c_n1, &bnrmto, &bnrm, n, n, &b[b_offset], ldb, & iinfo); if (iinfo != 0) { *info = *n + 9; return 0; } slascl_("G", &c_n1, &c_n1, &bnrmto, &bnrm, n, &c__1, &beta[1], n, & iinfo); if (iinfo != 0) { *info = *n + 9; return 0; } } L10: work[1] = (real) lwkopt; return 0; /* End of SGEGS */ } /* sgegs_ */
/* Subroutine */ int sggglm_(integer *n, integer *m, integer *p, real *a, integer *lda, real *b, integer *ldb, real *d__, real *x, real *y, real *work, integer *lwork, integer *info) { /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, i__1, i__2, i__3, i__4; /* Local variables */ integer i__, nb, np, nb1, nb2, nb3, nb4, lopt; extern /* Subroutine */ int sgemv_(char *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *), scopy_(integer *, real *, integer *, real *, integer *), xerbla_(char *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *); extern /* Subroutine */ int sggqrf_(integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, real *, integer * , integer *); integer lwkmin, lwkopt; logical lquery; extern /* Subroutine */ int sormqr_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *), sormrq_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real * , integer *, real *, integer *, integer *), strtrs_(char *, char *, char *, integer *, integer *, real *, integer *, real *, integer *, integer *); /* -- LAPACK driver routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SGGGLM solves a general Gauss-Markov linear model (GLM) problem: */ /* minimize || y ||_2 subject to d = A*x + B*y */ /* x */ /* where A is an N-by-M matrix, B is an N-by-P matrix, and d is a */ /* given N-vector. It is assumed that M <= N <= M+P, and */ /* rank(A) = M and rank( A B ) = N. */ /* Under these assumptions, the constrained equation is always */ /* consistent, and there is a unique solution x and a minimal 2-norm */ /* solution y, which is obtained using a generalized QR factorization */ /* of the matrices (A, B) given by */ /* A = Q*(R), B = Q*T*Z. */ /* (0) */ /* In particular, if matrix B is square nonsingular, then the problem */ /* GLM is equivalent to the following weighted linear least squares */ /* problem */ /* minimize || inv(B)*(d-A*x) ||_2 */ /* x */ /* where inv(B) denotes the inverse of B. */ /* Arguments */ /* ========= */ /* N (input) INTEGER */ /* The number of rows of the matrices A and B. N >= 0. */ /* M (input) INTEGER */ /* The number of columns of the matrix A. 0 <= M <= N. */ /* P (input) INTEGER */ /* The number of columns of the matrix B. P >= N-M. */ /* A (input/output) REAL array, dimension (LDA,M) */ /* On entry, the N-by-M matrix A. */ /* On exit, the upper triangular part of the array A contains */ /* the M-by-M upper triangular matrix R. */ /* LDA (input) INTEGER */ /* The leading dimension of the array A. LDA >= max(1,N). */ /* B (input/output) REAL array, dimension (LDB,P) */ /* On entry, the N-by-P matrix B. */ /* On exit, if N <= P, the upper triangle of the subarray */ /* B(1:N,P-N+1:P) contains the N-by-N upper triangular matrix T; */ /* if N > P, the elements on and above the (N-P)th subdiagonal */ /* contain the N-by-P upper trapezoidal matrix T. */ /* LDB (input) INTEGER */ /* The leading dimension of the array B. LDB >= max(1,N). */ /* D (input/output) REAL array, dimension (N) */ /* On entry, D is the left hand side of the GLM equation. */ /* On exit, D is destroyed. */ /* X (output) REAL array, dimension (M) */ /* Y (output) REAL array, dimension (P) */ /* On exit, X and Y are the solutions of the GLM problem. */ /* WORK (workspace/output) REAL array, dimension (MAX(1,LWORK)) */ /* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */ /* LWORK (input) INTEGER */ /* The dimension of the array WORK. LWORK >= max(1,N+M+P). */ /* For optimum performance, LWORK >= M+min(N,P)+max(N,P)*NB, */ /* where NB is an upper bound for the optimal blocksizes for */ /* SGEQRF, SGERQF, SORMQR and SORMRQ. */ /* If LWORK = -1, then a workspace query is assumed; the routine */ /* only calculates the optimal size of the WORK array, returns */ /* this value as the first entry of the WORK array, and no error */ /* message related to LWORK is issued by XERBLA. */ /* INFO (output) INTEGER */ /* = 0: successful exit. */ /* < 0: if INFO = -i, the i-th argument had an illegal value. */ /* = 1: the upper triangular factor R associated with A in the */ /* generalized QR factorization of the pair (A, B) is */ /* singular, so that rank(A) < M; the least squares */ /* solution could not be computed. */ /* = 2: the bottom (N-M) by (N-M) part of the upper trapezoidal */ /* factor T associated with B in the generalized QR */ /* factorization of the pair (A, B) is singular, so that */ /* rank( A B ) < N; the least squares solution could not */ /* be computed. */ /* =================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; b_dim1 = *ldb; b_offset = 1 + b_dim1; b -= b_offset; --d__; --x; --y; --work; /* Function Body */ *info = 0; np = min(*n,*p); lquery = *lwork == -1; if (*n < 0) { *info = -1; } else if (*m < 0 || *m > *n) { *info = -2; } else if (*p < 0 || *p < *n - *m) { *info = -3; } else if (*lda < max(1,*n)) { *info = -5; } else if (*ldb < max(1,*n)) { *info = -7; } /* Calculate workspace */ if (*info == 0) { if (*n == 0) { lwkmin = 1; lwkopt = 1; } else { nb1 = ilaenv_(&c__1, "SGEQRF", " ", n, m, &c_n1, &c_n1); nb2 = ilaenv_(&c__1, "SGERQF", " ", n, m, &c_n1, &c_n1); nb3 = ilaenv_(&c__1, "SORMQR", " ", n, m, p, &c_n1); nb4 = ilaenv_(&c__1, "SORMRQ", " ", n, m, p, &c_n1); /* Computing MAX */ i__1 = max(nb1,nb2), i__1 = max(i__1,nb3); nb = max(i__1,nb4); lwkmin = *m + *n + *p; lwkopt = *m + np + max(*n,*p) * nb; } work[1] = (real) lwkopt; if (*lwork < lwkmin && ! lquery) { *info = -12; } } if (*info != 0) { i__1 = -(*info); xerbla_("SGGGLM", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*n == 0) { return 0; } /* Compute the GQR factorization of matrices A and B: */ /* Q'*A = ( R11 ) M, Q'*B*Z' = ( T11 T12 ) M */ /* ( 0 ) N-M ( 0 T22 ) N-M */ /* M M+P-N N-M */ /* where R11 and T22 are upper triangular, and Q and Z are */ /* orthogonal. */ i__1 = *lwork - *m - np; sggqrf_(n, m, p, &a[a_offset], lda, &work[1], &b[b_offset], ldb, &work[*m + 1], &work[*m + np + 1], &i__1, info); lopt = work[*m + np + 1]; /* Update left-hand-side vector d = Q'*d = ( d1 ) M */ /* ( d2 ) N-M */ i__1 = max(1,*n); i__2 = *lwork - *m - np; sormqr_("Left", "Transpose", n, &c__1, m, &a[a_offset], lda, &work[1], & d__[1], &i__1, &work[*m + np + 1], &i__2, info); /* Computing MAX */ i__1 = lopt, i__2 = (integer) work[*m + np + 1]; lopt = max(i__1,i__2); /* Solve T22*y2 = d2 for y2 */ if (*n > *m) { i__1 = *n - *m; i__2 = *n - *m; strtrs_("Upper", "No transpose", "Non unit", &i__1, &c__1, &b[*m + 1 + (*m + *p - *n + 1) * b_dim1], ldb, &d__[*m + 1], &i__2, info); if (*info > 0) { *info = 1; return 0; } i__1 = *n - *m; scopy_(&i__1, &d__[*m + 1], &c__1, &y[*m + *p - *n + 1], &c__1); } /* Set y1 = 0 */ i__1 = *m + *p - *n; for (i__ = 1; i__ <= i__1; ++i__) { y[i__] = 0.f; /* L10: */ } /* Update d1 = d1 - T12*y2 */ i__1 = *n - *m; sgemv_("No transpose", m, &i__1, &c_b32, &b[(*m + *p - *n + 1) * b_dim1 + 1], ldb, &y[*m + *p - *n + 1], &c__1, &c_b34, &d__[1], &c__1); /* Solve triangular system: R11*x = d1 */ if (*m > 0) { strtrs_("Upper", "No Transpose", "Non unit", m, &c__1, &a[a_offset], lda, &d__[1], m, info); if (*info > 0) { *info = 2; return 0; } /* Copy D to X */ scopy_(m, &d__[1], &c__1, &x[1], &c__1); } /* Backward transformation y = Z'*y */ /* Computing MAX */ i__1 = 1, i__2 = *n - *p + 1; i__3 = max(1,*p); i__4 = *lwork - *m - np; sormrq_("Left", "Transpose", p, &c__1, &np, &b[max(i__1, i__2)+ b_dim1], ldb, &work[*m + 1], &y[1], &i__3, &work[*m + np + 1], &i__4, info); /* Computing MAX */ i__1 = lopt, i__2 = (integer) work[*m + np + 1]; work[1] = (real) (*m + np + max(i__1,i__2)); return 0; /* End of SGGGLM */ } /* sggglm_ */
/* Subroutine */ int serrqr_(char *path, integer *nunit) { /* Local variables */ real a[4] /* was [2][2] */, b[2]; integer i__, j; real w[2], x[2], af[4] /* was [2][2] */; integer info; /* Fortran I/O blocks */ static cilist io___1 = { 0, 0, 0, 0, 0 }; /* -- LAPACK test routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SERRQR tests the error exits for the REAL routines */ /* that use the QR decomposition of a general matrix. */ /* Arguments */ /* ========= */ /* PATH (input) CHARACTER*3 */ /* The LAPACK path name for the routines to be tested. */ /* NUNIT (input) INTEGER */ /* The unit number for output. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. Local Arrays .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Scalars in Common .. */ /* .. */ /* .. Common blocks .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ infoc_1.nout = *nunit; io___1.ciunit = infoc_1.nout; s_wsle(&io___1); e_wsle(); /* Set the variables to innocuous values. */ for (j = 1; j <= 2; ++j) { for (i__ = 1; i__ <= 2; ++i__) { a[i__ + (j << 1) - 3] = 1.f / (real) (i__ + j); af[i__ + (j << 1) - 3] = 1.f / (real) (i__ + j); /* L10: */ } b[j - 1] = 0.f; w[j - 1] = 0.f; x[j - 1] = 0.f; /* L20: */ } infoc_1.ok = TRUE_; /* Error exits for QR factorization */ /* SGEQRF */ s_copy(srnamc_1.srnamt, "SGEQRF", (ftnlen)32, (ftnlen)6); infoc_1.infot = 1; sgeqrf_(&c_n1, &c__0, a, &c__1, b, w, &c__1, &info); chkxer_("SGEQRF", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; sgeqrf_(&c__0, &c_n1, a, &c__1, b, w, &c__1, &info); chkxer_("SGEQRF", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 4; sgeqrf_(&c__2, &c__1, a, &c__1, b, w, &c__1, &info); chkxer_("SGEQRF", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 7; sgeqrf_(&c__1, &c__2, a, &c__1, b, w, &c__1, &info); chkxer_("SGEQRF", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); /* SGEQR2 */ s_copy(srnamc_1.srnamt, "SGEQR2", (ftnlen)32, (ftnlen)6); infoc_1.infot = 1; sgeqr2_(&c_n1, &c__0, a, &c__1, b, w, &info); chkxer_("SGEQR2", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; sgeqr2_(&c__0, &c_n1, a, &c__1, b, w, &info); chkxer_("SGEQR2", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 4; sgeqr2_(&c__2, &c__1, a, &c__1, b, w, &info); chkxer_("SGEQR2", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); /* SGEQRS */ s_copy(srnamc_1.srnamt, "SGEQRS", (ftnlen)32, (ftnlen)6); infoc_1.infot = 1; sgeqrs_(&c_n1, &c__0, &c__0, a, &c__1, x, b, &c__1, w, &c__1, &info); chkxer_("SGEQRS", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; sgeqrs_(&c__0, &c_n1, &c__0, a, &c__1, x, b, &c__1, w, &c__1, &info); chkxer_("SGEQRS", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; sgeqrs_(&c__1, &c__2, &c__0, a, &c__2, x, b, &c__2, w, &c__1, &info); chkxer_("SGEQRS", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 3; sgeqrs_(&c__0, &c__0, &c_n1, a, &c__1, x, b, &c__1, w, &c__1, &info); chkxer_("SGEQRS", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; sgeqrs_(&c__2, &c__1, &c__0, a, &c__1, x, b, &c__2, w, &c__1, &info); chkxer_("SGEQRS", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 8; sgeqrs_(&c__2, &c__1, &c__0, a, &c__2, x, b, &c__1, w, &c__1, &info); chkxer_("SGEQRS", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 10; sgeqrs_(&c__1, &c__1, &c__2, a, &c__1, x, b, &c__1, w, &c__1, &info); chkxer_("SGEQRS", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); /* SORGQR */ s_copy(srnamc_1.srnamt, "SORGQR", (ftnlen)32, (ftnlen)6); infoc_1.infot = 1; sorgqr_(&c_n1, &c__0, &c__0, a, &c__1, x, w, &c__1, &info); chkxer_("SORGQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; sorgqr_(&c__0, &c_n1, &c__0, a, &c__1, x, w, &c__1, &info); chkxer_("SORGQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; sorgqr_(&c__1, &c__2, &c__0, a, &c__1, x, w, &c__2, &info); chkxer_("SORGQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 3; sorgqr_(&c__0, &c__0, &c_n1, a, &c__1, x, w, &c__1, &info); chkxer_("SORGQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 3; sorgqr_(&c__1, &c__1, &c__2, a, &c__1, x, w, &c__1, &info); chkxer_("SORGQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; sorgqr_(&c__2, &c__2, &c__0, a, &c__1, x, w, &c__2, &info); chkxer_("SORGQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 8; sorgqr_(&c__2, &c__2, &c__0, a, &c__2, x, w, &c__1, &info); chkxer_("SORGQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); /* SORG2R */ s_copy(srnamc_1.srnamt, "SORG2R", (ftnlen)32, (ftnlen)6); infoc_1.infot = 1; sorg2r_(&c_n1, &c__0, &c__0, a, &c__1, x, w, &info); chkxer_("SORG2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; sorg2r_(&c__0, &c_n1, &c__0, a, &c__1, x, w, &info); chkxer_("SORG2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; sorg2r_(&c__1, &c__2, &c__0, a, &c__1, x, w, &info); chkxer_("SORG2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 3; sorg2r_(&c__0, &c__0, &c_n1, a, &c__1, x, w, &info); chkxer_("SORG2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 3; sorg2r_(&c__2, &c__1, &c__2, a, &c__2, x, w, &info); chkxer_("SORG2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; sorg2r_(&c__2, &c__1, &c__0, a, &c__1, x, w, &info); chkxer_("SORG2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); /* SORMQR */ s_copy(srnamc_1.srnamt, "SORMQR", (ftnlen)32, (ftnlen)6); infoc_1.infot = 1; sormqr_("/", "N", &c__0, &c__0, &c__0, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; sormqr_("L", "/", &c__0, &c__0, &c__0, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 3; sormqr_("L", "N", &c_n1, &c__0, &c__0, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 4; sormqr_("L", "N", &c__0, &c_n1, &c__0, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; sormqr_("L", "N", &c__0, &c__0, &c_n1, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; sormqr_("L", "N", &c__0, &c__1, &c__1, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; sormqr_("R", "N", &c__1, &c__0, &c__1, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 7; sormqr_("L", "N", &c__2, &c__1, &c__0, a, &c__1, x, af, &c__2, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 7; sormqr_("R", "N", &c__1, &c__2, &c__0, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 10; sormqr_("L", "N", &c__2, &c__1, &c__0, a, &c__2, x, af, &c__1, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 12; sormqr_("L", "N", &c__1, &c__2, &c__0, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 12; sormqr_("R", "N", &c__2, &c__1, &c__0, a, &c__1, x, af, &c__2, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); /* SORM2R */ s_copy(srnamc_1.srnamt, "SORM2R", (ftnlen)32, (ftnlen)6); infoc_1.infot = 1; sorm2r_("/", "N", &c__0, &c__0, &c__0, a, &c__1, x, af, &c__1, w, &info); chkxer_("SORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; sorm2r_("L", "/", &c__0, &c__0, &c__0, a, &c__1, x, af, &c__1, w, &info); chkxer_("SORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 3; sorm2r_("L", "N", &c_n1, &c__0, &c__0, a, &c__1, x, af, &c__1, w, &info); chkxer_("SORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 4; sorm2r_("L", "N", &c__0, &c_n1, &c__0, a, &c__1, x, af, &c__1, w, &info); chkxer_("SORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; sorm2r_("L", "N", &c__0, &c__0, &c_n1, a, &c__1, x, af, &c__1, w, &info); chkxer_("SORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; sorm2r_("L", "N", &c__0, &c__1, &c__1, a, &c__1, x, af, &c__1, w, &info); chkxer_("SORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; sorm2r_("R", "N", &c__1, &c__0, &c__1, a, &c__1, x, af, &c__1, w, &info); chkxer_("SORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 7; sorm2r_("L", "N", &c__2, &c__1, &c__0, a, &c__1, x, af, &c__2, w, &info); chkxer_("SORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 7; sorm2r_("R", "N", &c__1, &c__2, &c__0, a, &c__1, x, af, &c__1, w, &info); chkxer_("SORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 10; sorm2r_("L", "N", &c__2, &c__1, &c__0, a, &c__2, x, af, &c__1, w, &info); chkxer_("SORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); /* Print a summary line. */ alaesm_(path, &infoc_1.ok, &infoc_1.nout); return 0; /* End of SERRQR */ } /* serrqr_ */
/* Subroutine */ int sggesx_(char *jobvsl, char *jobvsr, char *sort, L_fp selctg, char *sense, integer *n, real *a, integer *lda, real *b, integer *ldb, integer *sdim, real *alphar, real *alphai, real *beta, real *vsl, integer *ldvsl, real *vsr, integer *ldvsr, real *rconde, real *rcondv, real *work, integer *lwork, integer *iwork, integer * liwork, logical *bwork, integer *info) { /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, vsl_dim1, vsl_offset, vsr_dim1, vsr_offset, i__1, i__2; real r__1; /* Builtin functions */ double sqrt(doublereal); /* Local variables */ integer i__, ip; real pl, pr, dif[2]; integer ihi, ilo; real eps; integer ijob; real anrm, bnrm; integer ierr, itau, iwrk, lwrk; extern logical lsame_(char *, char *); integer ileft, icols; logical cursl, ilvsl, ilvsr; integer irows; logical lst2sl; extern /* Subroutine */ int slabad_(real *, real *), sggbak_(char *, char *, integer *, integer *, integer *, real *, real *, integer *, real *, integer *, integer *), sggbal_(char *, integer *, real *, integer *, real *, integer *, integer *, integer *, real *, real *, real *, integer *); logical ilascl, ilbscl; extern doublereal slamch_(char *), slange_(char *, integer *, integer *, real *, integer *, real *); real safmin; extern /* Subroutine */ int sgghrd_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, integer *, real *, integer * , real *, integer *, integer *); real safmax; extern /* Subroutine */ int xerbla_(char *, integer *); real bignum; extern /* Subroutine */ int slascl_(char *, integer *, integer *, real *, real *, integer *, integer *, real *, integer *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *); integer ijobvl, iright; extern /* Subroutine */ int sgeqrf_(integer *, integer *, real *, integer *, real *, real *, integer *, integer *); integer ijobvr; extern /* Subroutine */ int slacpy_(char *, integer *, integer *, real *, integer *, real *, integer *); logical wantsb, wantse, lastsl; integer liwmin; real anrmto, bnrmto; integer minwrk, maxwrk; logical wantsn; real smlnum; extern /* Subroutine */ int shgeqz_(char *, char *, char *, integer *, integer *, integer *, real *, integer *, real *, integer *, real * , real *, real *, real *, integer *, real *, integer *, real *, integer *, integer *), slaset_(char *, integer *, integer *, real *, real *, real *, integer *), sorgqr_(integer *, integer *, integer *, real *, integer *, real * , real *, integer *, integer *), stgsen_(integer *, logical *, logical *, logical *, integer *, real *, integer *, real *, integer *, real *, real *, real *, real *, integer *, real *, integer *, integer *, real *, real *, real *, real *, integer *, integer *, integer *, integer *); logical wantst, lquery, wantsv; extern /* Subroutine */ int sormqr_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *); /* -- LAPACK driver routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* .. Function Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SGGESX computes for a pair of N-by-N real nonsymmetric matrices */ /* (A,B), the generalized eigenvalues, the real Schur form (S,T), and, */ /* optionally, the left and/or right matrices of Schur vectors (VSL and */ /* VSR). This gives the generalized Schur factorization */ /* (A,B) = ( (VSL) S (VSR)**T, (VSL) T (VSR)**T ) */ /* Optionally, it also orders the eigenvalues so that a selected cluster */ /* of eigenvalues appears in the leading diagonal blocks of the upper */ /* quasi-triangular matrix S and the upper triangular matrix T; computes */ /* a reciprocal condition number for the average of the selected */ /* eigenvalues (RCONDE); and computes a reciprocal condition number for */ /* the right and left deflating subspaces corresponding to the selected */ /* eigenvalues (RCONDV). The leading columns of VSL and VSR then form */ /* an orthonormal basis for the corresponding left and right eigenspaces */ /* (deflating subspaces). */ /* A generalized eigenvalue for a pair of matrices (A,B) is a scalar w */ /* or a ratio alpha/beta = w, such that A - w*B is singular. It is */ /* usually represented as the pair (alpha,beta), as there is a */ /* reasonable interpretation for beta=0 or for both being zero. */ /* A pair of matrices (S,T) is in generalized real Schur form if T is */ /* upper triangular with non-negative diagonal and S is block upper */ /* triangular with 1-by-1 and 2-by-2 blocks. 1-by-1 blocks correspond */ /* to real generalized eigenvalues, while 2-by-2 blocks of S will be */ /* "standardized" by making the corresponding elements of T have the */ /* form: */ /* [ a 0 ] */ /* [ 0 b ] */ /* and the pair of corresponding 2-by-2 blocks in S and T will have a */ /* complex conjugate pair of generalized eigenvalues. */ /* Arguments */ /* ========= */ /* JOBVSL (input) CHARACTER*1 */ /* = 'N': do not compute the left Schur vectors; */ /* = 'V': compute the left Schur vectors. */ /* JOBVSR (input) CHARACTER*1 */ /* = 'N': do not compute the right Schur vectors; */ /* = 'V': compute the right Schur vectors. */ /* SORT (input) CHARACTER*1 */ /* Specifies whether or not to order the eigenvalues on the */ /* diagonal of the generalized Schur form. */ /* = 'N': Eigenvalues are not ordered; */ /* = 'S': Eigenvalues are ordered (see SELCTG). */ /* SELCTG (external procedure) LOGICAL FUNCTION of three REAL arguments */ /* SELCTG must be declared EXTERNAL in the calling subroutine. */ /* If SORT = 'N', SELCTG is not referenced. */ /* If SORT = 'S', SELCTG is used to select eigenvalues to sort */ /* to the top left of the Schur form. */ /* An eigenvalue (ALPHAR(j)+ALPHAI(j))/BETA(j) is selected if */ /* SELCTG(ALPHAR(j),ALPHAI(j),BETA(j)) is true; i.e. if either */ /* one of a complex conjugate pair of eigenvalues is selected, */ /* then both complex eigenvalues are selected. */ /* Note that a selected complex eigenvalue may no longer satisfy */ /* SELCTG(ALPHAR(j),ALPHAI(j),BETA(j)) = .TRUE. after ordering, */ /* since ordering may change the value of complex eigenvalues */ /* (especially if the eigenvalue is ill-conditioned), in this */ /* case INFO is set to N+3. */ /* SENSE (input) CHARACTER*1 */ /* Determines which reciprocal condition numbers are computed. */ /* = 'N' : None are computed; */ /* = 'E' : Computed for average of selected eigenvalues only; */ /* = 'V' : Computed for selected deflating subspaces only; */ /* = 'B' : Computed for both. */ /* If SENSE = 'E', 'V', or 'B', SORT must equal 'S'. */ /* N (input) INTEGER */ /* The order of the matrices A, B, VSL, and VSR. N >= 0. */ /* A (input/output) REAL array, dimension (LDA, N) */ /* On entry, the first of the pair of matrices. */ /* On exit, A has been overwritten by its generalized Schur */ /* form S. */ /* LDA (input) INTEGER */ /* The leading dimension of A. LDA >= max(1,N). */ /* B (input/output) REAL array, dimension (LDB, N) */ /* On entry, the second of the pair of matrices. */ /* On exit, B has been overwritten by its generalized Schur */ /* form T. */ /* LDB (input) INTEGER */ /* The leading dimension of B. LDB >= max(1,N). */ /* SDIM (output) INTEGER */ /* If SORT = 'N', SDIM = 0. */ /* If SORT = 'S', SDIM = number of eigenvalues (after sorting) */ /* for which SELCTG is true. (Complex conjugate pairs for which */ /* SELCTG is true for either eigenvalue count as 2.) */ /* ALPHAR (output) REAL array, dimension (N) */ /* ALPHAI (output) REAL array, dimension (N) */ /* BETA (output) REAL array, dimension (N) */ /* On exit, (ALPHAR(j) + ALPHAI(j)*i)/BETA(j), j=1,...,N, will */ /* be the generalized eigenvalues. ALPHAR(j) + ALPHAI(j)*i */ /* and BETA(j),j=1,...,N are the diagonals of the complex Schur */ /* form (S,T) that would result if the 2-by-2 diagonal blocks of */ /* the real Schur form of (A,B) were further reduced to */ /* triangular form using 2-by-2 complex unitary transformations. */ /* If ALPHAI(j) is zero, then the j-th eigenvalue is real; if */ /* positive, then the j-th and (j+1)-st eigenvalues are a */ /* complex conjugate pair, with ALPHAI(j+1) negative. */ /* Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j) */ /* may easily over- or underflow, and BETA(j) may even be zero. */ /* Thus, the user should avoid naively computing the ratio. */ /* However, ALPHAR and ALPHAI will be always less than and */ /* usually comparable with norm(A) in magnitude, and BETA always */ /* less than and usually comparable with norm(B). */ /* VSL (output) REAL array, dimension (LDVSL,N) */ /* If JOBVSL = 'V', VSL will contain the left Schur vectors. */ /* Not referenced if JOBVSL = 'N'. */ /* LDVSL (input) INTEGER */ /* The leading dimension of the matrix VSL. LDVSL >=1, and */ /* if JOBVSL = 'V', LDVSL >= N. */ /* VSR (output) REAL array, dimension (LDVSR,N) */ /* If JOBVSR = 'V', VSR will contain the right Schur vectors. */ /* Not referenced if JOBVSR = 'N'. */ /* LDVSR (input) INTEGER */ /* The leading dimension of the matrix VSR. LDVSR >= 1, and */ /* if JOBVSR = 'V', LDVSR >= N. */ /* RCONDE (output) REAL array, dimension ( 2 ) */ /* If SENSE = 'E' or 'B', RCONDE(1) and RCONDE(2) contain the */ /* reciprocal condition numbers for the average of the selected */ /* eigenvalues. */ /* Not referenced if SENSE = 'N' or 'V'. */ /* RCONDV (output) REAL array, dimension ( 2 ) */ /* If SENSE = 'V' or 'B', RCONDV(1) and RCONDV(2) contain the */ /* reciprocal condition numbers for the selected deflating */ /* subspaces. */ /* Not referenced if SENSE = 'N' or 'E'. */ /* WORK (workspace/output) REAL array, dimension (MAX(1,LWORK)) */ /* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */ /* LWORK (input) INTEGER */ /* The dimension of the array WORK. */ /* If N = 0, LWORK >= 1, else if SENSE = 'E', 'V', or 'B', */ /* LWORK >= max( 8*N, 6*N+16, 2*SDIM*(N-SDIM) ), else */ /* LWORK >= max( 8*N, 6*N+16 ). */ /* Note that 2*SDIM*(N-SDIM) <= N*N/2. */ /* Note also that an error is only returned if */ /* LWORK < max( 8*N, 6*N+16), but if SENSE = 'E' or 'V' or 'B' */ /* this may not be large enough. */ /* If LWORK = -1, then a workspace query is assumed; the routine */ /* only calculates the bound on the optimal size of the WORK */ /* array and the minimum size of the IWORK array, returns these */ /* values as the first entries of the WORK and IWORK arrays, and */ /* no error message related to LWORK or LIWORK is issued by */ /* XERBLA. */ /* IWORK (workspace) INTEGER array, dimension (MAX(1,LIWORK)) */ /* On exit, if INFO = 0, IWORK(1) returns the minimum LIWORK. */ /* LIWORK (input) INTEGER */ /* The dimension of the array IWORK. */ /* If SENSE = 'N' or N = 0, LIWORK >= 1, otherwise */ /* LIWORK >= N+6. */ /* If LIWORK = -1, then a workspace query is assumed; the */ /* routine only calculates the bound on the optimal size of the */ /* WORK array and the minimum size of the IWORK array, returns */ /* these values as the first entries of the WORK and IWORK */ /* arrays, and no error message related to LWORK or LIWORK is */ /* issued by XERBLA. */ /* BWORK (workspace) LOGICAL array, dimension (N) */ /* Not referenced if SORT = 'N'. */ /* INFO (output) INTEGER */ /* = 0: successful exit */ /* < 0: if INFO = -i, the i-th argument had an illegal value. */ /* = 1,...,N: */ /* The QZ iteration failed. (A,B) are not in Schur */ /* form, but ALPHAR(j), ALPHAI(j), and BETA(j) should */ /* be correct for j=INFO+1,...,N. */ /* > N: =N+1: other than QZ iteration failed in SHGEQZ */ /* =N+2: after reordering, roundoff changed values of */ /* some complex eigenvalues so that leading */ /* eigenvalues in the Generalized Schur form no */ /* longer satisfy SELCTG=.TRUE. This could also */ /* be caused due to scaling. */ /* =N+3: reordering failed in STGSEN. */ /* Further details */ /* =============== */ /* An approximate (asymptotic) bound on the average absolute error of */ /* the selected eigenvalues is */ /* EPS * norm((A, B)) / RCONDE( 1 ). */ /* An approximate (asymptotic) bound on the maximum angular error in */ /* the computed deflating subspaces is */ /* EPS * norm((A, B)) / RCONDV( 2 ). */ /* See LAPACK User's Guide, section 4.11 for more information. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. Local Arrays .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Decode the input arguments */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; b_dim1 = *ldb; b_offset = 1 + b_dim1; b -= b_offset; --alphar; --alphai; --beta; vsl_dim1 = *ldvsl; vsl_offset = 1 + vsl_dim1; vsl -= vsl_offset; vsr_dim1 = *ldvsr; vsr_offset = 1 + vsr_dim1; vsr -= vsr_offset; --rconde; --rcondv; --work; --iwork; --bwork; /* Function Body */ if (lsame_(jobvsl, "N")) { ijobvl = 1; ilvsl = FALSE_; } else if (lsame_(jobvsl, "V")) { ijobvl = 2; ilvsl = TRUE_; } else { ijobvl = -1; ilvsl = FALSE_; } if (lsame_(jobvsr, "N")) { ijobvr = 1; ilvsr = FALSE_; } else if (lsame_(jobvsr, "V")) { ijobvr = 2; ilvsr = TRUE_; } else { ijobvr = -1; ilvsr = FALSE_; } wantst = lsame_(sort, "S"); wantsn = lsame_(sense, "N"); wantse = lsame_(sense, "E"); wantsv = lsame_(sense, "V"); wantsb = lsame_(sense, "B"); lquery = *lwork == -1 || *liwork == -1; if (wantsn) { ijob = 0; } else if (wantse) { ijob = 1; } else if (wantsv) { ijob = 2; } else if (wantsb) { ijob = 4; } /* Test the input arguments */ *info = 0; if (ijobvl <= 0) { *info = -1; } else if (ijobvr <= 0) { *info = -2; } else if (! wantst && ! lsame_(sort, "N")) { *info = -3; } else if (! (wantsn || wantse || wantsv || wantsb) || ! wantst && ! wantsn) { *info = -5; } else if (*n < 0) { *info = -6; } else if (*lda < max(1,*n)) { *info = -8; } else if (*ldb < max(1,*n)) { *info = -10; } else if (*ldvsl < 1 || ilvsl && *ldvsl < *n) { *info = -16; } else if (*ldvsr < 1 || ilvsr && *ldvsr < *n) { *info = -18; } /* Compute workspace */ /* (Note: Comments in the code beginning "Workspace:" describe the */ /* minimal amount of workspace needed at that point in the code, */ /* as well as the preferred amount for good performance. */ /* NB refers to the optimal block size for the immediately */ /* following subroutine, as returned by ILAENV.) */ if (*info == 0) { if (*n > 0) { /* Computing MAX */ i__1 = *n << 3, i__2 = *n * 6 + 16; minwrk = max(i__1,i__2); maxwrk = minwrk - *n + *n * ilaenv_(&c__1, "SGEQRF", " ", n, & c__1, n, &c__0); /* Computing MAX */ i__1 = maxwrk, i__2 = minwrk - *n + *n * ilaenv_(&c__1, "SORMQR", " ", n, &c__1, n, &c_n1); maxwrk = max(i__1,i__2); if (ilvsl) { /* Computing MAX */ i__1 = maxwrk, i__2 = minwrk - *n + *n * ilaenv_(&c__1, "SOR" "GQR", " ", n, &c__1, n, &c_n1); maxwrk = max(i__1,i__2); } lwrk = maxwrk; if (ijob >= 1) { /* Computing MAX */ i__1 = lwrk, i__2 = *n * *n / 2; lwrk = max(i__1,i__2); } } else { minwrk = 1; maxwrk = 1; lwrk = 1; } work[1] = (real) lwrk; if (wantsn || *n == 0) { liwmin = 1; } else { liwmin = *n + 6; } iwork[1] = liwmin; if (*lwork < minwrk && ! lquery) { *info = -22; } else if (*liwork < liwmin && ! lquery) { *info = -24; } } if (*info != 0) { i__1 = -(*info); xerbla_("SGGESX", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*n == 0) { *sdim = 0; return 0; } /* Get machine constants */ eps = slamch_("P"); safmin = slamch_("S"); safmax = 1.f / safmin; slabad_(&safmin, &safmax); smlnum = sqrt(safmin) / eps; bignum = 1.f / smlnum; /* Scale A if max element outside range [SMLNUM,BIGNUM] */ anrm = slange_("M", n, n, &a[a_offset], lda, &work[1]); ilascl = FALSE_; if (anrm > 0.f && anrm < smlnum) { anrmto = smlnum; ilascl = TRUE_; } else if (anrm > bignum) { anrmto = bignum; ilascl = TRUE_; } if (ilascl) { slascl_("G", &c__0, &c__0, &anrm, &anrmto, n, n, &a[a_offset], lda, & ierr); } /* Scale B if max element outside range [SMLNUM,BIGNUM] */ bnrm = slange_("M", n, n, &b[b_offset], ldb, &work[1]); ilbscl = FALSE_; if (bnrm > 0.f && bnrm < smlnum) { bnrmto = smlnum; ilbscl = TRUE_; } else if (bnrm > bignum) { bnrmto = bignum; ilbscl = TRUE_; } if (ilbscl) { slascl_("G", &c__0, &c__0, &bnrm, &bnrmto, n, n, &b[b_offset], ldb, & ierr); } /* Permute the matrix to make it more nearly triangular */ /* (Workspace: need 6*N + 2*N for permutation parameters) */ ileft = 1; iright = *n + 1; iwrk = iright + *n; sggbal_("P", n, &a[a_offset], lda, &b[b_offset], ldb, &ilo, &ihi, &work[ ileft], &work[iright], &work[iwrk], &ierr); /* Reduce B to triangular form (QR decomposition of B) */ /* (Workspace: need N, prefer N*NB) */ irows = ihi + 1 - ilo; icols = *n + 1 - ilo; itau = iwrk; iwrk = itau + irows; i__1 = *lwork + 1 - iwrk; sgeqrf_(&irows, &icols, &b[ilo + ilo * b_dim1], ldb, &work[itau], &work[ iwrk], &i__1, &ierr); /* Apply the orthogonal transformation to matrix A */ /* (Workspace: need N, prefer N*NB) */ i__1 = *lwork + 1 - iwrk; sormqr_("L", "T", &irows, &icols, &irows, &b[ilo + ilo * b_dim1], ldb, & work[itau], &a[ilo + ilo * a_dim1], lda, &work[iwrk], &i__1, & ierr); /* Initialize VSL */ /* (Workspace: need N, prefer N*NB) */ if (ilvsl) { slaset_("Full", n, n, &c_b42, &c_b43, &vsl[vsl_offset], ldvsl); if (irows > 1) { i__1 = irows - 1; i__2 = irows - 1; slacpy_("L", &i__1, &i__2, &b[ilo + 1 + ilo * b_dim1], ldb, &vsl[ ilo + 1 + ilo * vsl_dim1], ldvsl); } i__1 = *lwork + 1 - iwrk; sorgqr_(&irows, &irows, &irows, &vsl[ilo + ilo * vsl_dim1], ldvsl, & work[itau], &work[iwrk], &i__1, &ierr); } /* Initialize VSR */ if (ilvsr) { slaset_("Full", n, n, &c_b42, &c_b43, &vsr[vsr_offset], ldvsr); } /* Reduce to generalized Hessenberg form */ /* (Workspace: none needed) */ sgghrd_(jobvsl, jobvsr, n, &ilo, &ihi, &a[a_offset], lda, &b[b_offset], ldb, &vsl[vsl_offset], ldvsl, &vsr[vsr_offset], ldvsr, &ierr); *sdim = 0; /* Perform QZ algorithm, computing Schur vectors if desired */ /* (Workspace: need N) */ iwrk = itau; i__1 = *lwork + 1 - iwrk; shgeqz_("S", jobvsl, jobvsr, n, &ilo, &ihi, &a[a_offset], lda, &b[ b_offset], ldb, &alphar[1], &alphai[1], &beta[1], &vsl[vsl_offset] , ldvsl, &vsr[vsr_offset], ldvsr, &work[iwrk], &i__1, &ierr); if (ierr != 0) { if (ierr > 0 && ierr <= *n) { *info = ierr; } else if (ierr > *n && ierr <= *n << 1) { *info = ierr - *n; } else { *info = *n + 1; } goto L50; } /* Sort eigenvalues ALPHA/BETA and compute the reciprocal of */ /* condition number(s) */ /* (Workspace: If IJOB >= 1, need MAX( 8*(N+1), 2*SDIM*(N-SDIM) ) */ /* otherwise, need 8*(N+1) ) */ if (wantst) { /* Undo scaling on eigenvalues before SELCTGing */ if (ilascl) { slascl_("G", &c__0, &c__0, &anrmto, &anrm, n, &c__1, &alphar[1], n, &ierr); slascl_("G", &c__0, &c__0, &anrmto, &anrm, n, &c__1, &alphai[1], n, &ierr); } if (ilbscl) { slascl_("G", &c__0, &c__0, &bnrmto, &bnrm, n, &c__1, &beta[1], n, &ierr); } /* Select eigenvalues */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { bwork[i__] = (*selctg)(&alphar[i__], &alphai[i__], &beta[i__]); /* L10: */ } /* Reorder eigenvalues, transform Generalized Schur vectors, and */ /* compute reciprocal condition numbers */ i__1 = *lwork - iwrk + 1; stgsen_(&ijob, &ilvsl, &ilvsr, &bwork[1], n, &a[a_offset], lda, &b[ b_offset], ldb, &alphar[1], &alphai[1], &beta[1], &vsl[ vsl_offset], ldvsl, &vsr[vsr_offset], ldvsr, sdim, &pl, &pr, dif, &work[iwrk], &i__1, &iwork[1], liwork, &ierr); if (ijob >= 1) { /* Computing MAX */ i__1 = maxwrk, i__2 = (*sdim << 1) * (*n - *sdim); maxwrk = max(i__1,i__2); } if (ierr == -22) { /* not enough real workspace */ *info = -22; } else { if (ijob == 1 || ijob == 4) { rconde[1] = pl; rconde[2] = pr; } if (ijob == 2 || ijob == 4) { rcondv[1] = dif[0]; rcondv[2] = dif[1]; } if (ierr == 1) { *info = *n + 3; } } } /* Apply permutation to VSL and VSR */ /* (Workspace: none needed) */ if (ilvsl) { sggbak_("P", "L", n, &ilo, &ihi, &work[ileft], &work[iright], n, &vsl[ vsl_offset], ldvsl, &ierr); } if (ilvsr) { sggbak_("P", "R", n, &ilo, &ihi, &work[ileft], &work[iright], n, &vsr[ vsr_offset], ldvsr, &ierr); } /* Check if unscaling would cause over/underflow, if so, rescale */ /* (ALPHAR(I),ALPHAI(I),BETA(I)) so BETA(I) is on the order of */ /* B(I,I) and ALPHAR(I) and ALPHAI(I) are on the order of A(I,I) */ if (ilascl) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (alphai[i__] != 0.f) { if (alphar[i__] / safmax > anrmto / anrm || safmin / alphar[ i__] > anrm / anrmto) { work[1] = (r__1 = a[i__ + i__ * a_dim1] / alphar[i__], dabs(r__1)); beta[i__] *= work[1]; alphar[i__] *= work[1]; alphai[i__] *= work[1]; } else if (alphai[i__] / safmax > anrmto / anrm || safmin / alphai[i__] > anrm / anrmto) { work[1] = (r__1 = a[i__ + (i__ + 1) * a_dim1] / alphai[ i__], dabs(r__1)); beta[i__] *= work[1]; alphar[i__] *= work[1]; alphai[i__] *= work[1]; } } /* L20: */ } } if (ilbscl) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (alphai[i__] != 0.f) { if (beta[i__] / safmax > bnrmto / bnrm || safmin / beta[i__] > bnrm / bnrmto) { work[1] = (r__1 = b[i__ + i__ * b_dim1] / beta[i__], dabs( r__1)); beta[i__] *= work[1]; alphar[i__] *= work[1]; alphai[i__] *= work[1]; } } /* L25: */ } } /* Undo scaling */ if (ilascl) { slascl_("H", &c__0, &c__0, &anrmto, &anrm, n, n, &a[a_offset], lda, & ierr); slascl_("G", &c__0, &c__0, &anrmto, &anrm, n, &c__1, &alphar[1], n, & ierr); slascl_("G", &c__0, &c__0, &anrmto, &anrm, n, &c__1, &alphai[1], n, & ierr); } if (ilbscl) { slascl_("U", &c__0, &c__0, &bnrmto, &bnrm, n, n, &b[b_offset], ldb, & ierr); slascl_("G", &c__0, &c__0, &bnrmto, &bnrm, n, &c__1, &beta[1], n, & ierr); } if (wantst) { /* Check if reordering is correct */ lastsl = TRUE_; lst2sl = TRUE_; *sdim = 0; ip = 0; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { cursl = (*selctg)(&alphar[i__], &alphai[i__], &beta[i__]); if (alphai[i__] == 0.f) { if (cursl) { ++(*sdim); } ip = 0; if (cursl && ! lastsl) { *info = *n + 2; } } else { if (ip == 1) { /* Last eigenvalue of conjugate pair */ cursl = cursl || lastsl; lastsl = cursl; if (cursl) { *sdim += 2; } ip = -1; if (cursl && ! lst2sl) { *info = *n + 2; } } else { /* First eigenvalue of conjugate pair */ ip = 1; } } lst2sl = lastsl; lastsl = cursl; /* L40: */ } } L50: work[1] = (real) maxwrk; iwork[1] = liwmin; return 0; /* End of SGGESX */ } /* sggesx_ */
/* Subroutine */ int stimqr_(char *line, integer *nm, integer *mval, integer * nval, integer *nk, integer *kval, integer *nnb, integer *nbval, integer *nxval, integer *nlda, integer *ldaval, real *timmin, real *a, real *tau, real *b, real *work, real *reslts, integer *ldr1, integer *ldr2, integer *ldr3, integer *nout, ftnlen line_len) { /* Initialized data */ static char subnam[6*3] = "SGEQRF" "SORGQR" "SORMQR"; static char sides[1*2] = "L" "R"; static char transs[1*2] = "N" "T"; static integer iseed[4] = { 0,0,0,1 }; /* Format strings */ static char fmt_9999[] = "(1x,a6,\002 timing run not attempted\002,/)"; static char fmt_9998[] = "(/\002 *** Speed of \002,a6,\002 in megaflops " "***\002)"; static char fmt_9997[] = "(5x,\002line \002,i2,\002 with LDA = \002,i5)"; static char fmt_9996[] = "(5x,\002K = min(M,N)\002,/)"; static char fmt_9995[] = "(/5x,a6,\002 with SIDE = '\002,a1,\002', TRANS" " = '\002,a1,\002', \002,a1,\002 =\002,i6,/)"; static char fmt_9994[] = "(\002 *** No pairs (M,N) found with M >= N: " " \002,a6,\002 not timed\002)"; /* System generated locals */ integer reslts_dim1, reslts_dim2, reslts_dim3, reslts_offset, i__1, i__2, i__3, i__4, i__5, i__6; /* Builtin functions Subroutine */ int s_copy(char *, char *, ftnlen, ftnlen); integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), s_wsle(cilist *), e_wsle(void); /* Local variables */ static integer ilda; static char labm[1], side[1]; static integer info; static char path[3]; static real time; static integer isub, muse[12], nuse[12], i__, k, m, n; static char cname[6]; static integer iside, itoff, itran, minmn; extern doublereal sopla_(char *, integer *, integer *, integer *, integer *, integer *); extern /* Subroutine */ int icopy_(integer *, integer *, integer *, integer *, integer *); static char trans[1]; static integer k1, i4, m1, n1; static real s1, s2; static integer ic; extern /* Subroutine */ int sprtb4_(char *, char *, char *, integer *, integer *, integer *, integer *, integer *, integer *, integer *, real *, integer *, integer *, integer *, ftnlen, ftnlen, ftnlen), sprtb5_(char *, char *, char *, integer *, integer *, integer *, integer *, integer *, integer *, real *, integer *, integer *, integer *, ftnlen, ftnlen, ftnlen); static integer nb, ik, im, lw, nx, reseed[4]; extern /* Subroutine */ int atimck_(integer *, char *, integer *, integer *, integer *, integer *, integer *, integer *, ftnlen); extern doublereal second_(void); extern /* Subroutine */ int atimin_(char *, char *, integer *, char *, logical *, integer *, integer *, ftnlen, ftnlen, ftnlen), sgeqrf_( integer *, integer *, real *, integer *, real *, real *, integer * , integer *), slacpy_(char *, integer *, integer *, real *, integer *, real *, integer *), xlaenv_(integer *, integer *); extern doublereal smflop_(real *, real *, integer *); static real untime; extern /* Subroutine */ int stimmg_(integer *, integer *, integer *, real *, integer *, integer *, integer *); static logical timsub[3]; extern /* Subroutine */ int slatms_(integer *, integer *, char *, integer *, char *, real *, integer *, real *, real *, integer *, integer * , char *, real *, integer *, real *, integer *), sorgqr_(integer *, integer *, integer *, real *, integer *, real *, real *, integer *, integer *), sormqr_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real * , integer *, real *, integer *, integer *); static integer lda, icl, inb, imx; static real ops; /* Fortran I/O blocks */ static cilist io___9 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___29 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___31 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___32 = { 0, 0, 0, 0, 0 }; static cilist io___33 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___34 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___49 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___50 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___51 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___53 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___54 = { 0, 0, 0, fmt_9994, 0 }; #define subnam_ref(a_0,a_1) &subnam[(a_1)*6 + a_0 - 6] #define reslts_ref(a_1,a_2,a_3,a_4) reslts[(((a_4)*reslts_dim3 + (a_3))*\ reslts_dim2 + (a_2))*reslts_dim1 + a_1] /* -- LAPACK timing routine (version 3.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University March 31, 1993 Purpose ======= STIMQR times the LAPACK routines to perform the QR factorization of a REAL general matrix. Arguments ========= LINE (input) CHARACTER*80 The input line that requested this routine. The first six characters contain either the name of a subroutine or a generic path name. The remaining characters may be used to specify the individual routines to be timed. See ATIMIN for a full description of the format of the input line. NM (input) INTEGER The number of values of M and N contained in the vectors MVAL and NVAL. The matrix sizes are used in pairs (M,N). MVAL (input) INTEGER array, dimension (NM) The values of the matrix row dimension M. NVAL (input) INTEGER array, dimension (NM) The values of the matrix column dimension N. NK (input) INTEGER The number of values of K in the vector KVAL. KVAL (input) INTEGER array, dimension (NK) The values of the matrix dimension K, used in SORMQR. NNB (input) INTEGER The number of values of NB and NX contained in the vectors NBVAL and NXVAL. The blocking parameters are used in pairs (NB,NX). NBVAL (input) INTEGER array, dimension (NNB) The values of the blocksize NB. NXVAL (input) INTEGER array, dimension (NNB) The values of the crossover point NX. NLDA (input) INTEGER The number of values of LDA contained in the vector LDAVAL. LDAVAL (input) INTEGER array, dimension (NLDA) The values of the leading dimension of the array A. TIMMIN (input) REAL The minimum time a subroutine will be timed. A (workspace) REAL array, dimension (LDAMAX*NMAX) where LDAMAX and NMAX are the maximum values of LDA and N. TAU (workspace) REAL array, dimension (min(M,N)) B (workspace) REAL array, dimension (LDAMAX*NMAX) WORK (workspace) REAL array, dimension (LDAMAX*NBMAX) where NBMAX is the maximum value of NB. RESLTS (workspace) REAL array, dimension (LDR1,LDR2,LDR3,2*NK) The timing results for each subroutine over the relevant values of (M,N), (NB,NX), and LDA. LDR1 (input) INTEGER The first dimension of RESLTS. LDR1 >= max(1,NNB). LDR2 (input) INTEGER The second dimension of RESLTS. LDR2 >= max(1,NM). LDR3 (input) INTEGER The third dimension of RESLTS. LDR3 >= max(1,NLDA). NOUT (input) INTEGER The unit number for output. Internal Parameters =================== MODE INTEGER The matrix type. MODE = 3 is a geometric distribution of eigenvalues. See SLATMS for further details. COND REAL The condition number of the matrix. The singular values are set to values from DMAX to DMAX/COND. DMAX REAL The magnitude of the largest singular value. ===================================================================== Parameter adjustments */ --mval; --nval; --kval; --nbval; --nxval; --ldaval; --a; --tau; --b; --work; reslts_dim1 = *ldr1; reslts_dim2 = *ldr2; reslts_dim3 = *ldr3; reslts_offset = 1 + reslts_dim1 * (1 + reslts_dim2 * (1 + reslts_dim3 * 1) ); reslts -= reslts_offset; /* Function Body Extract the timing request from the input line. */ s_copy(path, "Single precision", (ftnlen)1, (ftnlen)16); s_copy(path + 1, "QR", (ftnlen)2, (ftnlen)2); atimin_(path, line, &c__3, subnam, timsub, nout, &info, (ftnlen)3, ( ftnlen)80, (ftnlen)6); if (info != 0) { goto L230; } /* Check that M <= LDA for the input values. */ s_copy(cname, line, (ftnlen)6, (ftnlen)6); atimck_(&c__1, cname, nm, &mval[1], nlda, &ldaval[1], nout, &info, ( ftnlen)6); if (info > 0) { io___9.ciunit = *nout; s_wsfe(&io___9); do_fio(&c__1, cname, (ftnlen)6); e_wsfe(); goto L230; } /* Do for each pair of values (M,N): */ i__1 = *nm; for (im = 1; im <= i__1; ++im) { m = mval[im]; n = nval[im]; minmn = min(m,n); icopy_(&c__4, iseed, &c__1, reseed, &c__1); /* Do for each value of LDA: */ i__2 = *nlda; for (ilda = 1; ilda <= i__2; ++ilda) { lda = ldaval[ilda]; /* Do for each pair of values (NB, NX) in NBVAL and NXVAL. */ i__3 = *nnb; for (inb = 1; inb <= i__3; ++inb) { nb = nbval[inb]; xlaenv_(&c__1, &nb); nx = nxval[inb]; xlaenv_(&c__3, &nx); /* Computing MAX */ i__4 = 1, i__5 = n * max(1,nb); lw = max(i__4,i__5); /* Generate a test matrix of size M by N. */ icopy_(&c__4, reseed, &c__1, iseed, &c__1); slatms_(&m, &n, "Uniform", iseed, "Nonsymm", &tau[1], &c__3, & c_b24, &c_b25, &m, &n, "No packing", &b[1], &lda, & work[1], &info); if (timsub[0]) { /* SGEQRF: QR factorization */ slacpy_("Full", &m, &n, &b[1], &lda, &a[1], &lda); ic = 0; s1 = second_(); L10: sgeqrf_(&m, &n, &a[1], &lda, &tau[1], &work[1], &lw, & info); s2 = second_(); time = s2 - s1; ++ic; if (time < *timmin) { slacpy_("Full", &m, &n, &b[1], &lda, &a[1], &lda); goto L10; } /* Subtract the time used in SLACPY. */ icl = 1; s1 = second_(); L20: s2 = second_(); untime = s2 - s1; ++icl; if (icl <= ic) { slacpy_("Full", &m, &n, &a[1], &lda, &b[1], &lda); goto L20; } time = (time - untime) / (real) ic; ops = sopla_("SGEQRF", &m, &n, &c__0, &c__0, &nb); reslts_ref(inb, im, ilda, 1) = smflop_(&ops, &time, &info) ; } else { /* If SGEQRF was not timed, generate a matrix and factor it using SGEQRF anyway so that the factored form of the matrix can be used in timing the other routines. */ slacpy_("Full", &m, &n, &b[1], &lda, &a[1], &lda); sgeqrf_(&m, &n, &a[1], &lda, &tau[1], &work[1], &lw, & info); } if (timsub[1]) { /* SORGQR: Generate orthogonal matrix Q from the QR factorization */ slacpy_("Full", &m, &minmn, &a[1], &lda, &b[1], &lda); ic = 0; s1 = second_(); L30: sorgqr_(&m, &minmn, &minmn, &b[1], &lda, &tau[1], &work[1] , &lw, &info); s2 = second_(); time = s2 - s1; ++ic; if (time < *timmin) { slacpy_("Full", &m, &minmn, &a[1], &lda, &b[1], &lda); goto L30; } /* Subtract the time used in SLACPY. */ icl = 1; s1 = second_(); L40: s2 = second_(); untime = s2 - s1; ++icl; if (icl <= ic) { slacpy_("Full", &m, &minmn, &a[1], &lda, &b[1], &lda); goto L40; } time = (time - untime) / (real) ic; ops = sopla_("SORGQR", &m, &minmn, &minmn, &c__0, &nb); reslts_ref(inb, im, ilda, 2) = smflop_(&ops, &time, &info) ; } /* L50: */ } /* L60: */ } /* L70: */ } /* Print tables of results */ for (isub = 1; isub <= 2; ++isub) { if (! timsub[isub - 1]) { goto L90; } io___29.ciunit = *nout; s_wsfe(&io___29); do_fio(&c__1, subnam_ref(0, isub), (ftnlen)6); e_wsfe(); if (*nlda > 1) { i__1 = *nlda; for (i__ = 1; i__ <= i__1; ++i__) { io___31.ciunit = *nout; s_wsfe(&io___31); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ldaval[i__], (ftnlen)sizeof(integer)); e_wsfe(); /* L80: */ } } io___32.ciunit = *nout; s_wsle(&io___32); e_wsle(); if (isub == 2) { io___33.ciunit = *nout; s_wsfe(&io___33); e_wsfe(); } sprtb4_("( NB, NX)", "M", "N", nnb, &nbval[1], &nxval[1], nm, &mval[ 1], &nval[1], nlda, &reslts_ref(1, 1, 1, isub), ldr1, ldr2, nout, (ftnlen)11, (ftnlen)1, (ftnlen)1); L90: ; } /* Time SORMQR separately. Here the starting matrix is M by N, and K is the free dimension of the matrix multiplied by Q. */ if (timsub[2]) { /* Check that K <= LDA for the input values. */ atimck_(&c__3, cname, nk, &kval[1], nlda, &ldaval[1], nout, &info, ( ftnlen)6); if (info > 0) { io___34.ciunit = *nout; s_wsfe(&io___34); do_fio(&c__1, subnam_ref(0, 3), (ftnlen)6); e_wsfe(); goto L230; } /* Use only the pairs (M,N) where M >= N. */ imx = 0; i__1 = *nm; for (im = 1; im <= i__1; ++im) { if (mval[im] >= nval[im]) { ++imx; muse[imx - 1] = mval[im]; nuse[imx - 1] = nval[im]; } /* L100: */ } /* SORMQR: Multiply by Q stored as a product of elementary transformations Do for each pair of values (M,N): */ i__1 = imx; for (im = 1; im <= i__1; ++im) { m = muse[im - 1]; n = nuse[im - 1]; /* Do for each value of LDA: */ i__2 = *nlda; for (ilda = 1; ilda <= i__2; ++ilda) { lda = ldaval[ilda]; /* Generate an M by N matrix and form its QR decomposition. */ slatms_(&m, &n, "Uniform", iseed, "Nonsymm", &tau[1], &c__3, & c_b24, &c_b25, &m, &n, "No packing", &a[1], &lda, & work[1], &info); /* Computing MAX */ i__3 = 1, i__4 = n * max(1,nb); lw = max(i__3,i__4); sgeqrf_(&m, &n, &a[1], &lda, &tau[1], &work[1], &lw, &info); /* Do first for SIDE = 'L', then for SIDE = 'R' */ i4 = 0; for (iside = 1; iside <= 2; ++iside) { *(unsigned char *)side = *(unsigned char *)&sides[iside - 1]; /* Do for each pair of values (NB, NX) in NBVAL and NXVAL. */ i__3 = *nnb; for (inb = 1; inb <= i__3; ++inb) { nb = nbval[inb]; xlaenv_(&c__1, &nb); nx = nxval[inb]; xlaenv_(&c__3, &nx); /* Do for each value of K in KVAL */ i__4 = *nk; for (ik = 1; ik <= i__4; ++ik) { k = kval[ik]; /* Sort out which variable is which */ if (iside == 1) { m1 = m; k1 = n; n1 = k; /* Computing MAX */ i__5 = 1, i__6 = n1 * max(1,nb); lw = max(i__5,i__6); } else { n1 = m; k1 = n; m1 = k; /* Computing MAX */ i__5 = 1, i__6 = m1 * max(1,nb); lw = max(i__5,i__6); } /* Do first for TRANS = 'N', then for TRANS = 'T' */ itoff = 0; for (itran = 1; itran <= 2; ++itran) { *(unsigned char *)trans = *(unsigned char *)& transs[itran - 1]; stimmg_(&c__0, &m1, &n1, &b[1], &lda, &c__0, & c__0); ic = 0; s1 = second_(); L110: sormqr_(side, trans, &m1, &n1, &k1, &a[1], & lda, &tau[1], &b[1], &lda, &work[1], & lw, &info); s2 = second_(); time = s2 - s1; ++ic; if (time < *timmin) { stimmg_(&c__0, &m1, &n1, &b[1], &lda, & c__0, &c__0); goto L110; } /* Subtract the time used in STIMMG. */ icl = 1; s1 = second_(); L120: s2 = second_(); untime = s2 - s1; ++icl; if (icl <= ic) { stimmg_(&c__0, &m1, &n1, &b[1], &lda, & c__0, &c__0); goto L120; } time = (time - untime) / (real) ic; i__5 = iside - 1; ops = sopla_("SORMQR", &m1, &n1, &k1, &i__5, & nb); reslts_ref(inb, im, ilda, i4 + itoff + ik) = smflop_(&ops, &time, &info); itoff = *nk; /* L130: */ } /* L140: */ } /* L150: */ } i4 = *nk << 1; /* L160: */ } /* L170: */ } /* L180: */ } /* Print tables of results */ isub = 3; i4 = 1; if (imx >= 1) { for (iside = 1; iside <= 2; ++iside) { *(unsigned char *)side = *(unsigned char *)&sides[iside - 1]; if (iside == 1) { io___49.ciunit = *nout; s_wsfe(&io___49); do_fio(&c__1, subnam_ref(0, isub), (ftnlen)6); e_wsfe(); if (*nlda > 1) { i__1 = *nlda; for (i__ = 1; i__ <= i__1; ++i__) { io___50.ciunit = *nout; s_wsfe(&io___50); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&ldaval[i__], (ftnlen) sizeof(integer)); e_wsfe(); /* L190: */ } } } for (itran = 1; itran <= 2; ++itran) { *(unsigned char *)trans = *(unsigned char *)&transs[itran - 1]; i__1 = *nk; for (ik = 1; ik <= i__1; ++ik) { if (iside == 1) { n = kval[ik]; io___51.ciunit = *nout; s_wsfe(&io___51); do_fio(&c__1, subnam_ref(0, isub), (ftnlen)6); do_fio(&c__1, side, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, "N", (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)) ; e_wsfe(); *(unsigned char *)labm = 'M'; } else { m = kval[ik]; io___53.ciunit = *nout; s_wsfe(&io___53); do_fio(&c__1, subnam_ref(0, isub), (ftnlen)6); do_fio(&c__1, side, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, "M", (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)) ; e_wsfe(); *(unsigned char *)labm = 'N'; } sprtb5_("NB", labm, "K", nnb, &nbval[1], &imx, muse, nuse, nlda, &reslts_ref(1, 1, 1, i4), ldr1, ldr2, nout, (ftnlen)2, (ftnlen)1, (ftnlen)1); ++i4; /* L200: */ } /* L210: */ } /* L220: */ } } else { io___54.ciunit = *nout; s_wsfe(&io___54); do_fio(&c__1, subnam_ref(0, isub), (ftnlen)6); e_wsfe(); } } L230: return 0; /* End of STIMQR */ } /* stimqr_ */
/* Subroutine */ int sgglse_(integer *m, integer *n, integer *p, real *a, integer *lda, real *b, integer *ldb, real *c__, real *d__, real *x, real *work, integer *lwork, integer *info) { /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, i__1, i__2; /* Local variables */ integer nb, mn, nr, nb1, nb2, nb3, nb4, lopt; extern /* Subroutine */ int sgemv_(char *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *), scopy_(integer *, real *, integer *, real *, integer *), saxpy_(integer *, real *, real *, integer *, real *, integer *), strmv_(char *, char *, char *, integer *, real *, integer *, real *, integer *), xerbla_(char *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *); extern /* Subroutine */ int sggrqf_(integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, real *, integer * , integer *); integer lwkmin, lwkopt; logical lquery; extern /* Subroutine */ int sormqr_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *), sormrq_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real * , integer *, real *, integer *, integer *), strtrs_(char *, char *, char *, integer *, integer *, real *, integer *, real *, integer *, integer *); /* -- LAPACK driver routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SGGLSE solves the linear equality-constrained least squares (LSE) */ /* problem: */ /* minimize || c - A*x ||_2 subject to B*x = d */ /* where A is an M-by-N matrix, B is a P-by-N matrix, c is a given */ /* M-vector, and d is a given P-vector. It is assumed that */ /* P <= N <= M+P, and */ /* rank(B) = P and rank( (A) ) = N. */ /* ( (B) ) */ /* These conditions ensure that the LSE problem has a unique solution, */ /* which is obtained using a generalized RQ factorization of the */ /* matrices (B, A) given by */ /* B = (0 R)*Q, A = Z*T*Q. */ /* Arguments */ /* ========= */ /* M (input) INTEGER */ /* The number of rows of the matrix A. M >= 0. */ /* N (input) INTEGER */ /* The number of columns of the matrices A and B. N >= 0. */ /* P (input) INTEGER */ /* The number of rows of the matrix B. 0 <= P <= N <= M+P. */ /* A (input/output) REAL array, dimension (LDA,N) */ /* On entry, the M-by-N matrix A. */ /* On exit, the elements on and above the diagonal of the array */ /* contain the min(M,N)-by-N upper trapezoidal matrix T. */ /* LDA (input) INTEGER */ /* The leading dimension of the array A. LDA >= max(1,M). */ /* B (input/output) REAL array, dimension (LDB,N) */ /* On entry, the P-by-N matrix B. */ /* On exit, the upper triangle of the subarray B(1:P,N-P+1:N) */ /* contains the P-by-P upper triangular matrix R. */ /* LDB (input) INTEGER */ /* The leading dimension of the array B. LDB >= max(1,P). */ /* C (input/output) REAL array, dimension (M) */ /* On entry, C contains the right hand side vector for the */ /* least squares part of the LSE problem. */ /* On exit, the residual sum of squares for the solution */ /* is given by the sum of squares of elements N-P+1 to M of */ /* vector C. */ /* D (input/output) REAL array, dimension (P) */ /* On entry, D contains the right hand side vector for the */ /* constrained equation. */ /* On exit, D is destroyed. */ /* X (output) REAL array, dimension (N) */ /* On exit, X is the solution of the LSE problem. */ /* WORK (workspace/output) REAL array, dimension (MAX(1,LWORK)) */ /* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */ /* LWORK (input) INTEGER */ /* The dimension of the array WORK. LWORK >= max(1,M+N+P). */ /* For optimum performance LWORK >= P+min(M,N)+max(M,N)*NB, */ /* where NB is an upper bound for the optimal blocksizes for */ /* SGEQRF, SGERQF, SORMQR and SORMRQ. */ /* If LWORK = -1, then a workspace query is assumed; the routine */ /* only calculates the optimal size of the WORK array, returns */ /* this value as the first entry of the WORK array, and no error */ /* message related to LWORK is issued by XERBLA. */ /* INFO (output) INTEGER */ /* = 0: successful exit. */ /* < 0: if INFO = -i, the i-th argument had an illegal value. */ /* = 1: the upper triangular factor R associated with B in the */ /* generalized RQ factorization of the pair (B, A) is */ /* singular, so that rank(B) < P; the least squares */ /* solution could not be computed. */ /* = 2: the (N-P) by (N-P) part of the upper trapezoidal factor */ /* T associated with A in the generalized RQ factorization */ /* of the pair (B, A) is singular, so that */ /* rank( (A) ) < N; the least squares solution could not */ /* ( (B) ) */ /* be computed. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; b_dim1 = *ldb; b_offset = 1 + b_dim1; b -= b_offset; --c__; --d__; --x; --work; /* Function Body */ *info = 0; mn = min(*m,*n); lquery = *lwork == -1; if (*m < 0) { *info = -1; } else if (*n < 0) { *info = -2; } else if (*p < 0 || *p > *n || *p < *n - *m) { *info = -3; } else if (*lda < max(1,*m)) { *info = -5; } else if (*ldb < max(1,*p)) { *info = -7; } /* Calculate workspace */ if (*info == 0) { if (*n == 0) { lwkmin = 1; lwkopt = 1; } else { nb1 = ilaenv_(&c__1, "SGEQRF", " ", m, n, &c_n1, &c_n1); nb2 = ilaenv_(&c__1, "SGERQF", " ", m, n, &c_n1, &c_n1); nb3 = ilaenv_(&c__1, "SORMQR", " ", m, n, p, &c_n1); nb4 = ilaenv_(&c__1, "SORMRQ", " ", m, n, p, &c_n1); /* Computing MAX */ i__1 = max(nb1,nb2), i__1 = max(i__1,nb3); nb = max(i__1,nb4); lwkmin = *m + *n + *p; lwkopt = *p + mn + max(*m,*n) * nb; } work[1] = (real) lwkopt; if (*lwork < lwkmin && ! lquery) { *info = -12; } } if (*info != 0) { i__1 = -(*info); xerbla_("SGGLSE", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*n == 0) { return 0; } /* Compute the GRQ factorization of matrices B and A: */ /* B*Q' = ( 0 T12 ) P Z'*A*Q' = ( R11 R12 ) N-P */ /* N-P P ( 0 R22 ) M+P-N */ /* N-P P */ /* where T12 and R11 are upper triangular, and Q and Z are */ /* orthogonal. */ i__1 = *lwork - *p - mn; sggrqf_(p, m, n, &b[b_offset], ldb, &work[1], &a[a_offset], lda, &work[*p + 1], &work[*p + mn + 1], &i__1, info); lopt = work[*p + mn + 1]; /* Update c = Z'*c = ( c1 ) N-P */ /* ( c2 ) M+P-N */ i__1 = max(1,*m); i__2 = *lwork - *p - mn; sormqr_("Left", "Transpose", m, &c__1, &mn, &a[a_offset], lda, &work[*p + 1], &c__[1], &i__1, &work[*p + mn + 1], &i__2, info); /* Computing MAX */ i__1 = lopt, i__2 = (integer) work[*p + mn + 1]; lopt = max(i__1,i__2); /* Solve T12*x2 = d for x2 */ if (*p > 0) { strtrs_("Upper", "No transpose", "Non-unit", p, &c__1, &b[(*n - *p + 1) * b_dim1 + 1], ldb, &d__[1], p, info); if (*info > 0) { *info = 1; return 0; } /* Put the solution in X */ scopy_(p, &d__[1], &c__1, &x[*n - *p + 1], &c__1); /* Update c1 */ i__1 = *n - *p; sgemv_("No transpose", &i__1, p, &c_b31, &a[(*n - *p + 1) * a_dim1 + 1], lda, &d__[1], &c__1, &c_b33, &c__[1], &c__1); } /* Solve R11*x1 = c1 for x1 */ if (*n > *p) { i__1 = *n - *p; i__2 = *n - *p; strtrs_("Upper", "No transpose", "Non-unit", &i__1, &c__1, &a[ a_offset], lda, &c__[1], &i__2, info); if (*info > 0) { *info = 2; return 0; } /* Put the solution in X */ i__1 = *n - *p; scopy_(&i__1, &c__[1], &c__1, &x[1], &c__1); } /* Compute the residual vector: */ if (*m < *n) { nr = *m + *p - *n; if (nr > 0) { i__1 = *n - *m; sgemv_("No transpose", &nr, &i__1, &c_b31, &a[*n - *p + 1 + (*m + 1) * a_dim1], lda, &d__[nr + 1], &c__1, &c_b33, &c__[*n - *p + 1], &c__1); } } else { nr = *p; } if (nr > 0) { strmv_("Upper", "No transpose", "Non unit", &nr, &a[*n - *p + 1 + (*n - *p + 1) * a_dim1], lda, &d__[1], &c__1); saxpy_(&nr, &c_b31, &d__[1], &c__1, &c__[*n - *p + 1], &c__1); } /* Backward transformation x = Q'*x */ i__1 = *lwork - *p - mn; sormrq_("Left", "Transpose", n, &c__1, p, &b[b_offset], ldb, &work[1], &x[ 1], n, &work[*p + mn + 1], &i__1, info); /* Computing MAX */ i__1 = lopt, i__2 = (integer) work[*p + mn + 1]; work[1] = (real) (*p + mn + max(i__1,i__2)); return 0; /* End of SGGLSE */ } /* sgglse_ */
/* Subroutine */ int sormtr_(char *side, char *uplo, char *trans, int *m, int *n, real *a, int *lda, real *tau, real *c, int *ldc, real *work, int *lwork, int *info) { /* -- LAPACK routine (version 2.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University September 30, 1994 Purpose ======= SORMTR overwrites the general real M-by-N matrix C with SIDE = 'L' SIDE = 'R' TRANS = 'N': Q * C C * Q TRANS = 'T': Q**T * C C * Q**T where Q is a real orthogonal matrix of order nq, with nq = m if SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of nq-1 elementary reflectors, as returned by SSYTRD: if UPLO = 'U', Q = H(nq-1) . . . H(2) H(1); if UPLO = 'L', Q = H(1) H(2) . . . H(nq-1). Arguments ========= SIDE (input) CHARACTER*1 = 'L': apply Q or Q**T from the Left; = 'R': apply Q or Q**T from the Right. UPLO (input) CHARACTER*1 = 'U': Upper triangle of A contains elementary reflectors from SSYTRD; = 'L': Lower triangle of A contains elementary reflectors from SSYTRD. TRANS (input) CHARACTER*1 = 'N': No transpose, apply Q; = 'T': Transpose, apply Q**T. M (input) INTEGER The number of rows of the matrix C. M >= 0. N (input) INTEGER The number of columns of the matrix C. N >= 0. A (input) REAL array, dimension (LDA,M) if SIDE = 'L' (LDA,N) if SIDE = 'R' The vectors which define the elementary reflectors, as returned by SSYTRD. LDA (input) INTEGER The leading dimension of the array A. LDA >= max(1,M) if SIDE = 'L'; LDA >= max(1,N) if SIDE = 'R'. TAU (input) REAL array, dimension (M-1) if SIDE = 'L' (N-1) if SIDE = 'R' TAU(i) must contain the scalar factor of the elementary reflector H(i), as returned by SSYTRD. C (input/output) REAL array, dimension (LDC,N) On entry, the M-by-N matrix C. On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. LDC (input) INTEGER The leading dimension of the array C. LDC >= max(1,M). WORK (workspace/output) REAL array, dimension (LWORK) On exit, if INFO = 0, WORK(1) returns the optimal LWORK. LWORK (input) INTEGER The dimension of the array WORK. If SIDE = 'L', LWORK >= max(1,N); if SIDE = 'R', LWORK >= max(1,M). For optimum performance LWORK >= N*NB if SIDE = 'L', and LWORK >= M*NB if SIDE = 'R', where NB is the optimal blocksize. INFO (output) INTEGER = 0: successful exit < 0: if INFO = -i, the i-th argument had an illegal value ===================================================================== Test the input arguments Parameter adjustments Function Body */ /* System generated locals */ /* Unused variables commented out by MDG on 03-09-05 int a_dim1, a_offset, c_dim1, c_offset; */ int i__1; /* Local variables */ static logical left; extern logical lsame_(char *, char *); static int iinfo, i1; static logical upper; static int i2, mi, ni, nq, nw; extern /* Subroutine */ int xerbla_(char *, int *), sormql_( char *, char *, int *, int *, int *, real *, int * , real *, real *, int *, real *, int *, int *), sormqr_(char *, char *, int *, int *, int *, real *, int *, real *, real *, int *, real *, int *, int *); #define TAU(I) tau[(I)-1] #define WORK(I) work[(I)-1] #define A(I,J) a[(I)-1 + ((J)-1)* ( *lda)] #define C(I,J) c[(I)-1 + ((J)-1)* ( *ldc)] *info = 0; left = lsame_(side, "L"); upper = lsame_(uplo, "U"); /* NQ is the order of Q and NW is the minimum dimension of WORK */ if (left) { nq = *m; nw = *n; } else { nq = *n; nw = *m; } if (! left && ! lsame_(side, "R")) { *info = -1; } else if (! upper && ! lsame_(uplo, "L")) { *info = -2; } else if (! lsame_(trans, "N") && ! lsame_(trans, "T")) { *info = -3; } else if (*m < 0) { *info = -4; } else if (*n < 0) { *info = -5; } else if (*lda < max(1,nq)) { *info = -7; } else if (*ldc < max(1,*m)) { *info = -10; } else if (*lwork < max(1,nw)) { *info = -12; } if (*info != 0) { i__1 = -(*info); xerbla_("SORMTR", &i__1); return 0; } /* Quick return if possible */ if (*m == 0 || *n == 0 || nq == 1) { WORK(1) = 1.f; return 0; } if (left) { mi = *m - 1; ni = *n; } else { mi = *m; ni = *n - 1; } if (upper) { /* Q was determined by a call to SSYTRD with UPLO = 'U' */ i__1 = nq - 1; sormql_(side, trans, &mi, &ni, &i__1, &A(1,2), lda, & TAU(1), &C(1,1), ldc, &WORK(1), lwork, &iinfo); } else { /* Q was determined by a call to SSYTRD with UPLO = 'L' */ if (left) { i1 = 2; i2 = 1; } else { i1 = 1; i2 = 2; } i__1 = nq - 1; sormqr_(side, trans, &mi, &ni, &i__1, &A(2,1), lda, &TAU(1), & C(i1,i2), ldc, &WORK(1), lwork, &iinfo); } return 0; /* End of SORMTR */ } /* sormtr_ */
/* Subroutine */ int serrqr_(char *path, integer *nunit) { /* Builtin functions */ integer s_wsle(cilist *), e_wsle(void); /* Subroutine */ int s_copy(char *, char *, ftnlen, ftnlen); /* Local variables */ static integer info; static real a[4] /* was [2][2] */, b[2]; static integer i__, j; static real w[2], x[2]; extern /* Subroutine */ int sgeqr2_(integer *, integer *, real *, integer *, real *, real *, integer *); static real af[4] /* was [2][2] */; extern /* Subroutine */ int sorg2r_(integer *, integer *, integer *, real *, integer *, real *, real *, integer *), sorm2r_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real * , integer *, real *, integer *), alaesm_(char *, logical *, integer *), chkxer_(char *, integer *, integer *, logical *, logical *), sgeqrf_(integer *, integer *, real *, integer *, real *, real *, integer *, integer *), sgeqrs_( integer *, integer *, integer *, real *, integer *, real *, real * , integer *, real *, integer *, integer *), sorgqr_(integer *, integer *, integer *, real *, integer *, real *, real *, integer * , integer *), sormqr_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *); /* Fortran I/O blocks */ static cilist io___1 = { 0, 0, 0, 0, 0 }; #define a_ref(a_1,a_2) a[(a_2)*2 + a_1 - 3] #define af_ref(a_1,a_2) af[(a_2)*2 + a_1 - 3] /* -- LAPACK test routine (version 3.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University February 29, 1992 Purpose ======= SERRQR tests the error exits for the REAL routines that use the QR decomposition of a general matrix. Arguments ========= PATH (input) CHARACTER*3 The LAPACK path name for the routines to be tested. NUNIT (input) INTEGER The unit number for output. ===================================================================== */ infoc_1.nout = *nunit; io___1.ciunit = infoc_1.nout; s_wsle(&io___1); e_wsle(); /* Set the variables to innocuous values. */ for (j = 1; j <= 2; ++j) { for (i__ = 1; i__ <= 2; ++i__) { a_ref(i__, j) = 1.f / (real) (i__ + j); af_ref(i__, j) = 1.f / (real) (i__ + j); /* L10: */ } b[j - 1] = 0.f; w[j - 1] = 0.f; x[j - 1] = 0.f; /* L20: */ } infoc_1.ok = TRUE_; /* Error exits for QR factorization SGEQRF */ s_copy(srnamc_1.srnamt, "SGEQRF", (ftnlen)6, (ftnlen)6); infoc_1.infot = 1; sgeqrf_(&c_n1, &c__0, a, &c__1, b, w, &c__1, &info); chkxer_("SGEQRF", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; sgeqrf_(&c__0, &c_n1, a, &c__1, b, w, &c__1, &info); chkxer_("SGEQRF", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 4; sgeqrf_(&c__2, &c__1, a, &c__1, b, w, &c__1, &info); chkxer_("SGEQRF", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 7; sgeqrf_(&c__1, &c__2, a, &c__1, b, w, &c__1, &info); chkxer_("SGEQRF", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); /* SGEQR2 */ s_copy(srnamc_1.srnamt, "SGEQR2", (ftnlen)6, (ftnlen)6); infoc_1.infot = 1; sgeqr2_(&c_n1, &c__0, a, &c__1, b, w, &info); chkxer_("SGEQR2", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; sgeqr2_(&c__0, &c_n1, a, &c__1, b, w, &info); chkxer_("SGEQR2", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 4; sgeqr2_(&c__2, &c__1, a, &c__1, b, w, &info); chkxer_("SGEQR2", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); /* SGEQRS */ s_copy(srnamc_1.srnamt, "SGEQRS", (ftnlen)6, (ftnlen)6); infoc_1.infot = 1; sgeqrs_(&c_n1, &c__0, &c__0, a, &c__1, x, b, &c__1, w, &c__1, &info); chkxer_("SGEQRS", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; sgeqrs_(&c__0, &c_n1, &c__0, a, &c__1, x, b, &c__1, w, &c__1, &info); chkxer_("SGEQRS", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; sgeqrs_(&c__1, &c__2, &c__0, a, &c__2, x, b, &c__2, w, &c__1, &info); chkxer_("SGEQRS", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 3; sgeqrs_(&c__0, &c__0, &c_n1, a, &c__1, x, b, &c__1, w, &c__1, &info); chkxer_("SGEQRS", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; sgeqrs_(&c__2, &c__1, &c__0, a, &c__1, x, b, &c__2, w, &c__1, &info); chkxer_("SGEQRS", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 8; sgeqrs_(&c__2, &c__1, &c__0, a, &c__2, x, b, &c__1, w, &c__1, &info); chkxer_("SGEQRS", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 10; sgeqrs_(&c__1, &c__1, &c__2, a, &c__1, x, b, &c__1, w, &c__1, &info); chkxer_("SGEQRS", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); /* SORGQR */ s_copy(srnamc_1.srnamt, "SORGQR", (ftnlen)6, (ftnlen)6); infoc_1.infot = 1; sorgqr_(&c_n1, &c__0, &c__0, a, &c__1, x, w, &c__1, &info); chkxer_("SORGQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; sorgqr_(&c__0, &c_n1, &c__0, a, &c__1, x, w, &c__1, &info); chkxer_("SORGQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; sorgqr_(&c__1, &c__2, &c__0, a, &c__1, x, w, &c__2, &info); chkxer_("SORGQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 3; sorgqr_(&c__0, &c__0, &c_n1, a, &c__1, x, w, &c__1, &info); chkxer_("SORGQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 3; sorgqr_(&c__1, &c__1, &c__2, a, &c__1, x, w, &c__1, &info); chkxer_("SORGQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; sorgqr_(&c__2, &c__2, &c__0, a, &c__1, x, w, &c__2, &info); chkxer_("SORGQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 8; sorgqr_(&c__2, &c__2, &c__0, a, &c__2, x, w, &c__1, &info); chkxer_("SORGQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); /* SORG2R */ s_copy(srnamc_1.srnamt, "SORG2R", (ftnlen)6, (ftnlen)6); infoc_1.infot = 1; sorg2r_(&c_n1, &c__0, &c__0, a, &c__1, x, w, &info); chkxer_("SORG2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; sorg2r_(&c__0, &c_n1, &c__0, a, &c__1, x, w, &info); chkxer_("SORG2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; sorg2r_(&c__1, &c__2, &c__0, a, &c__1, x, w, &info); chkxer_("SORG2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 3; sorg2r_(&c__0, &c__0, &c_n1, a, &c__1, x, w, &info); chkxer_("SORG2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 3; sorg2r_(&c__2, &c__1, &c__2, a, &c__2, x, w, &info); chkxer_("SORG2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; sorg2r_(&c__2, &c__1, &c__0, a, &c__1, x, w, &info); chkxer_("SORG2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); /* SORMQR */ s_copy(srnamc_1.srnamt, "SORMQR", (ftnlen)6, (ftnlen)6); infoc_1.infot = 1; sormqr_("/", "N", &c__0, &c__0, &c__0, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; sormqr_("L", "/", &c__0, &c__0, &c__0, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 3; sormqr_("L", "N", &c_n1, &c__0, &c__0, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 4; sormqr_("L", "N", &c__0, &c_n1, &c__0, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; sormqr_("L", "N", &c__0, &c__0, &c_n1, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; sormqr_("L", "N", &c__0, &c__1, &c__1, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; sormqr_("R", "N", &c__1, &c__0, &c__1, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 7; sormqr_("L", "N", &c__2, &c__1, &c__0, a, &c__1, x, af, &c__2, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 7; sormqr_("R", "N", &c__1, &c__2, &c__0, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 10; sormqr_("L", "N", &c__2, &c__1, &c__0, a, &c__2, x, af, &c__1, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 12; sormqr_("L", "N", &c__1, &c__2, &c__0, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 12; sormqr_("R", "N", &c__2, &c__1, &c__0, a, &c__1, x, af, &c__2, w, &c__1, & info); chkxer_("SORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); /* SORM2R */ s_copy(srnamc_1.srnamt, "SORM2R", (ftnlen)6, (ftnlen)6); infoc_1.infot = 1; sorm2r_("/", "N", &c__0, &c__0, &c__0, a, &c__1, x, af, &c__1, w, &info); chkxer_("SORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; sorm2r_("L", "/", &c__0, &c__0, &c__0, a, &c__1, x, af, &c__1, w, &info); chkxer_("SORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 3; sorm2r_("L", "N", &c_n1, &c__0, &c__0, a, &c__1, x, af, &c__1, w, &info); chkxer_("SORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 4; sorm2r_("L", "N", &c__0, &c_n1, &c__0, a, &c__1, x, af, &c__1, w, &info); chkxer_("SORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; sorm2r_("L", "N", &c__0, &c__0, &c_n1, a, &c__1, x, af, &c__1, w, &info); chkxer_("SORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; sorm2r_("L", "N", &c__0, &c__1, &c__1, a, &c__1, x, af, &c__1, w, &info); chkxer_("SORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; sorm2r_("R", "N", &c__1, &c__0, &c__1, a, &c__1, x, af, &c__1, w, &info); chkxer_("SORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 7; sorm2r_("L", "N", &c__2, &c__1, &c__0, a, &c__1, x, af, &c__2, w, &info); chkxer_("SORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 7; sorm2r_("R", "N", &c__1, &c__2, &c__0, a, &c__1, x, af, &c__1, w, &info); chkxer_("SORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 10; sorm2r_("L", "N", &c__2, &c__1, &c__0, a, &c__2, x, af, &c__1, w, &info); chkxer_("SORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); /* Print a summary line. */ alaesm_(path, &infoc_1.ok, &infoc_1.nout); return 0; /* End of SERRQR */ } /* serrqr_ */
/* Subroutine */ int sqrt03_(integer *m, integer *n, integer *k, real *af, real *c__, real *cc, real *q, integer *lda, real *tau, real *work, integer *lwork, real *rwork, real *result) { /* Initialized data */ static integer iseed[4] = { 1988,1989,1990,1991 }; /* System generated locals */ integer af_dim1, af_offset, c_dim1, c_offset, cc_dim1, cc_offset, q_dim1, q_offset, i__1; /* Builtin functions */ /* Subroutine */ int s_copy(char *, char *, ftnlen, ftnlen); /* Local variables */ integer j, mc, nc; real eps; char side[1]; integer info, iside; extern logical lsame_(char *, char *); real resid; extern /* Subroutine */ int sgemm_(char *, char *, integer *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *); real cnorm; char trans[1]; extern doublereal slamch_(char *), slange_(char *, integer *, integer *, real *, integer *, real *); extern /* Subroutine */ int slacpy_(char *, integer *, integer *, real *, integer *, real *, integer *), slaset_(char *, integer *, integer *, real *, real *, real *, integer *); integer itrans; extern /* Subroutine */ int slarnv_(integer *, integer *, integer *, real *), sorgqr_(integer *, integer *, integer *, real *, integer *, real *, real *, integer *, integer *), sormqr_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real * , integer *, real *, integer *, integer *); /* -- LAPACK test routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SQRT03 tests SORMQR, which computes Q*C, Q'*C, C*Q or C*Q'. */ /* SQRT03 compares the results of a call to SORMQR with the results of */ /* forming Q explicitly by a call to SORGQR and then performing matrix */ /* multiplication by a call to SGEMM. */ /* Arguments */ /* ========= */ /* M (input) INTEGER */ /* The order of the orthogonal matrix Q. M >= 0. */ /* N (input) INTEGER */ /* The number of rows or columns of the matrix C; C is m-by-n if */ /* Q is applied from the left, or n-by-m if Q is applied from */ /* the right. N >= 0. */ /* K (input) INTEGER */ /* The number of elementary reflectors whose product defines the */ /* orthogonal matrix Q. M >= K >= 0. */ /* AF (input) REAL array, dimension (LDA,N) */ /* Details of the QR factorization of an m-by-n matrix, as */ /* returnedby SGEQRF. See SGEQRF for further details. */ /* C (workspace) REAL array, dimension (LDA,N) */ /* CC (workspace) REAL array, dimension (LDA,N) */ /* Q (workspace) REAL array, dimension (LDA,M) */ /* LDA (input) INTEGER */ /* The leading dimension of the arrays AF, C, CC, and Q. */ /* TAU (input) REAL array, dimension (min(M,N)) */ /* The scalar factors of the elementary reflectors corresponding */ /* to the QR factorization in AF. */ /* WORK (workspace) REAL array, dimension (LWORK) */ /* LWORK (input) INTEGER */ /* The length of WORK. LWORK must be at least M, and should be */ /* M*NB, where NB is the blocksize for this environment. */ /* RWORK (workspace) REAL array, dimension (M) */ /* RESULT (output) REAL array, dimension (4) */ /* The test ratios compare two techniques for multiplying a */ /* random matrix C by an m-by-m orthogonal matrix Q. */ /* RESULT(1) = norm( Q*C - Q*C ) / ( M * norm(C) * EPS ) */ /* RESULT(2) = norm( C*Q - C*Q ) / ( M * norm(C) * EPS ) */ /* RESULT(3) = norm( Q'*C - Q'*C )/ ( M * norm(C) * EPS ) */ /* RESULT(4) = norm( C*Q' - C*Q' )/ ( M * norm(C) * EPS ) */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Local Arrays .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Scalars in Common .. */ /* .. */ /* .. Common blocks .. */ /* .. */ /* .. Data statements .. */ /* Parameter adjustments */ q_dim1 = *lda; q_offset = 1 + q_dim1; q -= q_offset; cc_dim1 = *lda; cc_offset = 1 + cc_dim1; cc -= cc_offset; c_dim1 = *lda; c_offset = 1 + c_dim1; c__ -= c_offset; af_dim1 = *lda; af_offset = 1 + af_dim1; af -= af_offset; --tau; --work; --rwork; --result; /* Function Body */ /* .. */ /* .. Executable Statements .. */ eps = slamch_("Epsilon"); /* Copy the first k columns of the factorization to the array Q */ slaset_("Full", m, m, &c_b4, &c_b4, &q[q_offset], lda); i__1 = *m - 1; slacpy_("Lower", &i__1, k, &af[af_dim1 + 2], lda, &q[q_dim1 + 2], lda); /* Generate the m-by-m matrix Q */ s_copy(srnamc_1.srnamt, "SORGQR", (ftnlen)6, (ftnlen)6); sorgqr_(m, m, k, &q[q_offset], lda, &tau[1], &work[1], lwork, &info); for (iside = 1; iside <= 2; ++iside) { if (iside == 1) { *(unsigned char *)side = 'L'; mc = *m; nc = *n; } else { *(unsigned char *)side = 'R'; mc = *n; nc = *m; } /* Generate MC by NC matrix C */ i__1 = nc; for (j = 1; j <= i__1; ++j) { slarnv_(&c__2, iseed, &mc, &c__[j * c_dim1 + 1]); /* L10: */ } cnorm = slange_("1", &mc, &nc, &c__[c_offset], lda, &rwork[1]); if (cnorm == 0.f) { cnorm = 1.f; } for (itrans = 1; itrans <= 2; ++itrans) { if (itrans == 1) { *(unsigned char *)trans = 'N'; } else { *(unsigned char *)trans = 'T'; } /* Copy C */ slacpy_("Full", &mc, &nc, &c__[c_offset], lda, &cc[cc_offset], lda); /* Apply Q or Q' to C */ s_copy(srnamc_1.srnamt, "SORMQR", (ftnlen)6, (ftnlen)6); sormqr_(side, trans, &mc, &nc, k, &af[af_offset], lda, &tau[1], & cc[cc_offset], lda, &work[1], lwork, &info); /* Form explicit product and subtract */ if (lsame_(side, "L")) { sgemm_(trans, "No transpose", &mc, &nc, &mc, &c_b21, &q[ q_offset], lda, &c__[c_offset], lda, &c_b22, &cc[ cc_offset], lda); } else { sgemm_("No transpose", trans, &mc, &nc, &nc, &c_b21, &c__[ c_offset], lda, &q[q_offset], lda, &c_b22, &cc[ cc_offset], lda); } /* Compute error in the difference */ resid = slange_("1", &mc, &nc, &cc[cc_offset], lda, &rwork[1]); result[(iside - 1 << 1) + itrans] = resid / ((real) max(1,*m) * cnorm * eps); /* L20: */ } /* L30: */ } return 0; /* End of SQRT03 */ } /* sqrt03_ */
/* Subroutine */ int sgglse_(integer *m, integer *n, integer *p, real *a, integer *lda, real *b, integer *ldb, real *c, real *d, real *x, real * work, integer *lwork, integer *info) { /* -- LAPACK driver routine (version 2.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University September 30, 1994 Purpose ======= SGGLSE solves the linear equality-constrained least squares (LSE) problem: minimize || c - A*x ||_2 subject to B*x = d where A is an M-by-N matrix, B is a P-by-N matrix, c is a given M-vector, and d is a given P-vector. It is assumed that P <= N <= M+P, and rank(B) = P and rank( ( A ) ) = N. ( ( B ) ) These conditions ensure that the LSE problem has a unique solution, which is obtained using a GRQ factorization of the matrices B and A. Arguments ========= M (input) INTEGER The number of rows of the matrix A. M >= 0. N (input) INTEGER The number of columns of the matrices A and B. N >= 0. P (input) INTEGER The number of rows of the matrix B. 0 <= P <= N <= M+P. A (input/output) REAL array, dimension (LDA,N) On entry, the M-by-N matrix A. On exit, A is destroyed. LDA (input) INTEGER The leading dimension of the array A. LDA >= max(1,M). B (input/output) REAL array, dimension (LDB,N) On entry, the P-by-N matrix B. On exit, B is destroyed. LDB (input) INTEGER The leading dimension of the array B. LDB >= max(1,P). C (input/output) REAL array, dimension (M) On entry, C contains the right hand side vector for the least squares part of the LSE problem. On exit, the residual sum of squares for the solution is given by the sum of squares of elements N-P+1 to M of vector C. D (input/output) REAL array, dimension (P) On entry, D contains the right hand side vector for the constrained equation. On exit, D is destroyed. X (output) REAL array, dimension (N) On exit, X is the solution of the LSE problem. WORK (workspace/output) REAL array, dimension (LWORK) On exit, if INFO = 0, WORK(1) returns the optimal LWORK. LWORK (input) INTEGER The dimension of the array WORK. LWORK >= max(1,M+N+P). For optimum performance LWORK >= P+min(M,N)+max(M,N)*NB, where NB is an upper bound for the optimal blocksizes for SGEQRF, SGERQF, SORMQR and SORMRQ. INFO (output) INTEGER = 0: successful exit. < 0: if INFO = -i, the i-th argument had an illegal value. ===================================================================== Test the input parameters Parameter adjustments Function Body */ /* Table of constant values */ static integer c__1 = 1; static real c_b11 = -1.f; static real c_b13 = 1.f; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, i__1, i__2; /* Local variables */ static integer lopt; extern /* Subroutine */ int sgemv_(char *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *), scopy_(integer *, real *, integer *, real *, integer *), saxpy_(integer *, real *, real *, integer *, real *, integer *), strmv_(char *, char *, char *, integer *, real *, integer *, real *, integer *), strsv_(char *, char *, char *, integer *, real *, integer *, real *, integer *); static integer mn, nr; extern /* Subroutine */ int xerbla_(char *, integer *), sggrqf_( integer *, integer *, integer *, real *, integer *, real *, real * , integer *, real *, real *, integer *, integer *), sormqr_(char * , char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *), sormrq_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *); #define C(I) c[(I)-1] #define D(I) d[(I)-1] #define X(I) x[(I)-1] #define WORK(I) work[(I)-1] #define A(I,J) a[(I)-1 + ((J)-1)* ( *lda)] #define B(I,J) b[(I)-1 + ((J)-1)* ( *ldb)] *info = 0; mn = min(*m,*n); if (*m < 0) { *info = -1; } else if (*n < 0) { *info = -2; } else if (*p < 0 || *p > *n || *p < *n - *m) { *info = -3; } else if (*lda < max(1,*m)) { *info = -5; } else if (*ldb < max(1,*p)) { *info = -7; } else /* if(complicated condition) */ { /* Computing MAX */ i__1 = 1, i__2 = *m + *n + *p; if (*lwork < max(i__1,i__2)) { *info = -12; } } if (*info != 0) { i__1 = -(*info); xerbla_("SGGLSE", &i__1); return 0; } /* Quick return if possible */ if (*n == 0) { return 0; } /* Compute the GRQ factorization of matrices B and A: B*Q' = ( 0 T12 ) P Z'*A*Q' = ( R11 R12 ) N-P N-P P ( 0 R22 ) M+P-N N-P P where T12 and R11 are upper triangular, and Q and Z are orthogonal. */ i__1 = *lwork - *p - mn; sggrqf_(p, m, n, &B(1,1), ldb, &WORK(1), &A(1,1), lda, &WORK(*p + 1), &WORK(*p + mn + 1), &i__1, info); lopt = WORK(*p + mn + 1); /* Update c = Z'*c = ( c1 ) N-P ( c2 ) M+P-N */ i__1 = max(1,*m); i__2 = *lwork - *p - mn; sormqr_("Left", "Transpose", m, &c__1, &mn, &A(1,1), lda, &WORK(*p + 1), &C(1), &i__1, &WORK(*p + mn + 1), &i__2, info); /* Computing MAX */ i__1 = lopt, i__2 = (integer) WORK(*p + mn + 1); lopt = max(i__1,i__2); /* Solve T12*x2 = d for x2 */ strsv_("Upper", "No transpose", "Non unit", p, &B(1,*n-*p+1), ldb, &D(1), &c__1); /* Update c1 */ i__1 = *n - *p; sgemv_("No transpose", &i__1, p, &c_b11, &A(1,*n-*p+1), lda, &D(1), &c__1, &c_b13, &C(1), &c__1); /* Sovle R11*x1 = c1 for x1 */ i__1 = *n - *p; strsv_("Upper", "No transpose", "Non unit", &i__1, &A(1,1), lda, &C( 1), &c__1); /* Put the solutions in X */ i__1 = *n - *p; scopy_(&i__1, &C(1), &c__1, &X(1), &c__1); scopy_(p, &D(1), &c__1, &X(*n - *p + 1), &c__1); /* Compute the residual vector: */ if (*m < *n) { nr = *m + *p - *n; i__1 = *n - *m; sgemv_("No transpose", &nr, &i__1, &c_b11, &A(*n-*p+1,*m+1), lda, &D(nr + 1), &c__1, &c_b13, &C(*n - *p + 1), & c__1); } else { nr = *p; } strmv_("Upper", "No transpose", "Non unit", &nr, &A(*n-*p+1,*n-*p+1), lda, &D(1), &c__1); saxpy_(&nr, &c_b11, &D(1), &c__1, &C(*n - *p + 1), &c__1); /* Backward transformation x = Q'*x */ i__1 = *lwork - *p - mn; sormrq_("Left", "Transpose", n, &c__1, p, &B(1,1), ldb, &WORK(1), &X( 1), n, &WORK(*p + mn + 1), &i__1, info); /* Computing MAX */ i__1 = lopt, i__2 = (integer) WORK(*p + mn + 1); WORK(1) = (real) (*p + mn + max(i__1,i__2)); return 0; /* End of SGGLSE */ } /* sgglse_ */
/* Subroutine */ int sgeqp3_(integer *m, integer *n, real *a, integer *lda, integer *jpvt, real *tau, real *work, integer *lwork, integer *info) { /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3; /* Local variables */ integer j, jb, na, nb, sm, sn, nx, fjb, iws, nfxd; extern doublereal snrm2_(integer *, real *, integer *); integer nbmin, minmn, minws; extern /* Subroutine */ int sswap_(integer *, real *, integer *, real *, integer *), slaqp2_(integer *, integer *, integer *, real *, integer *, integer *, real *, real *, real *, real *), xerbla_( char *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *); extern /* Subroutine */ int sgeqrf_(integer *, integer *, real *, integer *, real *, real *, integer *, integer *); integer topbmn, sminmn; extern /* Subroutine */ int slaqps_(integer *, integer *, integer *, integer *, integer *, real *, integer *, integer *, real *, real * , real *, real *, real *, integer *); integer lwkopt; logical lquery; extern /* Subroutine */ int sormqr_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *); /* -- LAPACK routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SGEQP3 computes a QR factorization with column pivoting of a */ /* matrix A: A*P = Q*R using Level 3 BLAS. */ /* Arguments */ /* ========= */ /* M (input) INTEGER */ /* The number of rows of the matrix A. M >= 0. */ /* N (input) INTEGER */ /* The number of columns of the matrix A. N >= 0. */ /* A (input/output) REAL array, dimension (LDA,N) */ /* On entry, the M-by-N matrix A. */ /* On exit, the upper triangle of the array contains the */ /* min(M,N)-by-N upper trapezoidal matrix R; the elements below */ /* the diagonal, together with the array TAU, represent the */ /* orthogonal matrix Q as a product of min(M,N) elementary */ /* reflectors. */ /* LDA (input) INTEGER */ /* The leading dimension of the array A. LDA >= max(1,M). */ /* JPVT (input/output) INTEGER array, dimension (N) */ /* On entry, if JPVT(J).ne.0, the J-th column of A is permuted */ /* to the front of A*P (a leading column); if JPVT(J)=0, */ /* the J-th column of A is a free column. */ /* On exit, if JPVT(J)=K, then the J-th column of A*P was the */ /* the K-th column of A. */ /* TAU (output) REAL array, dimension (min(M,N)) */ /* The scalar factors of the elementary reflectors. */ /* WORK (workspace/output) REAL array, dimension (MAX(1,LWORK)) */ /* On exit, if INFO=0, WORK(1) returns the optimal LWORK. */ /* LWORK (input) INTEGER */ /* The dimension of the array WORK. LWORK >= 3*N+1. */ /* For optimal performance LWORK >= 2*N+( N+1 )*NB, where NB */ /* is the optimal blocksize. */ /* If LWORK = -1, then a workspace query is assumed; the routine */ /* only calculates the optimal size of the WORK array, returns */ /* this value as the first entry of the WORK array, and no error */ /* message related to LWORK is issued by XERBLA. */ /* INFO (output) INTEGER */ /* = 0: successful exit. */ /* < 0: if INFO = -i, the i-th argument had an illegal value. */ /* Further Details */ /* =============== */ /* The matrix Q is represented as a product of elementary reflectors */ /* Q = H(1) H(2) . . . H(k), where k = min(m,n). */ /* Each H(i) has the form */ /* H(i) = I - tau * v * v' */ /* where tau is a real/complex scalar, and v is a real/complex vector */ /* with v(1:i-1) = 0 and v(i) = 1; v(i+1:m) is stored on exit in */ /* A(i+1:m,i), and tau in TAU(i). */ /* Based on contributions by */ /* G. Quintana-Orti, Depto. de Informatica, Universidad Jaime I, Spain */ /* X. Sun, Computer Science Dept., Duke University, USA */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; --jpvt; --tau; --work; /* Function Body */ *info = 0; lquery = *lwork == -1; if (*m < 0) { *info = -1; } else if (*n < 0) { *info = -2; } else if (*lda < max(1,*m)) { *info = -4; } if (*info == 0) { minmn = min(*m,*n); if (minmn == 0) { iws = 1; lwkopt = 1; } else { iws = *n * 3 + 1; nb = ilaenv_(&c__1, "SGEQRF", " ", m, n, &c_n1, &c_n1); lwkopt = (*n << 1) + (*n + 1) * nb; } work[1] = (real) lwkopt; if (*lwork < iws && ! lquery) { *info = -8; } } if (*info != 0) { i__1 = -(*info); xerbla_("SGEQP3", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible. */ if (minmn == 0) { return 0; } /* Move initial columns up front. */ nfxd = 1; i__1 = *n; for (j = 1; j <= i__1; ++j) { if (jpvt[j] != 0) { if (j != nfxd) { sswap_(m, &a[j * a_dim1 + 1], &c__1, &a[nfxd * a_dim1 + 1], & c__1); jpvt[j] = jpvt[nfxd]; jpvt[nfxd] = j; } else { jpvt[j] = j; } ++nfxd; } else { jpvt[j] = j; } /* L10: */ } --nfxd; /* Factorize fixed columns */ /* ======================= */ /* Compute the QR factorization of fixed columns and update */ /* remaining columns. */ if (nfxd > 0) { na = min(*m,nfxd); /* CC CALL SGEQR2( M, NA, A, LDA, TAU, WORK, INFO ) */ sgeqrf_(m, &na, &a[a_offset], lda, &tau[1], &work[1], lwork, info); /* Computing MAX */ i__1 = iws, i__2 = (integer) work[1]; iws = max(i__1,i__2); if (na < *n) { /* CC CALL SORM2R( 'Left', 'Transpose', M, N-NA, NA, A, LDA, */ /* CC $ TAU, A( 1, NA+1 ), LDA, WORK, INFO ) */ i__1 = *n - na; sormqr_("Left", "Transpose", m, &i__1, &na, &a[a_offset], lda, & tau[1], &a[(na + 1) * a_dim1 + 1], lda, &work[1], lwork, info); /* Computing MAX */ i__1 = iws, i__2 = (integer) work[1]; iws = max(i__1,i__2); } } /* Factorize free columns */ /* ====================== */ if (nfxd < minmn) { sm = *m - nfxd; sn = *n - nfxd; sminmn = minmn - nfxd; /* Determine the block size. */ nb = ilaenv_(&c__1, "SGEQRF", " ", &sm, &sn, &c_n1, &c_n1); nbmin = 2; nx = 0; if (nb > 1 && nb < sminmn) { /* Determine when to cross over from blocked to unblocked code. */ /* Computing MAX */ i__1 = 0, i__2 = ilaenv_(&c__3, "SGEQRF", " ", &sm, &sn, &c_n1, & c_n1); nx = max(i__1,i__2); if (nx < sminmn) { /* Determine if workspace is large enough for blocked code. */ minws = (sn << 1) + (sn + 1) * nb; iws = max(iws,minws); if (*lwork < minws) { /* Not enough workspace to use optimal NB: Reduce NB and */ /* determine the minimum value of NB. */ nb = (*lwork - (sn << 1)) / (sn + 1); /* Computing MAX */ i__1 = 2, i__2 = ilaenv_(&c__2, "SGEQRF", " ", &sm, &sn, & c_n1, &c_n1); nbmin = max(i__1,i__2); } } } /* Initialize partial column norms. The first N elements of work */ /* store the exact column norms. */ i__1 = *n; for (j = nfxd + 1; j <= i__1; ++j) { work[j] = snrm2_(&sm, &a[nfxd + 1 + j * a_dim1], &c__1); work[*n + j] = work[j]; /* L20: */ } if (nb >= nbmin && nb < sminmn && nx < sminmn) { /* Use blocked code initially. */ j = nfxd + 1; /* Compute factorization: while loop. */ topbmn = minmn - nx; L30: if (j <= topbmn) { /* Computing MIN */ i__1 = nb, i__2 = topbmn - j + 1; jb = min(i__1,i__2); /* Factorize JB columns among columns J:N. */ i__1 = *n - j + 1; i__2 = j - 1; i__3 = *n - j + 1; slaqps_(m, &i__1, &i__2, &jb, &fjb, &a[j * a_dim1 + 1], lda, & jpvt[j], &tau[j], &work[j], &work[*n + j], &work[(*n << 1) + 1], &work[(*n << 1) + jb + 1], &i__3); j += fjb; goto L30; } } else { j = nfxd + 1; } /* Use unblocked code to factor the last or only block. */ if (j <= minmn) { i__1 = *n - j + 1; i__2 = j - 1; slaqp2_(m, &i__1, &i__2, &a[j * a_dim1 + 1], lda, &jpvt[j], &tau[ j], &work[j], &work[*n + j], &work[(*n << 1) + 1]); } } work[1] = (real) iws; return 0; /* End of SGEQP3 */ } /* sgeqp3_ */
/* Subroutine */ int sormtr_(char *side, char *uplo, char *trans, integer *m, integer *n, real *a, integer *lda, real *tau, real *c__, integer *ldc, real *work, integer *lwork, integer *info) { /* System generated locals */ address a__1[2]; integer a_dim1, a_offset, c_dim1, c_offset, i__1[2], i__2, i__3; char ch__1[2]; /* Local variables */ integer i1, i2, nb, mi, ni, nq, nw; logical left; integer iinfo; logical upper; integer lwkopt; logical lquery; /* -- LAPACK routine (version 3.2) -- */ /* November 2006 */ /* Purpose */ /* ======= */ /* SORMTR overwrites the general real M-by-N matrix C with */ /* SIDE = 'L' SIDE = 'R' */ /* TRANS = 'N': Q * C C * Q */ /* TRANS = 'T': Q**T * C C * Q**T */ /* where Q is a real orthogonal matrix of order nq, with nq = m if */ /* SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of */ /* nq-1 elementary reflectors, as returned by SSYTRD: */ /* if UPLO = 'U', Q = H(nq-1) . . . H(2) H(1); */ /* if UPLO = 'L', Q = H(1) H(2) . . . H(nq-1). */ /* Arguments */ /* ========= */ /* SIDE (input) CHARACTER*1 */ /* = 'L': apply Q or Q**T from the Left; */ /* = 'R': apply Q or Q**T from the Right. */ /* UPLO (input) CHARACTER*1 */ /* = 'U': Upper triangle of A contains elementary reflectors */ /* from SSYTRD; */ /* = 'L': Lower triangle of A contains elementary reflectors */ /* from SSYTRD. */ /* TRANS (input) CHARACTER*1 */ /* = 'N': No transpose, apply Q; */ /* = 'T': Transpose, apply Q**T. */ /* M (input) INTEGER */ /* The number of rows of the matrix C. M >= 0. */ /* N (input) INTEGER */ /* The number of columns of the matrix C. N >= 0. */ /* A (input) REAL array, dimension */ /* (LDA,M) if SIDE = 'L' */ /* (LDA,N) if SIDE = 'R' */ /* The vectors which define the elementary reflectors, as */ /* returned by SSYTRD. */ /* LDA (input) INTEGER */ /* The leading dimension of the array A. */ /* LDA >= max(1,M) if SIDE = 'L'; LDA >= max(1,N) if SIDE = 'R'. */ /* TAU (input) REAL array, dimension */ /* (M-1) if SIDE = 'L' */ /* (N-1) if SIDE = 'R' */ /* TAU(i) must contain the scalar factor of the elementary */ /* reflector H(i), as returned by SSYTRD. */ /* C (input/output) REAL array, dimension (LDC,N) */ /* On entry, the M-by-N matrix C. */ /* On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. */ /* LDC (input) INTEGER */ /* The leading dimension of the array C. LDC >= max(1,M). */ /* WORK (workspace/output) REAL array, dimension (MAX(1,LWORK)) */ /* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */ /* LWORK (input) INTEGER */ /* The dimension of the array WORK. */ /* If SIDE = 'L', LWORK >= max(1,N); */ /* if SIDE = 'R', LWORK >= max(1,M). */ /* For optimum performance LWORK >= N*NB if SIDE = 'L', and */ /* LWORK >= M*NB if SIDE = 'R', where NB is the optimal */ /* blocksize. */ /* If LWORK = -1, then a workspace query is assumed; the routine */ /* only calculates the optimal size of the WORK array, returns */ /* this value as the first entry of the WORK array, and no error */ /* message related to LWORK is issued by XERBLA. */ /* INFO (output) INTEGER */ /* = 0: successful exit */ /* < 0: if INFO = -i, the i-th argument had an illegal value */ /* ===================================================================== */ /* Test the input arguments */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; --tau; c_dim1 = *ldc; c_offset = 1 + c_dim1; c__ -= c_offset; --work; /* Function Body */ *info = 0; left = lsame_(side, "L"); upper = lsame_(uplo, "U"); lquery = *lwork == -1; /* NQ is the order of Q and NW is the minimum dimension of WORK */ if (left) { nq = *m; nw = *n; } else { nq = *n; nw = *m; } if (! left && ! lsame_(side, "R")) { *info = -1; } else if (! upper && ! lsame_(uplo, "L")) { *info = -2; } else if (! lsame_(trans, "N") && ! lsame_(trans, "T")) { *info = -3; } else if (*m < 0) { *info = -4; } else if (*n < 0) { *info = -5; } else if (*lda < max(1,nq)) { *info = -7; } else if (*ldc < max(1,*m)) { *info = -10; } else if (*lwork < max(1,nw) && ! lquery) { *info = -12; } if (*info == 0) { if (upper) { if (left) { /* Writing concatenation */ i__1[0] = 1, a__1[0] = side; i__1[1] = 1, a__1[1] = trans; s_cat(ch__1, a__1, i__1, &c__2, (ftnlen)2); i__2 = *m - 1; i__3 = *m - 1; nb = ilaenv_(&c__1, "SORMQL", ch__1, &i__2, n, &i__3, &c_n1); } else { /* Writing concatenation */ i__1[0] = 1, a__1[0] = side; i__1[1] = 1, a__1[1] = trans; s_cat(ch__1, a__1, i__1, &c__2, (ftnlen)2); i__2 = *n - 1; i__3 = *n - 1; nb = ilaenv_(&c__1, "SORMQL", ch__1, m, &i__2, &i__3, &c_n1); } } else { if (left) { /* Writing concatenation */ i__1[0] = 1, a__1[0] = side; i__1[1] = 1, a__1[1] = trans; s_cat(ch__1, a__1, i__1, &c__2, (ftnlen)2); i__2 = *m - 1; i__3 = *m - 1; nb = ilaenv_(&c__1, "SORMQR", ch__1, &i__2, n, &i__3, &c_n1); } else { /* Writing concatenation */ i__1[0] = 1, a__1[0] = side; i__1[1] = 1, a__1[1] = trans; s_cat(ch__1, a__1, i__1, &c__2, (ftnlen)2); i__2 = *n - 1; i__3 = *n - 1; nb = ilaenv_(&c__1, "SORMQR", ch__1, m, &i__2, &i__3, &c_n1); } } lwkopt = max(1,nw) * nb; work[1] = (real) lwkopt; } if (*info != 0) { i__2 = -(*info); xerbla_("SORMTR", &i__2); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*m == 0 || *n == 0 || nq == 1) { work[1] = 1.f; return 0; } if (left) { mi = *m - 1; ni = *n; } else { mi = *m; ni = *n - 1; } if (upper) { /* Q was determined by a call to SSYTRD with UPLO = 'U' */ i__2 = nq - 1; sormql_(side, trans, &mi, &ni, &i__2, &a[(a_dim1 << 1) + 1], lda, & tau[1], &c__[c_offset], ldc, &work[1], lwork, &iinfo); } else { /* Q was determined by a call to SSYTRD with UPLO = 'L' */ if (left) { i1 = 2; i2 = 1; } else { i1 = 1; i2 = 2; } i__2 = nq - 1; sormqr_(side, trans, &mi, &ni, &i__2, &a[a_dim1 + 2], lda, &tau[1], & c__[i1 + i2 * c_dim1], ldc, &work[1], lwork, &iinfo); } work[1] = (real) lwkopt; return 0; /* End of SORMTR */ } /* sormtr_ */
/* Subroutine */ int sormbr_(char *vect, char *side, char *trans, integer *m, integer *n, integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc, real *work, integer *lwork, integer *info) { /* System generated locals */ address a__1[2]; integer a_dim1, a_offset, c_dim1, c_offset, i__1, i__2, i__3[2]; char ch__1[2]; /* Builtin functions */ /* Subroutine */ int s_cat(char *, char **, integer *, integer *, ftnlen); /* Local variables */ integer i1, i2, nb, mi, ni, nq, nw; logical left; extern logical lsame_(char *, char *); integer iinfo; extern /* Subroutine */ int xerbla_(char *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *); logical notran, applyq; char transt[1]; extern /* Subroutine */ int sormlq_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *); integer lwkopt; logical lquery; extern /* Subroutine */ int sormqr_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *); /* -- LAPACK routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* If VECT = 'Q', SORMBR overwrites the general real M-by-N matrix C */ /* with */ /* SIDE = 'L' SIDE = 'R' */ /* TRANS = 'N': Q * C C * Q */ /* TRANS = 'T': Q**T * C C * Q**T */ /* If VECT = 'P', SORMBR overwrites the general real M-by-N matrix C */ /* with */ /* SIDE = 'L' SIDE = 'R' */ /* TRANS = 'N': P * C C * P */ /* TRANS = 'T': P**T * C C * P**T */ /* Here Q and P**T are the orthogonal matrices determined by SGEBRD when */ /* reducing a real matrix A to bidiagonal form: A = Q * B * P**T. Q and */ /* P**T are defined as products of elementary reflectors H(i) and G(i) */ /* respectively. */ /* Let nq = m if SIDE = 'L' and nq = n if SIDE = 'R'. Thus nq is the */ /* order of the orthogonal matrix Q or P**T that is applied. */ /* If VECT = 'Q', A is assumed to have been an NQ-by-K matrix: */ /* if nq >= k, Q = H(1) H(2) . . . H(k); */ /* if nq < k, Q = H(1) H(2) . . . H(nq-1). */ /* If VECT = 'P', A is assumed to have been a K-by-NQ matrix: */ /* if k < nq, P = G(1) G(2) . . . G(k); */ /* if k >= nq, P = G(1) G(2) . . . G(nq-1). */ /* Arguments */ /* ========= */ /* VECT (input) CHARACTER*1 */ /* = 'Q': apply Q or Q**T; */ /* = 'P': apply P or P**T. */ /* SIDE (input) CHARACTER*1 */ /* = 'L': apply Q, Q**T, P or P**T from the Left; */ /* = 'R': apply Q, Q**T, P or P**T from the Right. */ /* TRANS (input) CHARACTER*1 */ /* = 'N': No transpose, apply Q or P; */ /* = 'T': Transpose, apply Q**T or P**T. */ /* M (input) INTEGER */ /* The number of rows of the matrix C. M >= 0. */ /* N (input) INTEGER */ /* The number of columns of the matrix C. N >= 0. */ /* K (input) INTEGER */ /* If VECT = 'Q', the number of columns in the original */ /* matrix reduced by SGEBRD. */ /* If VECT = 'P', the number of rows in the original */ /* matrix reduced by SGEBRD. */ /* K >= 0. */ /* A (input) REAL array, dimension */ /* (LDA,min(nq,K)) if VECT = 'Q' */ /* (LDA,nq) if VECT = 'P' */ /* The vectors which define the elementary reflectors H(i) and */ /* G(i), whose products determine the matrices Q and P, as */ /* returned by SGEBRD. */ /* LDA (input) INTEGER */ /* The leading dimension of the array A. */ /* If VECT = 'Q', LDA >= max(1,nq); */ /* if VECT = 'P', LDA >= max(1,min(nq,K)). */ /* TAU (input) REAL array, dimension (min(nq,K)) */ /* TAU(i) must contain the scalar factor of the elementary */ /* reflector H(i) or G(i) which determines Q or P, as returned */ /* by SGEBRD in the array argument TAUQ or TAUP. */ /* C (input/output) REAL array, dimension (LDC,N) */ /* On entry, the M-by-N matrix C. */ /* On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q */ /* or P*C or P**T*C or C*P or C*P**T. */ /* LDC (input) INTEGER */ /* The leading dimension of the array C. LDC >= max(1,M). */ /* WORK (workspace/output) REAL array, dimension (MAX(1,LWORK)) */ /* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */ /* LWORK (input) INTEGER */ /* The dimension of the array WORK. */ /* If SIDE = 'L', LWORK >= max(1,N); */ /* if SIDE = 'R', LWORK >= max(1,M). */ /* For optimum performance LWORK >= N*NB if SIDE = 'L', and */ /* LWORK >= M*NB if SIDE = 'R', where NB is the optimal */ /* blocksize. */ /* If LWORK = -1, then a workspace query is assumed; the routine */ /* only calculates the optimal size of the WORK array, returns */ /* this value as the first entry of the WORK array, and no error */ /* message related to LWORK is issued by XERBLA. */ /* INFO (output) INTEGER */ /* = 0: successful exit */ /* < 0: if INFO = -i, the i-th argument had an illegal value */ /* ===================================================================== */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input arguments */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; --tau; c_dim1 = *ldc; c_offset = 1 + c_dim1; c__ -= c_offset; --work; /* Function Body */ *info = 0; applyq = lsame_(vect, "Q"); left = lsame_(side, "L"); notran = lsame_(trans, "N"); lquery = *lwork == -1; /* NQ is the order of Q or P and NW is the minimum dimension of WORK */ if (left) { nq = *m; nw = *n; } else { nq = *n; nw = *m; } if (! applyq && ! lsame_(vect, "P")) { *info = -1; } else if (! left && ! lsame_(side, "R")) { *info = -2; } else if (! notran && ! lsame_(trans, "T")) { *info = -3; } else if (*m < 0) { *info = -4; } else if (*n < 0) { *info = -5; } else if (*k < 0) { *info = -6; } else /* if(complicated condition) */ { /* Computing MAX */ i__1 = 1, i__2 = min(nq,*k); if (applyq && *lda < max(1,nq) || ! applyq && *lda < max(i__1,i__2)) { *info = -8; } else if (*ldc < max(1,*m)) { *info = -11; } else if (*lwork < max(1,nw) && ! lquery) { *info = -13; } } if (*info == 0) { if (applyq) { if (left) { /* Writing concatenation */ i__3[0] = 1, a__1[0] = side; i__3[1] = 1, a__1[1] = trans; s_cat(ch__1, a__1, i__3, &c__2, (ftnlen)2); i__1 = *m - 1; i__2 = *m - 1; nb = ilaenv_(&c__1, "SORMQR", ch__1, &i__1, n, &i__2, &c_n1); } else { /* Writing concatenation */ i__3[0] = 1, a__1[0] = side; i__3[1] = 1, a__1[1] = trans; s_cat(ch__1, a__1, i__3, &c__2, (ftnlen)2); i__1 = *n - 1; i__2 = *n - 1; nb = ilaenv_(&c__1, "SORMQR", ch__1, m, &i__1, &i__2, &c_n1); } } else { if (left) { /* Writing concatenation */ i__3[0] = 1, a__1[0] = side; i__3[1] = 1, a__1[1] = trans; s_cat(ch__1, a__1, i__3, &c__2, (ftnlen)2); i__1 = *m - 1; i__2 = *m - 1; nb = ilaenv_(&c__1, "SORMLQ", ch__1, &i__1, n, &i__2, &c_n1); } else { /* Writing concatenation */ i__3[0] = 1, a__1[0] = side; i__3[1] = 1, a__1[1] = trans; s_cat(ch__1, a__1, i__3, &c__2, (ftnlen)2); i__1 = *n - 1; i__2 = *n - 1; nb = ilaenv_(&c__1, "SORMLQ", ch__1, m, &i__1, &i__2, &c_n1); } } lwkopt = max(1,nw) * nb; work[1] = (real) lwkopt; } if (*info != 0) { i__1 = -(*info); xerbla_("SORMBR", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ work[1] = 1.f; if (*m == 0 || *n == 0) { return 0; } if (applyq) { /* Apply Q */ if (nq >= *k) { /* Q was determined by a call to SGEBRD with nq >= k */ sormqr_(side, trans, m, n, k, &a[a_offset], lda, &tau[1], &c__[ c_offset], ldc, &work[1], lwork, &iinfo); } else if (nq > 1) { /* Q was determined by a call to SGEBRD with nq < k */ if (left) { mi = *m - 1; ni = *n; i1 = 2; i2 = 1; } else { mi = *m; ni = *n - 1; i1 = 1; i2 = 2; } i__1 = nq - 1; sormqr_(side, trans, &mi, &ni, &i__1, &a[a_dim1 + 2], lda, &tau[1] , &c__[i1 + i2 * c_dim1], ldc, &work[1], lwork, &iinfo); } } else { /* Apply P */ if (notran) { *(unsigned char *)transt = 'T'; } else { *(unsigned char *)transt = 'N'; } if (nq > *k) { /* P was determined by a call to SGEBRD with nq > k */ sormlq_(side, transt, m, n, k, &a[a_offset], lda, &tau[1], &c__[ c_offset], ldc, &work[1], lwork, &iinfo); } else if (nq > 1) { /* P was determined by a call to SGEBRD with nq <= k */ if (left) { mi = *m - 1; ni = *n; i1 = 2; i2 = 1; } else { mi = *m; ni = *n - 1; i1 = 1; i2 = 2; } i__1 = nq - 1; sormlq_(side, transt, &mi, &ni, &i__1, &a[(a_dim1 << 1) + 1], lda, &tau[1], &c__[i1 + i2 * c_dim1], ldc, &work[1], lwork, & iinfo); } } work[1] = (real) lwkopt; return 0; /* End of SORMBR */ } /* sormbr_ */
int sggevx_(char *balanc, char *jobvl, char *jobvr, char * sense, int *n, float *a, int *lda, float *b, int *ldb, float *alphar, float *alphai, float *beta, float *vl, int *ldvl, float *vr, int *ldvr, int *ilo, int *ihi, float *lscale, float *rscale, float *abnrm, float *bbnrm, float *rconde, float *rcondv, float *work, int *lwork, int *iwork, int *bwork, int *info) { /* System generated locals */ int a_dim1, a_offset, b_dim1, b_offset, vl_dim1, vl_offset, vr_dim1, vr_offset, i__1, i__2; float r__1, r__2, r__3, r__4; /* Builtin functions */ double sqrt(double); /* Local variables */ int i__, j, m, jc, in, mm, jr; float eps; int ilv, pair; float anrm, bnrm; int ierr, itau; float temp; int ilvl, ilvr; int iwrk, iwrk1; extern int lsame_(char *, char *); int icols; int noscl; int irows; extern int slabad_(float *, float *), sggbak_(char *, char *, int *, int *, int *, float *, float *, int *, float *, int *, int *), sggbal_(char *, int *, float *, int *, float *, int *, int *, int *, float *, float *, float *, int *); int ilascl, ilbscl; extern double slamch_(char *); extern int xerbla_(char *, int *), sgghrd_( char *, char *, int *, int *, int *, float *, int * , float *, int *, float *, int *, float *, int *, int *); int ldumma[1]; char chtemp[1]; float bignum; extern int slascl_(char *, int *, int *, float *, float *, int *, int *, float *, int *, int *); extern int ilaenv_(int *, char *, char *, int *, int *, int *, int *); extern double slange_(char *, int *, int *, float *, int *, float *); int ijobvl; extern int sgeqrf_(int *, int *, float *, int *, float *, float *, int *, int *); int ijobvr; extern int slacpy_(char *, int *, int *, float *, int *, float *, int *); int wantsb; extern int slaset_(char *, int *, int *, float *, float *, float *, int *); float anrmto; int wantse; float bnrmto; extern int shgeqz_(char *, char *, char *, int *, int *, int *, float *, int *, float *, int *, float * , float *, float *, float *, int *, float *, int *, float *, int *, int *), stgevc_(char *, char *, int *, int *, float *, int *, float *, int * , float *, int *, float *, int *, int *, int *, float *, int *), stgsna_(char *, char *, int *, int *, float *, int *, float *, int *, float * , int *, float *, int *, float *, float *, int *, int *, float *, int *, int *, int *); int minwrk, maxwrk; int wantsn; float smlnum; extern int sorgqr_(int *, int *, int *, float *, int *, float *, float *, int *, int *); int lquery, wantsv; extern int sormqr_(char *, char *, int *, int *, int *, float *, int *, float *, float *, int *, float *, int *, int *); /* -- LAPACK driver routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SGGEVX computes for a pair of N-by-N float nonsymmetric matrices (A,B) */ /* the generalized eigenvalues, and optionally, the left and/or right */ /* generalized eigenvectors. */ /* Optionally also, it computes a balancing transformation to improve */ /* the conditioning of the eigenvalues and eigenvectors (ILO, IHI, */ /* LSCALE, RSCALE, ABNRM, and BBNRM), reciprocal condition numbers for */ /* the eigenvalues (RCONDE), and reciprocal condition numbers for the */ /* right eigenvectors (RCONDV). */ /* A generalized eigenvalue for a pair of matrices (A,B) is a scalar */ /* lambda or a ratio alpha/beta = lambda, such that A - lambda*B is */ /* singular. It is usually represented as the pair (alpha,beta), as */ /* there is a reasonable interpretation for beta=0, and even for both */ /* being zero. */ /* The right eigenvector v(j) corresponding to the eigenvalue lambda(j) */ /* of (A,B) satisfies */ /* A * v(j) = lambda(j) * B * v(j) . */ /* The left eigenvector u(j) corresponding to the eigenvalue lambda(j) */ /* of (A,B) satisfies */ /* u(j)**H * A = lambda(j) * u(j)**H * B. */ /* where u(j)**H is the conjugate-transpose of u(j). */ /* Arguments */ /* ========= */ /* BALANC (input) CHARACTER*1 */ /* Specifies the balance option to be performed. */ /* = 'N': do not diagonally scale or permute; */ /* = 'P': permute only; */ /* = 'S': scale only; */ /* = 'B': both permute and scale. */ /* Computed reciprocal condition numbers will be for the */ /* matrices after permuting and/or balancing. Permuting does */ /* not change condition numbers (in exact arithmetic), but */ /* balancing does. */ /* JOBVL (input) CHARACTER*1 */ /* = 'N': do not compute the left generalized eigenvectors; */ /* = 'V': compute the left generalized eigenvectors. */ /* JOBVR (input) CHARACTER*1 */ /* = 'N': do not compute the right generalized eigenvectors; */ /* = 'V': compute the right generalized eigenvectors. */ /* SENSE (input) CHARACTER*1 */ /* Determines which reciprocal condition numbers are computed. */ /* = 'N': none are computed; */ /* = 'E': computed for eigenvalues only; */ /* = 'V': computed for eigenvectors only; */ /* = 'B': computed for eigenvalues and eigenvectors. */ /* N (input) INTEGER */ /* The order of the matrices A, B, VL, and VR. N >= 0. */ /* A (input/output) REAL array, dimension (LDA, N) */ /* On entry, the matrix A in the pair (A,B). */ /* On exit, A has been overwritten. If JOBVL='V' or JOBVR='V' */ /* or both, then A contains the first part of the float Schur */ /* form of the "balanced" versions of the input A and B. */ /* LDA (input) INTEGER */ /* The leading dimension of A. LDA >= MAX(1,N). */ /* B (input/output) REAL array, dimension (LDB, N) */ /* On entry, the matrix B in the pair (A,B). */ /* On exit, B has been overwritten. If JOBVL='V' or JOBVR='V' */ /* or both, then B contains the second part of the float Schur */ /* form of the "balanced" versions of the input A and B. */ /* LDB (input) INTEGER */ /* The leading dimension of B. LDB >= MAX(1,N). */ /* ALPHAR (output) REAL array, dimension (N) */ /* ALPHAI (output) REAL array, dimension (N) */ /* BETA (output) REAL array, dimension (N) */ /* On exit, (ALPHAR(j) + ALPHAI(j)*i)/BETA(j), j=1,...,N, will */ /* be the generalized eigenvalues. If ALPHAI(j) is zero, then */ /* the j-th eigenvalue is float; if positive, then the j-th and */ /* (j+1)-st eigenvalues are a complex conjugate pair, with */ /* ALPHAI(j+1) negative. */ /* Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j) */ /* may easily over- or underflow, and BETA(j) may even be zero. */ /* Thus, the user should avoid naively computing the ratio */ /* ALPHA/BETA. However, ALPHAR and ALPHAI will be always less */ /* than and usually comparable with norm(A) in magnitude, and */ /* BETA always less than and usually comparable with norm(B). */ /* VL (output) REAL array, dimension (LDVL,N) */ /* If JOBVL = 'V', the left eigenvectors u(j) are stored one */ /* after another in the columns of VL, in the same order as */ /* their eigenvalues. If the j-th eigenvalue is float, then */ /* u(j) = VL(:,j), the j-th column of VL. If the j-th and */ /* (j+1)-th eigenvalues form a complex conjugate pair, then */ /* u(j) = VL(:,j)+i*VL(:,j+1) and u(j+1) = VL(:,j)-i*VL(:,j+1). */ /* Each eigenvector will be scaled so the largest component have */ /* ABS(float part) + ABS(imag. part) = 1. */ /* Not referenced if JOBVL = 'N'. */ /* LDVL (input) INTEGER */ /* The leading dimension of the matrix VL. LDVL >= 1, and */ /* if JOBVL = 'V', LDVL >= N. */ /* VR (output) REAL array, dimension (LDVR,N) */ /* If JOBVR = 'V', the right eigenvectors v(j) are stored one */ /* after another in the columns of VR, in the same order as */ /* their eigenvalues. If the j-th eigenvalue is float, then */ /* v(j) = VR(:,j), the j-th column of VR. If the j-th and */ /* (j+1)-th eigenvalues form a complex conjugate pair, then */ /* v(j) = VR(:,j)+i*VR(:,j+1) and v(j+1) = VR(:,j)-i*VR(:,j+1). */ /* Each eigenvector will be scaled so the largest component have */ /* ABS(float part) + ABS(imag. part) = 1. */ /* Not referenced if JOBVR = 'N'. */ /* LDVR (input) INTEGER */ /* The leading dimension of the matrix VR. LDVR >= 1, and */ /* if JOBVR = 'V', LDVR >= N. */ /* ILO (output) INTEGER */ /* IHI (output) INTEGER */ /* ILO and IHI are int values such that on exit */ /* A(i,j) = 0 and B(i,j) = 0 if i > j and */ /* j = 1,...,ILO-1 or i = IHI+1,...,N. */ /* If BALANC = 'N' or 'S', ILO = 1 and IHI = N. */ /* LSCALE (output) REAL array, dimension (N) */ /* Details of the permutations and scaling factors applied */ /* to the left side of A and B. If PL(j) is the index of the */ /* row interchanged with row j, and DL(j) is the scaling */ /* factor applied to row j, then */ /* LSCALE(j) = PL(j) for j = 1,...,ILO-1 */ /* = DL(j) for j = ILO,...,IHI */ /* = PL(j) for j = IHI+1,...,N. */ /* The order in which the interchanges are made is N to IHI+1, */ /* then 1 to ILO-1. */ /* RSCALE (output) REAL array, dimension (N) */ /* Details of the permutations and scaling factors applied */ /* to the right side of A and B. If PR(j) is the index of the */ /* column interchanged with column j, and DR(j) is the scaling */ /* factor applied to column j, then */ /* RSCALE(j) = PR(j) for j = 1,...,ILO-1 */ /* = DR(j) for j = ILO,...,IHI */ /* = PR(j) for j = IHI+1,...,N */ /* The order in which the interchanges are made is N to IHI+1, */ /* then 1 to ILO-1. */ /* ABNRM (output) REAL */ /* The one-norm of the balanced matrix A. */ /* BBNRM (output) REAL */ /* The one-norm of the balanced matrix B. */ /* RCONDE (output) REAL array, dimension (N) */ /* If SENSE = 'E' or 'B', the reciprocal condition numbers of */ /* the eigenvalues, stored in consecutive elements of the array. */ /* For a complex conjugate pair of eigenvalues two consecutive */ /* elements of RCONDE are set to the same value. Thus RCONDE(j), */ /* RCONDV(j), and the j-th columns of VL and VR all correspond */ /* to the j-th eigenpair. */ /* If SENSE = 'N' or 'V', RCONDE is not referenced. */ /* RCONDV (output) REAL array, dimension (N) */ /* If SENSE = 'V' or 'B', the estimated reciprocal condition */ /* numbers of the eigenvectors, stored in consecutive elements */ /* of the array. For a complex eigenvector two consecutive */ /* elements of RCONDV are set to the same value. If the */ /* eigenvalues cannot be reordered to compute RCONDV(j), */ /* RCONDV(j) is set to 0; this can only occur when the true */ /* value would be very small anyway. */ /* If SENSE = 'N' or 'E', RCONDV is not referenced. */ /* WORK (workspace/output) REAL array, dimension (MAX(1,LWORK)) */ /* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */ /* LWORK (input) INTEGER */ /* The dimension of the array WORK. LWORK >= MAX(1,2*N). */ /* If BALANC = 'S' or 'B', or JOBVL = 'V', or JOBVR = 'V', */ /* LWORK >= MAX(1,6*N). */ /* If SENSE = 'E', LWORK >= MAX(1,10*N). */ /* If SENSE = 'V' or 'B', LWORK >= 2*N*N+8*N+16. */ /* If LWORK = -1, then a workspace query is assumed; the routine */ /* only calculates the optimal size of the WORK array, returns */ /* this value as the first entry of the WORK array, and no error */ /* message related to LWORK is issued by XERBLA. */ /* IWORK (workspace) INTEGER array, dimension (N+6) */ /* If SENSE = 'E', IWORK is not referenced. */ /* BWORK (workspace) LOGICAL array, dimension (N) */ /* If SENSE = 'N', BWORK is not referenced. */ /* INFO (output) INTEGER */ /* = 0: successful exit */ /* < 0: if INFO = -i, the i-th argument had an illegal value. */ /* = 1,...,N: */ /* The QZ iteration failed. No eigenvectors have been */ /* calculated, but ALPHAR(j), ALPHAI(j), and BETA(j) */ /* should be correct for j=INFO+1,...,N. */ /* > N: =N+1: other than QZ iteration failed in SHGEQZ. */ /* =N+2: error return from STGEVC. */ /* Further Details */ /* =============== */ /* Balancing a matrix pair (A,B) includes, first, permuting rows and */ /* columns to isolate eigenvalues, second, applying diagonal similarity */ /* transformation to the rows and columns to make the rows and columns */ /* as close in norm as possible. The computed reciprocal condition */ /* numbers correspond to the balanced matrix. Permuting rows and columns */ /* will not change the condition numbers (in exact arithmetic) but */ /* diagonal scaling will. For further explanation of balancing, see */ /* section 4.11.1.2 of LAPACK Users' Guide. */ /* An approximate error bound on the chordal distance between the i-th */ /* computed generalized eigenvalue w and the corresponding exact */ /* eigenvalue lambda is */ /* chord(w, lambda) <= EPS * norm(ABNRM, BBNRM) / RCONDE(I) */ /* An approximate error bound for the angle between the i-th computed */ /* eigenvector VL(i) or VR(i) is given by */ /* EPS * norm(ABNRM, BBNRM) / DIF(i). */ /* For further explanation of the reciprocal condition numbers RCONDE */ /* and RCONDV, see section 4.11 of LAPACK User's Guide. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. Local Arrays .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Decode the input arguments */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; b_dim1 = *ldb; b_offset = 1 + b_dim1; b -= b_offset; --alphar; --alphai; --beta; vl_dim1 = *ldvl; vl_offset = 1 + vl_dim1; vl -= vl_offset; vr_dim1 = *ldvr; vr_offset = 1 + vr_dim1; vr -= vr_offset; --lscale; --rscale; --rconde; --rcondv; --work; --iwork; --bwork; /* Function Body */ if (lsame_(jobvl, "N")) { ijobvl = 1; ilvl = FALSE; } else if (lsame_(jobvl, "V")) { ijobvl = 2; ilvl = TRUE; } else { ijobvl = -1; ilvl = FALSE; } if (lsame_(jobvr, "N")) { ijobvr = 1; ilvr = FALSE; } else if (lsame_(jobvr, "V")) { ijobvr = 2; ilvr = TRUE; } else { ijobvr = -1; ilvr = FALSE; } ilv = ilvl || ilvr; noscl = lsame_(balanc, "N") || lsame_(balanc, "P"); wantsn = lsame_(sense, "N"); wantse = lsame_(sense, "E"); wantsv = lsame_(sense, "V"); wantsb = lsame_(sense, "B"); /* Test the input arguments */ *info = 0; lquery = *lwork == -1; if (! (noscl || lsame_(balanc, "S") || lsame_( balanc, "B"))) { *info = -1; } else if (ijobvl <= 0) { *info = -2; } else if (ijobvr <= 0) { *info = -3; } else if (! (wantsn || wantse || wantsb || wantsv)) { *info = -4; } else if (*n < 0) { *info = -5; } else if (*lda < MAX(1,*n)) { *info = -7; } else if (*ldb < MAX(1,*n)) { *info = -9; } else if (*ldvl < 1 || ilvl && *ldvl < *n) { *info = -14; } else if (*ldvr < 1 || ilvr && *ldvr < *n) { *info = -16; } /* Compute workspace */ /* (Note: Comments in the code beginning "Workspace:" describe the */ /* minimal amount of workspace needed at that point in the code, */ /* as well as the preferred amount for good performance. */ /* NB refers to the optimal block size for the immediately */ /* following subroutine, as returned by ILAENV. The workspace is */ /* computed assuming ILO = 1 and IHI = N, the worst case.) */ if (*info == 0) { if (*n == 0) { minwrk = 1; maxwrk = 1; } else { if (noscl && ! ilv) { minwrk = *n << 1; } else { minwrk = *n * 6; } if (wantse) { minwrk = *n * 10; } else if (wantsv || wantsb) { minwrk = (*n << 1) * (*n + 4) + 16; } maxwrk = minwrk; /* Computing MAX */ i__1 = maxwrk, i__2 = *n + *n * ilaenv_(&c__1, "SGEQRF", " ", n, & c__1, n, &c__0); maxwrk = MAX(i__1,i__2); /* Computing MAX */ i__1 = maxwrk, i__2 = *n + *n * ilaenv_(&c__1, "SORMQR", " ", n, & c__1, n, &c__0); maxwrk = MAX(i__1,i__2); if (ilvl) { /* Computing MAX */ i__1 = maxwrk, i__2 = *n + *n * ilaenv_(&c__1, "SORGQR", " ", n, &c__1, n, &c__0); maxwrk = MAX(i__1,i__2); } } work[1] = (float) maxwrk; if (*lwork < minwrk && ! lquery) { *info = -26; } } if (*info != 0) { i__1 = -(*info); xerbla_("SGGEVX", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*n == 0) { return 0; } /* Get machine constants */ eps = slamch_("P"); smlnum = slamch_("S"); bignum = 1.f / smlnum; slabad_(&smlnum, &bignum); smlnum = sqrt(smlnum) / eps; bignum = 1.f / smlnum; /* Scale A if max element outside range [SMLNUM,BIGNUM] */ anrm = slange_("M", n, n, &a[a_offset], lda, &work[1]); ilascl = FALSE; if (anrm > 0.f && anrm < smlnum) { anrmto = smlnum; ilascl = TRUE; } else if (anrm > bignum) { anrmto = bignum; ilascl = TRUE; } if (ilascl) { slascl_("G", &c__0, &c__0, &anrm, &anrmto, n, n, &a[a_offset], lda, & ierr); } /* Scale B if max element outside range [SMLNUM,BIGNUM] */ bnrm = slange_("M", n, n, &b[b_offset], ldb, &work[1]); ilbscl = FALSE; if (bnrm > 0.f && bnrm < smlnum) { bnrmto = smlnum; ilbscl = TRUE; } else if (bnrm > bignum) { bnrmto = bignum; ilbscl = TRUE; } if (ilbscl) { slascl_("G", &c__0, &c__0, &bnrm, &bnrmto, n, n, &b[b_offset], ldb, & ierr); } /* Permute and/or balance the matrix pair (A,B) */ /* (Workspace: need 6*N if BALANC = 'S' or 'B', 1 otherwise) */ sggbal_(balanc, n, &a[a_offset], lda, &b[b_offset], ldb, ilo, ihi, & lscale[1], &rscale[1], &work[1], &ierr); /* Compute ABNRM and BBNRM */ *abnrm = slange_("1", n, n, &a[a_offset], lda, &work[1]); if (ilascl) { work[1] = *abnrm; slascl_("G", &c__0, &c__0, &anrmto, &anrm, &c__1, &c__1, &work[1], & c__1, &ierr); *abnrm = work[1]; } *bbnrm = slange_("1", n, n, &b[b_offset], ldb, &work[1]); if (ilbscl) { work[1] = *bbnrm; slascl_("G", &c__0, &c__0, &bnrmto, &bnrm, &c__1, &c__1, &work[1], & c__1, &ierr); *bbnrm = work[1]; } /* Reduce B to triangular form (QR decomposition of B) */ /* (Workspace: need N, prefer N*NB ) */ irows = *ihi + 1 - *ilo; if (ilv || ! wantsn) { icols = *n + 1 - *ilo; } else { icols = irows; } itau = 1; iwrk = itau + irows; i__1 = *lwork + 1 - iwrk; sgeqrf_(&irows, &icols, &b[*ilo + *ilo * b_dim1], ldb, &work[itau], &work[ iwrk], &i__1, &ierr); /* Apply the orthogonal transformation to A */ /* (Workspace: need N, prefer N*NB) */ i__1 = *lwork + 1 - iwrk; sormqr_("L", "T", &irows, &icols, &irows, &b[*ilo + *ilo * b_dim1], ldb, & work[itau], &a[*ilo + *ilo * a_dim1], lda, &work[iwrk], &i__1, & ierr); /* Initialize VL and/or VR */ /* (Workspace: need N, prefer N*NB) */ if (ilvl) { slaset_("Full", n, n, &c_b57, &c_b58, &vl[vl_offset], ldvl) ; if (irows > 1) { i__1 = irows - 1; i__2 = irows - 1; slacpy_("L", &i__1, &i__2, &b[*ilo + 1 + *ilo * b_dim1], ldb, &vl[ *ilo + 1 + *ilo * vl_dim1], ldvl); } i__1 = *lwork + 1 - iwrk; sorgqr_(&irows, &irows, &irows, &vl[*ilo + *ilo * vl_dim1], ldvl, & work[itau], &work[iwrk], &i__1, &ierr); } if (ilvr) { slaset_("Full", n, n, &c_b57, &c_b58, &vr[vr_offset], ldvr) ; } /* Reduce to generalized Hessenberg form */ /* (Workspace: none needed) */ if (ilv || ! wantsn) { /* Eigenvectors requested -- work on whole matrix. */ sgghrd_(jobvl, jobvr, n, ilo, ihi, &a[a_offset], lda, &b[b_offset], ldb, &vl[vl_offset], ldvl, &vr[vr_offset], ldvr, &ierr); } else { sgghrd_("N", "N", &irows, &c__1, &irows, &a[*ilo + *ilo * a_dim1], lda, &b[*ilo + *ilo * b_dim1], ldb, &vl[vl_offset], ldvl, &vr[ vr_offset], ldvr, &ierr); } /* Perform QZ algorithm (Compute eigenvalues, and optionally, the */ /* Schur forms and Schur vectors) */ /* (Workspace: need N) */ if (ilv || ! wantsn) { *(unsigned char *)chtemp = 'S'; } else { *(unsigned char *)chtemp = 'E'; } shgeqz_(chtemp, jobvl, jobvr, n, ilo, ihi, &a[a_offset], lda, &b[b_offset] , ldb, &alphar[1], &alphai[1], &beta[1], &vl[vl_offset], ldvl, & vr[vr_offset], ldvr, &work[1], lwork, &ierr); if (ierr != 0) { if (ierr > 0 && ierr <= *n) { *info = ierr; } else if (ierr > *n && ierr <= *n << 1) { *info = ierr - *n; } else { *info = *n + 1; } goto L130; } /* Compute Eigenvectors and estimate condition numbers if desired */ /* (Workspace: STGEVC: need 6*N */ /* STGSNA: need 2*N*(N+2)+16 if SENSE = 'V' or 'B', */ /* need N otherwise ) */ if (ilv || ! wantsn) { if (ilv) { if (ilvl) { if (ilvr) { *(unsigned char *)chtemp = 'B'; } else { *(unsigned char *)chtemp = 'L'; } } else { *(unsigned char *)chtemp = 'R'; } stgevc_(chtemp, "B", ldumma, n, &a[a_offset], lda, &b[b_offset], ldb, &vl[vl_offset], ldvl, &vr[vr_offset], ldvr, n, &in, & work[1], &ierr); if (ierr != 0) { *info = *n + 2; goto L130; } } if (! wantsn) { /* compute eigenvectors (STGEVC) and estimate condition */ /* numbers (STGSNA). Note that the definition of the condition */ /* number is not invariant under transformation (u,v) to */ /* (Q*u, Z*v), where (u,v) are eigenvectors of the generalized */ /* Schur form (S,T), Q and Z are orthogonal matrices. In order */ /* to avoid using extra 2*N*N workspace, we have to recalculate */ /* eigenvectors and estimate one condition numbers at a time. */ pair = FALSE; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (pair) { pair = FALSE; goto L20; } mm = 1; if (i__ < *n) { if (a[i__ + 1 + i__ * a_dim1] != 0.f) { pair = TRUE; mm = 2; } } i__2 = *n; for (j = 1; j <= i__2; ++j) { bwork[j] = FALSE; /* L10: */ } if (mm == 1) { bwork[i__] = TRUE; } else if (mm == 2) { bwork[i__] = TRUE; bwork[i__ + 1] = TRUE; } iwrk = mm * *n + 1; iwrk1 = iwrk + mm * *n; /* Compute a pair of left and right eigenvectors. */ /* (compute workspace: need up to 4*N + 6*N) */ if (wantse || wantsb) { stgevc_("B", "S", &bwork[1], n, &a[a_offset], lda, &b[ b_offset], ldb, &work[1], n, &work[iwrk], n, &mm, &m, &work[iwrk1], &ierr); if (ierr != 0) { *info = *n + 2; goto L130; } } i__2 = *lwork - iwrk1 + 1; stgsna_(sense, "S", &bwork[1], n, &a[a_offset], lda, &b[ b_offset], ldb, &work[1], n, &work[iwrk], n, &rconde[ i__], &rcondv[i__], &mm, &m, &work[iwrk1], &i__2, & iwork[1], &ierr); L20: ; } } } /* Undo balancing on VL and VR and normalization */ /* (Workspace: none needed) */ if (ilvl) { sggbak_(balanc, "L", n, ilo, ihi, &lscale[1], &rscale[1], n, &vl[ vl_offset], ldvl, &ierr); i__1 = *n; for (jc = 1; jc <= i__1; ++jc) { if (alphai[jc] < 0.f) { goto L70; } temp = 0.f; if (alphai[jc] == 0.f) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ r__2 = temp, r__3 = (r__1 = vl[jr + jc * vl_dim1], ABS( r__1)); temp = MAX(r__2,r__3); /* L30: */ } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ r__3 = temp, r__4 = (r__1 = vl[jr + jc * vl_dim1], ABS( r__1)) + (r__2 = vl[jr + (jc + 1) * vl_dim1], ABS(r__2)); temp = MAX(r__3,r__4); /* L40: */ } } if (temp < smlnum) { goto L70; } temp = 1.f / temp; if (alphai[jc] == 0.f) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { vl[jr + jc * vl_dim1] *= temp; /* L50: */ } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { vl[jr + jc * vl_dim1] *= temp; vl[jr + (jc + 1) * vl_dim1] *= temp; /* L60: */ } } L70: ; } } if (ilvr) { sggbak_(balanc, "R", n, ilo, ihi, &lscale[1], &rscale[1], n, &vr[ vr_offset], ldvr, &ierr); i__1 = *n; for (jc = 1; jc <= i__1; ++jc) { if (alphai[jc] < 0.f) { goto L120; } temp = 0.f; if (alphai[jc] == 0.f) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ r__2 = temp, r__3 = (r__1 = vr[jr + jc * vr_dim1], ABS( r__1)); temp = MAX(r__2,r__3); /* L80: */ } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ r__3 = temp, r__4 = (r__1 = vr[jr + jc * vr_dim1], ABS( r__1)) + (r__2 = vr[jr + (jc + 1) * vr_dim1], ABS(r__2)); temp = MAX(r__3,r__4); /* L90: */ } } if (temp < smlnum) { goto L120; } temp = 1.f / temp; if (alphai[jc] == 0.f) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { vr[jr + jc * vr_dim1] *= temp; /* L100: */ } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { vr[jr + jc * vr_dim1] *= temp; vr[jr + (jc + 1) * vr_dim1] *= temp; /* L110: */ } } L120: ; } } /* Undo scaling if necessary */ if (ilascl) { slascl_("G", &c__0, &c__0, &anrmto, &anrm, n, &c__1, &alphar[1], n, & ierr); slascl_("G", &c__0, &c__0, &anrmto, &anrm, n, &c__1, &alphai[1], n, & ierr); } if (ilbscl) { slascl_("G", &c__0, &c__0, &bnrmto, &bnrm, n, &c__1, &beta[1], n, & ierr); } L130: work[1] = (float) maxwrk; return 0; /* End of SGGEVX */ } /* sggevx_ */
/* Subroutine */ int sgglse_(integer *m, integer *n, integer *p, real *a, integer *lda, real *b, integer *ldb, real *c__, real *d__, real *x, real *work, integer *lwork, integer *info) { /* -- LAPACK driver 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 ======= SGGLSE solves the linear equality-constrained least squares (LSE) problem: minimize || c - A*x ||_2 subject to B*x = d where A is an M-by-N matrix, B is a P-by-N matrix, c is a given M-vector, and d is a given P-vector. It is assumed that P <= N <= M+P, and rank(B) = P and rank( ( A ) ) = N. ( ( B ) ) These conditions ensure that the LSE problem has a unique solution, which is obtained using a GRQ factorization of the matrices B and A. Arguments ========= M (input) INTEGER The number of rows of the matrix A. M >= 0. N (input) INTEGER The number of columns of the matrices A and B. N >= 0. P (input) INTEGER The number of rows of the matrix B. 0 <= P <= N <= M+P. A (input/output) REAL array, dimension (LDA,N) On entry, the M-by-N matrix A. On exit, A is destroyed. LDA (input) INTEGER The leading dimension of the array A. LDA >= max(1,M). B (input/output) REAL array, dimension (LDB,N) On entry, the P-by-N matrix B. On exit, B is destroyed. LDB (input) INTEGER The leading dimension of the array B. LDB >= max(1,P). C (input/output) REAL array, dimension (M) On entry, C contains the right hand side vector for the least squares part of the LSE problem. On exit, the residual sum of squares for the solution is given by the sum of squares of elements N-P+1 to M of vector C. D (input/output) REAL array, dimension (P) On entry, D contains the right hand side vector for the constrained equation. On exit, D is destroyed. X (output) REAL array, dimension (N) On exit, X is the solution of the LSE problem. WORK (workspace/output) REAL array, dimension (LWORK) On exit, if INFO = 0, WORK(1) returns the optimal LWORK. LWORK (input) INTEGER The dimension of the array WORK. LWORK >= max(1,M+N+P). For optimum performance LWORK >= P+min(M,N)+max(M,N)*NB, where NB is an upper bound for the optimal blocksizes for SGEQRF, SGERQF, SORMQR and SORMRQ. If LWORK = -1, then a workspace query is assumed; the routine only calculates the optimal size of the WORK array, returns this value as the first entry of the WORK array, and no error message related to LWORK is issued by XERBLA. INFO (output) INTEGER = 0: successful exit. < 0: if INFO = -i, the i-th argument had an illegal value. ===================================================================== Test the input parameters Parameter adjustments */ /* Table of constant values */ static integer c__1 = 1; static integer c_n1 = -1; static real c_b29 = -1.f; static real c_b31 = 1.f; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, i__1, i__2; /* Local variables */ static integer lopt; extern /* Subroutine */ int sgemv_(char *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *), scopy_(integer *, real *, integer *, real *, integer *), saxpy_(integer *, real *, real *, integer *, real *, integer *), strmv_(char *, char *, char *, integer *, real *, integer *, real *, integer *), strsv_(char *, char *, char *, integer *, real *, integer *, real *, integer *); static integer nb, mn, nr; extern /* Subroutine */ int xerbla_(char *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *, ftnlen, ftnlen); extern /* Subroutine */ int sggrqf_(integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, real *, integer * , integer *); static integer nb1, nb2, nb3, nb4, lwkopt; static logical lquery; extern /* Subroutine */ int sormqr_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *), sormrq_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real * , integer *, real *, integer *, integer *); #define a_ref(a_1,a_2) a[(a_2)*a_dim1 + a_1] #define b_ref(a_1,a_2) b[(a_2)*b_dim1 + a_1] a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; b_dim1 = *ldb; b_offset = 1 + b_dim1 * 1; b -= b_offset; --c__; --d__; --x; --work; /* Function Body */ *info = 0; mn = min(*m,*n); nb1 = ilaenv_(&c__1, "SGEQRF", " ", m, n, &c_n1, &c_n1, (ftnlen)6, ( ftnlen)1); nb2 = ilaenv_(&c__1, "SGERQF", " ", m, n, &c_n1, &c_n1, (ftnlen)6, ( ftnlen)1); nb3 = ilaenv_(&c__1, "SORMQR", " ", m, n, p, &c_n1, (ftnlen)6, (ftnlen)1); nb4 = ilaenv_(&c__1, "SORMRQ", " ", m, n, p, &c_n1, (ftnlen)6, (ftnlen)1); /* Computing MAX */ i__1 = max(nb1,nb2), i__1 = max(i__1,nb3); nb = max(i__1,nb4); lwkopt = *p + mn + max(*m,*n) * nb; work[1] = (real) lwkopt; lquery = *lwork == -1; if (*m < 0) { *info = -1; } else if (*n < 0) { *info = -2; } else if (*p < 0 || *p > *n || *p < *n - *m) { *info = -3; } else if (*lda < max(1,*m)) { *info = -5; } else if (*ldb < max(1,*p)) { *info = -7; } else /* if(complicated condition) */ { /* Computing MAX */ i__1 = 1, i__2 = *m + *n + *p; if (*lwork < max(i__1,i__2) && ! lquery) { *info = -12; } } if (*info != 0) { i__1 = -(*info); xerbla_("SGGLSE", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*n == 0) { return 0; } /* Compute the GRQ factorization of matrices B and A: B*Q' = ( 0 T12 ) P Z'*A*Q' = ( R11 R12 ) N-P N-P P ( 0 R22 ) M+P-N N-P P where T12 and R11 are upper triangular, and Q and Z are orthogonal. */ i__1 = *lwork - *p - mn; sggrqf_(p, m, n, &b[b_offset], ldb, &work[1], &a[a_offset], lda, &work[*p + 1], &work[*p + mn + 1], &i__1, info); lopt = work[*p + mn + 1]; /* Update c = Z'*c = ( c1 ) N-P ( c2 ) M+P-N */ i__1 = max(1,*m); i__2 = *lwork - *p - mn; sormqr_("Left", "Transpose", m, &c__1, &mn, &a[a_offset], lda, &work[*p + 1], &c__[1], &i__1, &work[*p + mn + 1], &i__2, info); /* Computing MAX */ i__1 = lopt, i__2 = (integer) work[*p + mn + 1]; lopt = max(i__1,i__2); /* Solve T12*x2 = d for x2 */ strsv_("Upper", "No transpose", "Non unit", p, &b_ref(1, *n - *p + 1), ldb, &d__[1], &c__1); /* Update c1 */ i__1 = *n - *p; sgemv_("No transpose", &i__1, p, &c_b29, &a_ref(1, *n - *p + 1), lda, & d__[1], &c__1, &c_b31, &c__[1], &c__1); /* Sovle R11*x1 = c1 for x1 */ i__1 = *n - *p; strsv_("Upper", "No transpose", "Non unit", &i__1, &a[a_offset], lda, & c__[1], &c__1); /* Put the solutions in X */ i__1 = *n - *p; scopy_(&i__1, &c__[1], &c__1, &x[1], &c__1); scopy_(p, &d__[1], &c__1, &x[*n - *p + 1], &c__1); /* Compute the residual vector: */ if (*m < *n) { nr = *m + *p - *n; i__1 = *n - *m; sgemv_("No transpose", &nr, &i__1, &c_b29, &a_ref(*n - *p + 1, *m + 1) , lda, &d__[nr + 1], &c__1, &c_b31, &c__[*n - *p + 1], &c__1); } else { nr = *p; } strmv_("Upper", "No transpose", "Non unit", &nr, &a_ref(*n - *p + 1, *n - *p + 1), lda, &d__[1], &c__1); saxpy_(&nr, &c_b29, &d__[1], &c__1, &c__[*n - *p + 1], &c__1); /* Backward transformation x = Q'*x */ i__1 = *lwork - *p - mn; sormrq_("Left", "Transpose", n, &c__1, p, &b[b_offset], ldb, &work[1], &x[ 1], n, &work[*p + mn + 1], &i__1, info); /* Computing MAX */ i__1 = lopt, i__2 = (integer) work[*p + mn + 1]; work[1] = (real) (*p + mn + max(i__1,i__2)); return 0; /* End of SGGLSE */ } /* sgglse_ */
/* Subroutine */ int sormhr_(char *side, char *trans, integer *m, integer *n, integer *ilo, integer *ihi, real *a, integer *lda, real *tau, real * c__, integer *ldc, real *work, integer *lwork, integer *info, ftnlen side_len, ftnlen trans_len) { /* System generated locals */ address a__1[2]; integer a_dim1, a_offset, c_dim1, c_offset, i__1[2], i__2; char ch__1[2]; /* Builtin functions */ /* Subroutine */ int s_cat(char *, char **, integer *, integer *, ftnlen); /* Local variables */ static integer i1, i2, nb, mi, nh, ni, nq, nw; static logical left; extern logical lsame_(char *, char *, ftnlen, ftnlen); static integer iinfo; extern /* Subroutine */ int xerbla_(char *, integer *, ftnlen); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *, ftnlen, ftnlen); static integer lwkopt; static logical lquery; extern /* Subroutine */ int sormqr_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *, ftnlen, ftnlen); /* -- 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 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SORMHR overwrites the general real M-by-N matrix C with */ /* SIDE = 'L' SIDE = 'R' */ /* TRANS = 'N': Q * C C * Q */ /* TRANS = 'T': Q**T * C C * Q**T */ /* where Q is a real orthogonal matrix of order nq, with nq = m if */ /* SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of */ /* IHI-ILO elementary reflectors, as returned by SGEHRD: */ /* Q = H(ilo) H(ilo+1) . . . H(ihi-1). */ /* Arguments */ /* ========= */ /* SIDE (input) CHARACTER*1 */ /* = 'L': apply Q or Q**T from the Left; */ /* = 'R': apply Q or Q**T from the Right. */ /* TRANS (input) CHARACTER*1 */ /* = 'N': No transpose, apply Q; */ /* = 'T': Transpose, apply Q**T. */ /* M (input) INTEGER */ /* The number of rows of the matrix C. M >= 0. */ /* N (input) INTEGER */ /* The number of columns of the matrix C. N >= 0. */ /* ILO (input) INTEGER */ /* IHI (input) INTEGER */ /* ILO and IHI must have the same values as in the previous call */ /* of SGEHRD. Q is equal to the unit matrix except in the */ /* submatrix Q(ilo+1:ihi,ilo+1:ihi). */ /* If SIDE = 'L', then 1 <= ILO <= IHI <= M, if M > 0, and */ /* ILO = 1 and IHI = 0, if M = 0; */ /* if SIDE = 'R', then 1 <= ILO <= IHI <= N, if N > 0, and */ /* ILO = 1 and IHI = 0, if N = 0. */ /* A (input) REAL array, dimension */ /* (LDA,M) if SIDE = 'L' */ /* (LDA,N) if SIDE = 'R' */ /* The vectors which define the elementary reflectors, as */ /* returned by SGEHRD. */ /* LDA (input) INTEGER */ /* The leading dimension of the array A. */ /* LDA >= max(1,M) if SIDE = 'L'; LDA >= max(1,N) if SIDE = 'R'. */ /* TAU (input) REAL array, dimension */ /* (M-1) if SIDE = 'L' */ /* (N-1) if SIDE = 'R' */ /* TAU(i) must contain the scalar factor of the elementary */ /* reflector H(i), as returned by SGEHRD. */ /* C (input/output) REAL array, dimension (LDC,N) */ /* On entry, the M-by-N matrix C. */ /* On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. */ /* LDC (input) INTEGER */ /* The leading dimension of the array C. LDC >= max(1,M). */ /* WORK (workspace/output) REAL array, dimension (LWORK) */ /* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */ /* LWORK (input) INTEGER */ /* The dimension of the array WORK. */ /* If SIDE = 'L', LWORK >= max(1,N); */ /* if SIDE = 'R', LWORK >= max(1,M). */ /* For optimum performance LWORK >= N*NB if SIDE = 'L', and */ /* LWORK >= M*NB if SIDE = 'R', where NB is the optimal */ /* blocksize. */ /* If LWORK = -1, then a workspace query is assumed; the routine */ /* only calculates the optimal size of the WORK array, returns */ /* this value as the first entry of the WORK array, and no error */ /* message related to LWORK is issued by XERBLA. */ /* INFO (output) INTEGER */ /* = 0: successful exit */ /* < 0: if INFO = -i, the i-th argument had an illegal value */ /* ===================================================================== */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input arguments */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; --tau; c_dim1 = *ldc; c_offset = 1 + c_dim1; c__ -= c_offset; --work; /* Function Body */ *info = 0; nh = *ihi - *ilo; left = lsame_(side, "L", (ftnlen)1, (ftnlen)1); lquery = *lwork == -1; /* NQ is the order of Q and NW is the minimum dimension of WORK */ if (left) { nq = *m; nw = *n; } else { nq = *n; nw = *m; } if (! left && ! lsame_(side, "R", (ftnlen)1, (ftnlen)1)) { *info = -1; } else if (! lsame_(trans, "N", (ftnlen)1, (ftnlen)1) && ! lsame_(trans, "T", (ftnlen)1, (ftnlen)1)) { *info = -2; } else if (*m < 0) { *info = -3; } else if (*n < 0) { *info = -4; } else if (*ilo < 1 || *ilo > max(1,nq)) { *info = -5; } else if (*ihi < min(*ilo,nq) || *ihi > nq) { *info = -6; } else if (*lda < max(1,nq)) { *info = -8; } else if (*ldc < max(1,*m)) { *info = -11; } else if (*lwork < max(1,nw) && ! lquery) { *info = -13; } if (*info == 0) { if (left) { /* Writing concatenation */ i__1[0] = 1, a__1[0] = side; i__1[1] = 1, a__1[1] = trans; s_cat(ch__1, a__1, i__1, &c__2, (ftnlen)2); nb = ilaenv_(&c__1, "SORMQR", ch__1, &nh, n, &nh, &c_n1, (ftnlen) 6, (ftnlen)2); } else { /* Writing concatenation */ i__1[0] = 1, a__1[0] = side; i__1[1] = 1, a__1[1] = trans; s_cat(ch__1, a__1, i__1, &c__2, (ftnlen)2); nb = ilaenv_(&c__1, "SORMQR", ch__1, m, &nh, &nh, &c_n1, (ftnlen) 6, (ftnlen)2); } lwkopt = max(1,nw) * nb; work[1] = (real) lwkopt; } if (*info != 0) { i__2 = -(*info); xerbla_("SORMHR", &i__2, (ftnlen)6); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*m == 0 || *n == 0 || nh == 0) { work[1] = 1.f; return 0; } if (left) { mi = nh; ni = *n; i1 = *ilo + 1; i2 = 1; } else { mi = *m; ni = nh; i1 = 1; i2 = *ilo + 1; } sormqr_(side, trans, &mi, &ni, &nh, &a[*ilo + 1 + *ilo * a_dim1], lda, & tau[*ilo], &c__[i1 + i2 * c_dim1], ldc, &work[1], lwork, &iinfo, ( ftnlen)1, (ftnlen)1); work[1] = (real) lwkopt; return 0; /* End of SORMHR */ } /* sormhr_ */