DLLEXPORT MKL_INT d_qr_factor(MKL_INT m, MKL_INT n, double r[], double tau[], double q[], double work[], MKL_INT len) { MKL_INT info = 0; dgeqrf_(&m, &n, r, &m, tau, work, &len, &info); for (MKL_INT i = 0; i < m; ++i) { for (MKL_INT j = 0; j < m && j < n; ++j) { if (i > j) { q[j * m + i] = r[j * m + i]; } } } //compute the q elements explicitly if (m <= n) { dorgqr_(&m, &m, &m, q, &m, tau, work, &len, &info); } else { dorgqr_(&m, &n, &n, q, &m, tau, work, &len, &info); } return info; }
void matrix_dorgqr(matrix_type * A , double * tau, int num_reflectors) { /* num_reflectors == length of tau. */ int lda = matrix_get_column_stride( A ); int m = matrix_get_rows( A ); int n = matrix_get_columns( A ); double * work = util_malloc(sizeof * work ); int worksize; int info; /* Determine optimal worksize. */ worksize = -1; dorgqr_(&m , &n , &num_reflectors , matrix_get_data( A ), &lda , tau , work , &worksize , &info); if (info != 0) util_abort("%s: dorgqf routine failed with info:%d \n",__func__ , info); worksize = ( int ) work[0]; { double * tmp = realloc(work , sizeof * work * worksize ); if (tmp == NULL) { /* OK - we could not get the optimal worksize, try again with the minimum. */ worksize = n; work = util_realloc(work , sizeof * work * worksize ); } else work = tmp; /* The request for optimal worksize succeeded */ } /* Second call - do the actual computation. */ dorgqr_(&m , &n , &num_reflectors , matrix_get_data( A ), &lda , tau , work , &worksize , &info); if (info != 0) util_abort("%s: dorqf routine failed with info:%d \n",__func__ , info); free( work ); }
bool qr(const mat &A, mat &Q, mat &R, bmat &P) { int info; int m = A.rows(); int n = A.cols(); int lwork = n; int k = std::min(m, n); vec tau(k); vec work(lwork); ivec jpvt(n); jpvt.zeros(); R = A; // perform workspace query for optimum lwork value int lwork_tmp = -1; dgeqp3_(&m, &n, R._data(), &m, jpvt._data(), tau._data(), work._data(), &lwork_tmp, &info); if (info == 0) { lwork = static_cast<int>(work(0)); work.set_size(lwork, false); } dgeqp3_(&m, &n, R._data(), &m, jpvt._data(), tau._data(), work._data(), &lwork, &info); Q = R; Q.set_size(m, m, true); // construct permutation matrix P = zeros_b(n, n); for (int j = 0; j < n; j++) P(jpvt(j) - 1, j) = 1; // construct R for (int i = 0; i < m; i++) for (int j = 0; j < std::min(i, n); j++) R(i, j) = 0; // perform workspace query for optimum lwork value lwork_tmp = -1; dorgqr_(&m, &m, &k, Q._data(), &m, tau._data(), work._data(), &lwork_tmp, &info); if (info == 0) { lwork = static_cast<int>(work(0)); work.set_size(lwork, false); } dorgqr_(&m, &m, &k, Q._data(), &m, tau._data(), work._data(), &lwork, &info); return (info == 0); }
void Stiefel::ObtainPerp(Variable *x) const { const double *xM = x->ObtainReadData(); SharedSpace *SharedSpacePerp = new SharedSpace(2, n, n - p); double *Perp = SharedSpacePerp->ObtainWriteEntireData(); for (integer i = 0; i < n * (n - p); i++) Perp[i] = genrand_gaussian(); double *temp = new double[p * (n - p)]; char *transn = const_cast<char *> ("n"), *transt = const_cast<char *> ("t"); double one = 1, zero = 0, neg_one = -1; integer P = p, N = n, NmP = n - p; // temp = X^T * Perp dgemm_(transt, transn, &P, &NmP, &N, &one, const_cast<double *> (xM), &N, Perp, &N, &zero, temp, &P); // Perp = Perp - X * temp dgemm_(transn, transn, &N, &NmP, &P, &neg_one, const_cast<double *> (xM), &N, temp, &P, &one, Perp, &N); delete[] temp; integer *jpvt = new integer[NmP]; integer lwork = 2 * NmP + (1 + NmP) * INITIALBLOCKSIZE, info; double *tau = new double[NmP + lwork]; double *work = tau + NmP; for (integer i = 0; i < NmP; i++) jpvt[i] = 0; dgeqp3_(&N, &NmP, Perp, &N, jpvt, tau, work, &lwork, &info); if (info < 0) Rcpp::Rcout << "Error in qr decomposition!" << std::endl; dorgqr_(&N, &NmP, &NmP, Perp, &N, tau, work, &lwork, &info); if (info < 0) Rcpp::Rcout << "Error in forming Q matrix!" << std::endl; delete[] jpvt; delete[] tau; x->AddToTempData("Perp", SharedSpacePerp); };
static void qr_factorize(mat m, mat q, mat r) { int i,j; double* a = (double*) malloc(sizeof(double)*m->r*m->c); double* tau = (double*) malloc(sizeof(double)*m->c); double* work; double workopt; int lda = m->r; int lwork = -1; int info; int loc; loc = 0; for(j = 0; j < m->c; j++) { for(i = 0; i < m->r; i++) { a[loc++] = m->m[mindex(i,j,m)]; } } /*QR decomposition into a compact format*/ dgeqrf_(&m->r, &m->c, a, &lda, tau, &workopt, &lwork, &info); lwork = (int) workopt; work = (double*) malloc(sizeof(double)*lwork); dgeqrf_(&m->r, &m->c, a, &lda, tau, work, &lwork, &info); for(i = 0; i < m->c; i++) { for(j = i; j < m->c; j++) { r->m[mindex(i,j,r)] = a[i+j*lda]; a[i+j*lda] = (i == j) ? 1 : 0; } } lwork = -1; dorgqr_(&m->r, &m->c, &m->c, a, &lda, tau, &workopt, &lwork, &info); lwork = (int) workopt; work = (double*) realloc(work, sizeof(double)*lwork); dorgqr_(&m->r, &m->c, &m->c, a, &lda, tau, work, &lwork, &info); for(i = 0; i < q->r; i++) { for(j = 0; j < q->c; j++) { q->m[mindex(i,j,q)] = a[i+j*lda]; } } free(work); free(a); free(tau); }
/* Build Q from output of geqrf */ void THLapack_(orgqr)(int m, int n, int k, real *a, int lda, real *tau, real *work, int lwork, int *info) { #ifdef USE_LAPACK #if defined(TH_REAL_IS_DOUBLE) dorgqr_(&m, &n, &k, a, &lda, tau, work, &lwork, info); #else sorgqr_(&m, &n, &k, a, &lda, tau, work, &lwork, info); #endif #else THError("orgqr: Lapack library not found in compile time\n"); #endif }
/* ------------------------------------------------------------------ */ void mim_ip_span_nullspace(int nf, int nconn, int d, double *C, double *A, double *X, double *work, int nwork) /* ------------------------------------------------------------------ */ { MAT_SIZE_T m, n, k, ldC, ldX, info, lwork; int i, j; double a1, a2; double tau[3] = { 0.0 }; /* No more than 3 spatial dimensions */ /* Step 1) X(1:nf, 1:nf) <- I_{nf} */ for (j = 0; j < nf; j++) { for (i = 0; i < nf; i++) { X[i + j*nconn] = 0.0; } X[j * (nconn + 1)] = 1.0; } /* Step 2) C <- orth(A * C) */ for (j = 0; j < d; j++) { for (i = 0; i < nf; i++) { C[i + j*nf] *= A[i]; } } m = nf; n = d; ldC = nf; k = d; lwork = nwork; dgeqrf_(&m, &n, C, &ldC, tau, work, &lwork, &info); dorgqr_(&m, &n, &k, C, &ldC, tau, work, &lwork, &info); /* Step 3) X <- A * (X - C*C') * A */ ldX = nconn; a1 = -1.0; a2 = 1.0; dsyrk_("Upper Triangular", "No Transpose", &m, &n, &a1, C, &ldC, &a2, X, &ldX); for (j = 0; j < nf; j++) { for (i = 0; i <= j; i++) { X[i + j*nconn] *= A[i] * A[j]; } } /* Account for DSYRK only assigning upper triangular part. */ for (j = 0; j < nf; j++) { for (i = j + 1; i < nf; i++) { X[i + j*nconn] = X[j + i*nconn]; } } }
/****************************************************************************************** * * Extract Q factor of stored in terms of elementary reflectors in A, uses LAPACK * ******************************************************************************************/ void mtx_QR_extractQ( Tmtx_ptr A ) { int lwork, info; double *work; lwork = 64*(A->ncols+1); work = (double*)calloc( lwork, sizeof(double) ); // find QR decomp of block, storing in the block dorgqr_( &A->nrows, &A->ncols, &A->ncols, A->dat, &A->nrows, A->tau, work, &lwork, &info ); free( work ); }
void compute_qr_q(full_matrix *mat, qr_scratch *qr) { int m; int n; int info; m = mat->m; n = mat->n; dgeqrf_(&m, &n, mat->val, &m, qr->tau, qr->work, &(qr->lwork), &info); dorgqr_(&m, &n, &n, mat->val, &m, qr->tau, qr->work, &(qr->lwork), &info); }
DLLEXPORT MKL_INT d_qr_thin_factor(MKL_INT m, MKL_INT n, double q[], double tau[], double r[], double work[], MKL_INT len) { MKL_INT info = 0; dgeqrf_(&m, &n, q, &m, tau, work, &len, &info); for (MKL_INT i = 0; i < n; ++i) { for (MKL_INT j = 0; j < n; ++j) { if( i <= j) { r[j * n + i] = q[j * m + i]; } } } dorgqr_(&m, &n, &n, q, &m, tau, work, &len, &info); return info; }
/* Subroutine */ int dggev_(char *jobvl, char *jobvr, integer *n, doublereal * a, integer *lda, doublereal *b, integer *ldb, doublereal *alphar, doublereal *alphai, doublereal *beta, doublereal *vl, integer *ldvl, doublereal *vr, integer *ldvr, doublereal *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 ======= DGGEV 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) DOUBLE PRECISION 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) DOUBLE PRECISION 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) DOUBLE PRECISION array, dimension (N) ALPHAI (output) DOUBLE PRECISION array, dimension (N) BETA (output) DOUBLE PRECISION 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) DOUBLE PRECISION 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) DOUBLE PRECISION 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) DOUBLE PRECISION 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 DHGEQZ. =N+2: error return from DTGEVC. ===================================================================== Decode the input arguments Parameter adjustments */ /* Table of constant values */ static integer c__1 = 1; static integer c__0 = 0; static doublereal c_b26 = 0.; static doublereal c_b27 = 1.; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, vl_dim1, vl_offset, vr_dim1, vr_offset, i__1, i__2; doublereal d__1, d__2, d__3, d__4; /* Builtin functions */ double sqrt(doublereal); /* Local variables */ static doublereal anrm, bnrm; static integer ierr, itau; static doublereal temp; static logical ilvl, ilvr; static integer iwrk; extern logical lsame_(char *, char *); static integer ileft, icols, irows; extern /* Subroutine */ int dlabad_(doublereal *, doublereal *); static integer jc; extern /* Subroutine */ int dggbak_(char *, char *, integer *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, integer *), dggbal_(char *, integer *, doublereal *, integer *, doublereal *, integer *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *); static integer in; extern doublereal dlamch_(char *), dlange_(char *, integer *, integer *, doublereal *, integer *, doublereal *); static integer jr; extern /* Subroutine */ int dgghrd_(char *, char *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, integer *), dlascl_(char *, integer *, integer *, doublereal *, doublereal *, integer *, integer *, doublereal *, integer *, integer *); static logical ilascl, ilbscl; extern /* Subroutine */ int dgeqrf_(integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *), dlacpy_(char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *), dlaset_(char *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *), dtgevc_(char *, char *, logical *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, integer *, integer *, doublereal *, integer *); static logical ldumma[1]; static char chtemp[1]; static doublereal bignum; extern /* Subroutine */ int dhgeqz_(char *, char *, char *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, integer *), xerbla_(char *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *, ftnlen, ftnlen); static integer ijobvl, iright, ijobvr; extern /* Subroutine */ int dorgqr_(integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *); static doublereal anrmto, bnrmto; extern /* Subroutine */ int dormqr_(char *, char *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, integer *); static integer minwrk, maxwrk; static doublereal smlnum; static logical lquery; static integer ihi, ilo; static doublereal 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, "DGEQRF", " ", 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] = (doublereal) maxwrk; } if (*lwork < minwrk && ! lquery) { *info = -16; } if (*info != 0) { i__1 = -(*info); xerbla_("DGGEV ", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*n == 0) { return 0; } /* Get machine constants */ eps = dlamch_("P"); smlnum = dlamch_("S"); bignum = 1. / smlnum; dlabad_(&smlnum, &bignum); smlnum = sqrt(smlnum) / eps; bignum = 1. / smlnum; /* Scale A if max element outside range [SMLNUM,BIGNUM] */ anrm = dlange_("M", n, n, &a[a_offset], lda, &work[1]); ilascl = FALSE_; if (anrm > 0. && anrm < smlnum) { anrmto = smlnum; ilascl = TRUE_; } else if (anrm > bignum) { anrmto = bignum; ilascl = TRUE_; } if (ilascl) { dlascl_("G", &c__0, &c__0, &anrm, &anrmto, n, n, &a[a_offset], lda, & ierr); } /* Scale B if max element outside range [SMLNUM,BIGNUM] */ bnrm = dlange_("M", n, n, &b[b_offset], ldb, &work[1]); ilbscl = FALSE_; if (bnrm > 0. && bnrm < smlnum) { bnrmto = smlnum; ilbscl = TRUE_; } else if (bnrm > bignum) { bnrmto = bignum; ilbscl = TRUE_; } if (ilbscl) { dlascl_("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; dggbal_("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; dgeqrf_(&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; dormqr_("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) { dlaset_("Full", n, n, &c_b26, &c_b27, &vl[vl_offset], ldvl) ; i__1 = irows - 1; i__2 = irows - 1; dlacpy_("L", &i__1, &i__2, &b_ref(ilo + 1, ilo), ldb, &vl_ref(ilo + 1, ilo), ldvl); i__1 = *lwork + 1 - iwrk; dorgqr_(&irows, &irows, &irows, &vl_ref(ilo, ilo), ldvl, &work[itau], &work[iwrk], &i__1, &ierr); } /* Initialize VR */ if (ilvr) { dlaset_("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. */ dgghrd_(jobvl, jobvr, n, &ilo, &ihi, &a[a_offset], lda, &b[b_offset], ldb, &vl[vl_offset], ldvl, &vr[vr_offset], ldvr, &ierr); } else { dgghrd_("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; dhgeqz_(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'; } dtgevc_(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) { dggbak_("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.) { goto L50; } temp = 0.; if (alphai[jc] == 0.) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ d__2 = temp, d__3 = (d__1 = vl_ref(jr, jc), abs(d__1)) ; temp = max(d__2,d__3); /* L10: */ } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ d__3 = temp, d__4 = (d__1 = vl_ref(jr, jc), abs(d__1)) + (d__2 = vl_ref(jr, jc + 1), abs(d__2)); temp = max(d__3,d__4); /* L20: */ } } if (temp < smlnum) { goto L50; } temp = 1. / temp; if (alphai[jc] == 0.) { 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) { dggbak_("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.) { goto L100; } temp = 0.; if (alphai[jc] == 0.) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ d__2 = temp, d__3 = (d__1 = vr_ref(jr, jc), abs(d__1)) ; temp = max(d__2,d__3); /* L60: */ } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ d__3 = temp, d__4 = (d__1 = vr_ref(jr, jc), abs(d__1)) + (d__2 = vr_ref(jr, jc + 1), abs(d__2)); temp = max(d__3,d__4); /* L70: */ } } if (temp < smlnum) { goto L100; } temp = 1. / temp; if (alphai[jc] == 0.) { 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) { dlascl_("G", &c__0, &c__0, &anrmto, &anrm, n, &c__1, &alphar[1], n, & ierr); dlascl_("G", &c__0, &c__0, &anrmto, &anrm, n, &c__1, &alphai[1], n, & ierr); } if (ilbscl) { dlascl_("G", &c__0, &c__0, &bnrmto, &bnrm, n, &c__1, &beta[1], n, & ierr); } L110: work[1] = (doublereal) maxwrk; return 0; /* End of DGGEV */ } /* dggev_ */
/* Subroutine */ int dggevx_(char *balanc, char *jobvl, char *jobvr, char * sense, integer *n, doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *alphar, doublereal *alphai, doublereal * beta, doublereal *vl, integer *ldvl, doublereal *vr, integer *ldvr, integer *ilo, integer *ihi, doublereal *lscale, doublereal *rscale, doublereal *abnrm, doublereal *bbnrm, doublereal *rconde, doublereal * rcondv, doublereal *work, integer *lwork, integer *iwork, 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 ======= DGGEVX 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. 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) DOUBLE PRECISION 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 real 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) DOUBLE PRECISION 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 real 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) DOUBLE PRECISION array, dimension (N) ALPHAI (output) DOUBLE PRECISION array, dimension (N) BETA (output) DOUBLE PRECISION 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) DOUBLE PRECISION 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) DOUBLE PRECISION 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. ILO,IHI (output) INTEGER ILO and IHI are integer 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) DOUBLE PRECISION 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) DOUBLE PRECISION 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) DOUBLE PRECISION The one-norm of the balanced matrix A. BBNRM (output) DOUBLE PRECISION The one-norm of the balanced matrix B. RCONDE (output) DOUBLE PRECISION array, dimension (N) If SENSE = 'E' or 'B', the reciprocal condition numbers of the selected 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 same eigenpair (but not in general the j-th eigenpair, unless all eigenpairs are selected). If SENSE = 'V', RCONDE is not referenced. RCONDV (output) DOUBLE PRECISION array, dimension (N) If SENSE = 'V' or 'B', the estimated reciprocal condition numbers of the selected 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 = 'E', RCONDV is not referenced. WORK (workspace/output) DOUBLE PRECISION 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,6*N). If SENSE = 'E', LWORK >= 12*N. If SENSE = 'V' or 'B', LWORK >= 2*N*N+12*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 DHGEQZ. =N+2: error return from DTGEVC. 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. ===================================================================== Decode the input arguments Parameter adjustments */ /* Table of constant values */ static integer c__1 = 1; static integer c__0 = 0; static doublereal c_b47 = 0.; static doublereal c_b48 = 1.; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, vl_dim1, vl_offset, vr_dim1, vr_offset, i__1, i__2; doublereal d__1, d__2, d__3, d__4; /* Builtin functions */ double sqrt(doublereal); /* Local variables */ static logical pair; static doublereal anrm, bnrm; static integer ierr, itau; static doublereal temp; static logical ilvl, ilvr; static integer iwrk, iwrk1, i__, j, m; extern logical lsame_(char *, char *); static integer icols, irows; extern /* Subroutine */ int dlabad_(doublereal *, doublereal *); static integer jc; extern /* Subroutine */ int dggbak_(char *, char *, integer *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, integer *), dggbal_(char *, integer *, doublereal *, integer *, doublereal *, integer *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *); static integer in; extern doublereal dlamch_(char *); static integer mm; extern doublereal dlange_(char *, integer *, integer *, doublereal *, integer *, doublereal *); static integer jr; extern /* Subroutine */ int dgghrd_(char *, char *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, integer *), dlascl_(char *, integer *, integer *, doublereal *, doublereal *, integer *, integer *, doublereal *, integer *, integer *); static logical ilascl, ilbscl; extern /* Subroutine */ int dgeqrf_(integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *), dlacpy_(char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *); static logical ldumma[1]; static char chtemp[1]; static doublereal bignum; extern /* Subroutine */ int dhgeqz_(char *, char *, char *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, integer *), dlaset_(char *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *); static integer ijobvl; extern /* Subroutine */ int dtgevc_(char *, char *, logical *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, integer *, integer *, doublereal *, integer *), dtgsna_(char *, char *, logical *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *, doublereal *, integer *, integer *, integer *), xerbla_(char *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *, ftnlen, ftnlen); static integer ijobvr; static logical wantsb; extern /* Subroutine */ int dorgqr_(integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *); static doublereal anrmto; static logical wantse; static doublereal bnrmto; extern /* Subroutine */ int dormqr_(char *, char *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, integer *); static integer minwrk, maxwrk; static logical wantsn; static doublereal smlnum; static logical lquery, wantsv; static doublereal 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; --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; 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 (! (lsame_(balanc, "N") || lsame_(balanc, "S") || lsame_(balanc, "P") || 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.) */ minwrk = 1; if (*info == 0 && (*lwork >= 1 || lquery)) { maxwrk = *n * 5 + *n * ilaenv_(&c__1, "DGEQRF", " ", n, &c__1, n, & c__0, (ftnlen)6, (ftnlen)1); /* Computing MAX */ i__1 = 1, i__2 = *n * 6; minwrk = max(i__1,i__2); if (wantse) { /* Computing MAX */ i__1 = 1, i__2 = *n * 12; minwrk = max(i__1,i__2); } else if (wantsv || wantsb) { minwrk = (*n << 1) * *n + *n * 12 + 16; /* Computing MAX */ i__1 = maxwrk, i__2 = (*n << 1) * *n + *n * 12 + 16; maxwrk = max(i__1,i__2); } work[1] = (doublereal) maxwrk; } if (*lwork < minwrk && ! lquery) { *info = -26; } if (*info != 0) { i__1 = -(*info); xerbla_("DGGEVX", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*n == 0) { return 0; } /* Get machine constants */ eps = dlamch_("P"); smlnum = dlamch_("S"); bignum = 1. / smlnum; dlabad_(&smlnum, &bignum); smlnum = sqrt(smlnum) / eps; bignum = 1. / smlnum; /* Scale A if max element outside range [SMLNUM,BIGNUM] */ anrm = dlange_("M", n, n, &a[a_offset], lda, &work[1]); ilascl = FALSE_; if (anrm > 0. && anrm < smlnum) { anrmto = smlnum; ilascl = TRUE_; } else if (anrm > bignum) { anrmto = bignum; ilascl = TRUE_; } if (ilascl) { dlascl_("G", &c__0, &c__0, &anrm, &anrmto, n, n, &a[a_offset], lda, & ierr); } /* Scale B if max element outside range [SMLNUM,BIGNUM] */ bnrm = dlange_("M", n, n, &b[b_offset], ldb, &work[1]); ilbscl = FALSE_; if (bnrm > 0. && bnrm < smlnum) { bnrmto = smlnum; ilbscl = TRUE_; } else if (bnrm > bignum) { bnrmto = bignum; ilbscl = TRUE_; } if (ilbscl) { dlascl_("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) */ dggbal_(balanc, n, &a[a_offset], lda, &b[b_offset], ldb, ilo, ihi, & lscale[1], &rscale[1], &work[1], &ierr); /* Compute ABNRM and BBNRM */ *abnrm = dlange_("1", n, n, &a[a_offset], lda, &work[1]); if (ilascl) { work[1] = *abnrm; dlascl_("G", &c__0, &c__0, &anrmto, &anrm, &c__1, &c__1, &work[1], & c__1, &ierr); *abnrm = work[1]; } *bbnrm = dlange_("1", n, n, &b[b_offset], ldb, &work[1]); if (ilbscl) { work[1] = *bbnrm; dlascl_("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; dgeqrf_(&irows, &icols, &b_ref(*ilo, *ilo), 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; dormqr_("L", "T", &irows, &icols, &irows, &b_ref(*ilo, *ilo), ldb, &work[ itau], &a_ref(*ilo, *ilo), lda, &work[iwrk], &i__1, &ierr); /* Initialize VL and/or VR (Workspace: need N, prefer N*NB) */ if (ilvl) { dlaset_("Full", n, n, &c_b47, &c_b48, &vl[vl_offset], ldvl) ; i__1 = irows - 1; i__2 = irows - 1; dlacpy_("L", &i__1, &i__2, &b_ref(*ilo + 1, *ilo), ldb, &vl_ref(*ilo + 1, *ilo), ldvl); i__1 = *lwork + 1 - iwrk; dorgqr_(&irows, &irows, &irows, &vl_ref(*ilo, *ilo), ldvl, &work[itau] , &work[iwrk], &i__1, &ierr); } if (ilvr) { dlaset_("Full", n, n, &c_b47, &c_b48, &vr[vr_offset], ldvr) ; } /* Reduce to generalized Hessenberg form (Workspace: none needed) */ if (ilv || ! wantsn) { /* Eigenvectors requested -- work on whole matrix. */ dgghrd_(jobvl, jobvr, n, ilo, ihi, &a[a_offset], lda, &b[b_offset], ldb, &vl[vl_offset], ldvl, &vr[vr_offset], ldvr, &ierr); } else { dgghrd_("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) */ if (ilv || ! wantsn) { *(unsigned char *)chtemp = 'S'; } else { *(unsigned char *)chtemp = 'E'; } dhgeqz_(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: DTGEVC: need 6*N DTGSNA: 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'; } dtgevc_(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 (DTGEVC) and estimate condition numbers (DTGSNA). 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_ref(i__ + 1, i__) != 0.) { 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) { dtgevc_("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; dtgsna_(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) { dggbak_(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.) { goto L70; } temp = 0.; if (alphai[jc] == 0.) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ d__2 = temp, d__3 = (d__1 = vl_ref(jr, jc), abs(d__1)); temp = max(d__2,d__3); /* L30: */ } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ d__3 = temp, d__4 = (d__1 = vl_ref(jr, jc), abs(d__1)) + ( d__2 = vl_ref(jr, jc + 1), abs(d__2)); temp = max(d__3,d__4); /* L40: */ } } if (temp < smlnum) { goto L70; } temp = 1. / temp; if (alphai[jc] == 0.) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { vl_ref(jr, jc) = vl_ref(jr, jc) * temp; /* L50: */ } } 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; /* L60: */ } } L70: ; } } if (ilvr) { dggbak_(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.) { goto L120; } temp = 0.; if (alphai[jc] == 0.) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ d__2 = temp, d__3 = (d__1 = vr_ref(jr, jc), abs(d__1)); temp = max(d__2,d__3); /* L80: */ } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ d__3 = temp, d__4 = (d__1 = vr_ref(jr, jc), abs(d__1)) + ( d__2 = vr_ref(jr, jc + 1), abs(d__2)); temp = max(d__3,d__4); /* L90: */ } } if (temp < smlnum) { goto L120; } temp = 1. / temp; if (alphai[jc] == 0.) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { vr_ref(jr, jc) = vr_ref(jr, jc) * temp; /* L100: */ } } 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; /* L110: */ } } L120: ; } } /* Undo scaling if necessary */ if (ilascl) { dlascl_("G", &c__0, &c__0, &anrmto, &anrm, n, &c__1, &alphar[1], n, & ierr); dlascl_("G", &c__0, &c__0, &anrmto, &anrm, n, &c__1, &alphai[1], n, & ierr); } if (ilbscl) { dlascl_("G", &c__0, &c__0, &bnrmto, &bnrm, n, &c__1, &beta[1], n, & ierr); } L130: work[1] = (doublereal) maxwrk; return 0; /* End of DGGEVX */ } /* dggevx_ */
/* Subroutine */ int dgegs_(char *jobvsl, char *jobvsr, integer *n, doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal * alphar, doublereal *alphai, doublereal *beta, doublereal *vsl, integer *ldvsl, doublereal *vsr, integer *ldvsr, doublereal *work, integer *lwork, 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; /* Local variables */ integer nb, nb1, nb2, nb3, ihi, ilo; doublereal eps, anrm, bnrm; integer itau, lopt; extern logical lsame_(char *, char *); integer ileft, iinfo, icols; logical ilvsl; integer iwork; logical ilvsr; integer irows; extern /* Subroutine */ int dggbak_(char *, char *, integer *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, integer *), dggbal_(char *, integer *, doublereal *, integer *, doublereal *, integer *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *); extern doublereal dlamch_(char *), dlange_(char *, integer *, integer *, doublereal *, integer *, doublereal *); extern /* Subroutine */ int dgghrd_(char *, char *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, integer *), dlascl_(char *, integer *, integer *, doublereal *, doublereal *, integer *, integer *, doublereal *, integer *, integer *); logical ilascl, ilbscl; extern /* Subroutine */ int dgeqrf_(integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *), dlacpy_(char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *); doublereal safmin; extern /* Subroutine */ int dlaset_(char *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *), xerbla_(char *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *); doublereal bignum; extern /* Subroutine */ int dhgeqz_(char *, char *, char *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, integer *); integer ijobvl, iright, ijobvr; extern /* Subroutine */ int dorgqr_(integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *); doublereal anrmto; integer lwkmin; doublereal bnrmto; extern /* Subroutine */ int dormqr_(char *, char *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, integer *); doublereal smlnum; integer lwkopt; logical lquery; /* -- LAPACK driver routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* This routine is deprecated and has been replaced by routine DGGES. */ /* DGEGS computes the eigenvalues, real Schur form, and, optionally, */ /* left and or/right Schur vectors of a real matrix pair (A,B). */ /* Given two square matrices A and B, the generalized real Schur */ /* factorization has the form */ /* A = Q*S*Z**T, B = Q*T*Z**T */ /* where Q and Z are orthogonal matrices, T is upper triangular, and S */ /* is an upper quasi-triangular matrix with 1-by-1 and 2-by-2 diagonal */ /* blocks, the 2-by-2 blocks corresponding to complex conjugate pairs */ /* of eigenvalues of (A,B). The columns of Q are the left Schur vectors */ /* and the columns of Z are the right Schur vectors. */ /* If only the eigenvalues of (A,B) are needed, the driver routine */ /* DGEGV should be used instead. See DGEGV for a description of the */ /* eigenvalues of the generalized nonsymmetric eigenvalue problem */ /* (GNEP). */ /* Arguments */ /* ========= */ /* JOBVSL (input) CHARACTER*1 */ /* = 'N': do not compute the left Schur vectors; */ /* = 'V': compute the left Schur vectors (returned in VSL). */ /* JOBVSR (input) CHARACTER*1 */ /* = 'N': do not compute the right Schur vectors; */ /* = 'V': compute the right Schur vectors (returned in VSR). */ /* N (input) INTEGER */ /* The order of the matrices A, B, VSL, and VSR. N >= 0. */ /* A (input/output) DOUBLE PRECISION array, dimension (LDA, N) */ /* On entry, the matrix A. */ /* On exit, the upper quasi-triangular matrix S from the */ /* generalized real Schur factorization. */ /* LDA (input) INTEGER */ /* The leading dimension of A. LDA >= max(1,N). */ /* B (input/output) DOUBLE PRECISION array, dimension (LDB, N) */ /* On entry, the matrix B. */ /* On exit, the upper triangular matrix T from the generalized */ /* real Schur factorization. */ /* LDB (input) INTEGER */ /* The leading dimension of B. LDB >= max(1,N). */ /* ALPHAR (output) DOUBLE PRECISION array, dimension (N) */ /* The real parts of each scalar alpha defining an eigenvalue */ /* of GNEP. */ /* ALPHAI (output) DOUBLE PRECISION 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) DOUBLE PRECISION 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. */ /* VSL (output) DOUBLE PRECISION array, dimension (LDVSL,N) */ /* If JOBVSL = 'V', the matrix of left Schur vectors Q. */ /* 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) DOUBLE PRECISION array, dimension (LDVSR,N) */ /* If JOBVSR = 'V', the matrix of right Schur vectors Z. */ /* 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) DOUBLE PRECISION 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,4*N). */ /* For good performance, LWORK must generally be larger. */ /* To compute the optimal value of LWORK, call ILAENV to get */ /* blocksizes (for DGEQRF, DORMQR, and DORGQR.) Then compute: */ /* NB -- MAX of the blocksizes for DGEQRF, DORMQR, and DORGQR */ /* 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 DGGBAL */ /* =N+2: error return from DGEQRF */ /* =N+3: error return from DORMQR */ /* =N+4: error return from DORGQR */ /* =N+5: error return from DGGHRD */ /* =N+6: error return from DHGEQZ (other than failed */ /* iteration) */ /* =N+7: error return from DGGBAK (computing VSL) */ /* =N+8: error return from DGGBAK (computing VSR) */ /* =N+9: error return from DLASCL (various places) */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. 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; --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] = (doublereal) 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, "DGEQRF", " ", n, n, &c_n1, &c_n1); nb2 = ilaenv_(&c__1, "DORMQR", " ", n, n, n, &c_n1); nb3 = ilaenv_(&c__1, "DORGQR", " ", n, n, n, &c_n1); /* Computing MAX */ i__1 = max(nb1,nb2); nb = max(i__1,nb3); lopt = (*n << 1) + *n * (nb + 1); work[1] = (doublereal) lopt; } if (*info != 0) { i__1 = -(*info); xerbla_("DGEGS ", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*n == 0) { return 0; } /* Get machine constants */ eps = dlamch_("E") * dlamch_("B"); safmin = dlamch_("S"); smlnum = *n * safmin / eps; bignum = 1. / smlnum; /* Scale A if max element outside range [SMLNUM,BIGNUM] */ anrm = dlange_("M", n, n, &a[a_offset], lda, &work[1]); ilascl = FALSE_; if (anrm > 0. && anrm < smlnum) { anrmto = smlnum; ilascl = TRUE_; } else if (anrm > bignum) { anrmto = bignum; ilascl = TRUE_; } if (ilascl) { dlascl_("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 = dlange_("M", n, n, &b[b_offset], ldb, &work[1]); ilbscl = FALSE_; if (bnrm > 0. && bnrm < smlnum) { bnrmto = smlnum; ilbscl = TRUE_; } else if (bnrm > bignum) { bnrmto = bignum; ilbscl = TRUE_; } if (ilbscl) { dlascl_("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; dggbal_("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; dgeqrf_(&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 L10; } i__1 = *lwork + 1 - iwork; dormqr_("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 L10; } if (ilvsl) { dlaset_("Full", n, n, &c_b36, &c_b37, &vsl[vsl_offset], ldvsl); i__1 = irows - 1; i__2 = irows - 1; dlacpy_("L", &i__1, &i__2, &b[ilo + 1 + ilo * b_dim1], ldb, &vsl[ilo + 1 + ilo * vsl_dim1], ldvsl); i__1 = *lwork + 1 - iwork; dorgqr_(&irows, &irows, &irows, &vsl[ilo + ilo * vsl_dim1], 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) { dlaset_("Full", n, n, &c_b36, &c_b37, &vsr[vsr_offset], ldvsr); } /* Reduce to generalized Hessenberg form */ dgghrd_(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; dhgeqz_("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) { dggbak_("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) { dggbak_("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) { dlascl_("H", &c_n1, &c_n1, &anrmto, &anrm, n, n, &a[a_offset], lda, & iinfo); if (iinfo != 0) { *info = *n + 9; return 0; } dlascl_("G", &c_n1, &c_n1, &anrmto, &anrm, n, &c__1, &alphar[1], n, & iinfo); if (iinfo != 0) { *info = *n + 9; return 0; } dlascl_("G", &c_n1, &c_n1, &anrmto, &anrm, n, &c__1, &alphai[1], n, & iinfo); if (iinfo != 0) { *info = *n + 9; return 0; } } if (ilbscl) { dlascl_("U", &c_n1, &c_n1, &bnrmto, &bnrm, n, n, &b[b_offset], ldb, & iinfo); if (iinfo != 0) { *info = *n + 9; return 0; } dlascl_("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] = (doublereal) lwkopt; return 0; /* End of DGEGS */ } /* dgegs_ */
/* Subroutine */ int dggevx_(char *balanc, char *jobvl, char *jobvr, char * sense, integer *n, doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *alphar, doublereal *alphai, doublereal * beta, doublereal *vl, integer *ldvl, doublereal *vr, integer *ldvr, integer *ilo, integer *ihi, doublereal *lscale, doublereal *rscale, doublereal *abnrm, doublereal *bbnrm, doublereal *rconde, doublereal * rcondv, doublereal *work, integer *lwork, integer *iwork, logical * bwork, 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; doublereal d__1, d__2, d__3, d__4; /* Local variables */ integer i__, j, m, jc, in, mm, jr; doublereal eps; logical ilv, pair; doublereal anrm, bnrm; integer ierr, itau; doublereal temp; logical ilvl, ilvr; integer iwrk, iwrk1; integer icols; logical noscl; integer irows; logical ilascl, ilbscl; logical ldumma[1]; char chtemp[1]; doublereal bignum; integer ijobvl; integer ijobvr; logical wantsb; doublereal anrmto; logical wantse; doublereal bnrmto; integer minwrk, maxwrk; logical wantsn; doublereal smlnum; logical lquery, wantsv; /* -- LAPACK driver routine (version 3.2) -- */ /* November 2006 */ /* Purpose */ /* ======= */ /* DGGEVX 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. */ /* 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) DOUBLE PRECISION 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 real 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) DOUBLE PRECISION 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 real 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) DOUBLE PRECISION array, dimension (N) */ /* ALPHAI (output) DOUBLE PRECISION array, dimension (N) */ /* BETA (output) DOUBLE PRECISION array, dimension (N) */ /* 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) DOUBLE PRECISION 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) DOUBLE PRECISION 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. */ /* ILO (output) INTEGER */ /* IHI (output) INTEGER */ /* ILO and IHI are integer values such that on exit */ /* A(i,j) = 0 and B(i,j) = 0 if i > j and */ /* If BALANC = 'N' or 'S', ILO = 1 and IHI = N. */ /* LSCALE (output) DOUBLE PRECISION 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 */ /* The order in which the interchanges are made is N to IHI+1, */ /* then 1 to ILO-1. */ /* RSCALE (output) DOUBLE PRECISION 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 */ /* The order in which the interchanges are made is N to IHI+1, */ /* then 1 to ILO-1. */ /* ABNRM (output) DOUBLE PRECISION */ /* The one-norm of the balanced matrix A. */ /* BBNRM (output) DOUBLE PRECISION */ /* The one-norm of the balanced matrix B. */ /* RCONDE (output) DOUBLE PRECISION 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) DOUBLE PRECISION 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) DOUBLE PRECISION 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' or 'B', 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. */ /* The QZ iteration failed. No eigenvectors have been */ /* calculated, but ALPHAR(j), ALPHAI(j), and BETA(j) */ /* > N: =N+1: other than QZ iteration failed in DHGEQZ. */ /* =N+2: error return from DTGEVC. */ /* 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. */ /* ===================================================================== */ /* 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 (! (lsame_(balanc, "N") || lsame_(balanc, "S") || lsame_(balanc, "P") || 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 || wantsb) { minwrk = *n * 10; } if (wantsv || wantsb) { /* Computing MAX */ i__1 = minwrk, i__2 = (*n << 1) * (*n + 4) + 16; minwrk = max(i__1,i__2); } maxwrk = minwrk; /* Computing MAX */ i__1 = maxwrk, i__2 = *n + *n * ilaenv_(&c__1, "DGEQRF", " ", n, & c__1, n, &c__0); maxwrk = max(i__1,i__2); /* Computing MAX */ i__1 = maxwrk, i__2 = *n + *n * ilaenv_(&c__1, "DORMQR", " ", 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, "DORGQR", " ", n, &c__1, n, &c__0); maxwrk = max(i__1,i__2); } } work[1] = (doublereal) maxwrk; if (*lwork < minwrk && ! lquery) { *info = -26; } } if (*info != 0) { i__1 = -(*info); xerbla_("DGGEVX", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*n == 0) { return 0; } /* Get machine constants */ eps = dlamch_("P"); smlnum = dlamch_("S"); bignum = 1. / smlnum; dlabad_(&smlnum, &bignum); smlnum = sqrt(smlnum) / eps; bignum = 1. / smlnum; /* Scale A if max element outside range [SMLNUM,BIGNUM] */ anrm = dlange_("M", n, n, &a[a_offset], lda, &work[1]); ilascl = FALSE_; if (anrm > 0. && anrm < smlnum) { anrmto = smlnum; ilascl = TRUE_; } else if (anrm > bignum) { anrmto = bignum; ilascl = TRUE_; } if (ilascl) { dlascl_("G", &c__0, &c__0, &anrm, &anrmto, n, n, &a[a_offset], lda, & ierr); } /* Scale B if max element outside range [SMLNUM,BIGNUM] */ bnrm = dlange_("M", n, n, &b[b_offset], ldb, &work[1]); ilbscl = FALSE_; if (bnrm > 0. && bnrm < smlnum) { bnrmto = smlnum; ilbscl = TRUE_; } else if (bnrm > bignum) { bnrmto = bignum; ilbscl = TRUE_; } if (ilbscl) { dlascl_("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) */ dggbal_(balanc, n, &a[a_offset], lda, &b[b_offset], ldb, ilo, ihi, & lscale[1], &rscale[1], &work[1], &ierr); /* Compute ABNRM and BBNRM */ *abnrm = dlange_("1", n, n, &a[a_offset], lda, &work[1]); if (ilascl) { work[1] = *abnrm; dlascl_("G", &c__0, &c__0, &anrmto, &anrm, &c__1, &c__1, &work[1], & c__1, &ierr); *abnrm = work[1]; } *bbnrm = dlange_("1", n, n, &b[b_offset], ldb, &work[1]); if (ilbscl) { work[1] = *bbnrm; dlascl_("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; dgeqrf_(&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; dormqr_("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) { dlaset_("Full", n, n, &c_b59, &c_b60, &vl[vl_offset], ldvl) ; if (irows > 1) { i__1 = irows - 1; i__2 = irows - 1; dlacpy_("L", &i__1, &i__2, &b[*ilo + 1 + *ilo * b_dim1], ldb, &vl[ *ilo + 1 + *ilo * vl_dim1], ldvl); } i__1 = *lwork + 1 - iwrk; dorgqr_(&irows, &irows, &irows, &vl[*ilo + *ilo * vl_dim1], ldvl, & work[itau], &work[iwrk], &i__1, &ierr); } if (ilvr) { dlaset_("Full", n, n, &c_b59, &c_b60, &vr[vr_offset], ldvr) ; } /* Reduce to generalized Hessenberg form */ /* (Workspace: none needed) */ if (ilv || ! wantsn) { /* Eigenvectors requested -- work on whole matrix. */ dgghrd_(jobvl, jobvr, n, ilo, ihi, &a[a_offset], lda, &b[b_offset], ldb, &vl[vl_offset], ldvl, &vr[vr_offset], ldvr, &ierr); } else { dgghrd_("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'; } dhgeqz_(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: DTGEVC: need 6*N */ /* DTGSNA: 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'; } dtgevc_(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 (DTGEVC) and estimate condition */ /* numbers (DTGSNA). 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.) { pair = TRUE_; mm = 2; } } i__2 = *n; for (j = 1; j <= i__2; ++j) { bwork[j] = FALSE_; } 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) { dtgevc_("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; dtgsna_(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) { dggbak_(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.) { goto L70; } temp = 0.; if (alphai[jc] == 0.) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ d__2 = temp, d__3 = (d__1 = vl[jr + jc * vl_dim1], abs( d__1)); temp = max(d__2,d__3); } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ d__3 = temp, d__4 = (d__1 = vl[jr + jc * vl_dim1], abs( d__1)) + (d__2 = vl[jr + (jc + 1) * vl_dim1], abs( d__2)); temp = max(d__3,d__4); } } if (temp < smlnum) { goto L70; } temp = 1. / temp; if (alphai[jc] == 0.) { 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; } } L70: ; } } if (ilvr) { dggbak_(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.) { goto L120; } temp = 0.; if (alphai[jc] == 0.) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ d__2 = temp, d__3 = (d__1 = vr[jr + jc * vr_dim1], abs( d__1)); temp = max(d__2,d__3); } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ d__3 = temp, d__4 = (d__1 = vr[jr + jc * vr_dim1], abs( d__1)) + (d__2 = vr[jr + (jc + 1) * vr_dim1], abs( d__2)); temp = max(d__3,d__4); } } if (temp < smlnum) { goto L120; } temp = 1. / temp; if (alphai[jc] == 0.) { 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; } } L120: ; } } /* Undo scaling if necessary */ if (ilascl) { dlascl_("G", &c__0, &c__0, &anrmto, &anrm, n, &c__1, &alphar[1], n, & ierr); dlascl_("G", &c__0, &c__0, &anrmto, &anrm, n, &c__1, &alphai[1], n, & ierr); } if (ilbscl) { dlascl_("G", &c__0, &c__0, &bnrmto, &bnrm, n, &c__1, &beta[1], n, & ierr); } L130: work[1] = (doublereal) maxwrk; return 0; /* End of DGGEVX */ } /* dggevx_ */
/* Subroutine */ int dorgbr_(char *vect, integer *m, integer *n, integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *work, integer *lwork, integer *info) { /* -- LAPACK routine (version 3.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University June 30, 1999 Purpose ======= DORGBR generates one of the real orthogonal matrices Q or P**T determined by DGEBRD 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) or G(i) respectively. If VECT = 'Q', A is assumed to have been an M-by-K matrix, and Q is of order M: if m >= k, Q = H(1) H(2) . . . H(k) and DORGBR returns the first n columns of Q, where m >= n >= k; if m < k, Q = H(1) H(2) . . . H(m-1) and DORGBR returns Q as an M-by-M matrix. If VECT = 'P', A is assumed to have been a K-by-N matrix, and P**T is of order N: if k < n, P**T = G(k) . . . G(2) G(1) and DORGBR returns the first m rows of P**T, where n >= m >= k; if k >= n, P**T = G(n-1) . . . G(2) G(1) and DORGBR returns P**T as an N-by-N matrix. Arguments ========= VECT (input) CHARACTER*1 Specifies whether the matrix Q or the matrix P**T is required, as defined in the transformation applied by DGEBRD: = 'Q': generate Q; = 'P': generate P**T. M (input) INTEGER The number of rows of the matrix Q or P**T to be returned. M >= 0. N (input) INTEGER The number of columns of the matrix Q or P**T to be returned. N >= 0. If VECT = 'Q', M >= N >= min(M,K); if VECT = 'P', N >= M >= min(N,K). K (input) INTEGER If VECT = 'Q', the number of columns in the original M-by-K matrix reduced by DGEBRD. If VECT = 'P', the number of rows in the original K-by-N matrix reduced by DGEBRD. K >= 0. A (input/output) DOUBLE PRECISION array, dimension (LDA,N) On entry, the vectors which define the elementary reflectors, as returned by DGEBRD. On exit, the M-by-N matrix Q or P**T. LDA (input) INTEGER The leading dimension of the array A. LDA >= max(1,M). TAU (input) DOUBLE PRECISION array, dimension (min(M,K)) if VECT = 'Q' (min(N,K)) if VECT = 'P' TAU(i) must contain the scalar factor of the elementary reflector H(i) or G(i), which determines Q or P**T, as returned by DGEBRD in its array argument TAUQ or TAUP. WORK (workspace/output) DOUBLE PRECISION 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,min(M,N)). For optimum performance LWORK >= min(M,N)*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 ===================================================================== Test the input arguments Parameter adjustments */ /* Table of constant values */ static integer c__1 = 1; static integer c_n1 = -1; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3; /* Local variables */ static integer i__, j; extern logical lsame_(char *, char *); static integer iinfo; static logical wantq; static integer nb, mn; extern /* Subroutine */ int xerbla_(char *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *, ftnlen, ftnlen); extern /* Subroutine */ int dorglq_(integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *), dorgqr_(integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *); static integer lwkopt; static logical lquery; #define a_ref(a_1,a_2) a[(a_2)*a_dim1 + a_1] a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; --tau; --work; /* Function Body */ *info = 0; wantq = lsame_(vect, "Q"); mn = min(*m,*n); lquery = *lwork == -1; if (! wantq && ! lsame_(vect, "P")) { *info = -1; } else if (*m < 0) { *info = -2; } else if (*n < 0 || wantq && (*n > *m || *n < min(*m,*k)) || ! wantq && ( *m > *n || *m < min(*n,*k))) { *info = -3; } else if (*k < 0) { *info = -4; } else if (*lda < max(1,*m)) { *info = -6; } else if (*lwork < max(1,mn) && ! lquery) { *info = -9; } if (*info == 0) { if (wantq) { nb = ilaenv_(&c__1, "DORGQR", " ", m, n, k, &c_n1, (ftnlen)6, ( ftnlen)1); } else { nb = ilaenv_(&c__1, "DORGLQ", " ", m, n, k, &c_n1, (ftnlen)6, ( ftnlen)1); } lwkopt = max(1,mn) * nb; work[1] = (doublereal) lwkopt; } if (*info != 0) { i__1 = -(*info); xerbla_("DORGBR", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*m == 0 || *n == 0) { work[1] = 1.; return 0; } if (wantq) { /* Form Q, determined by a call to DGEBRD to reduce an m-by-k matrix */ if (*m >= *k) { /* If m >= k, assume m >= n >= k */ dorgqr_(m, n, k, &a[a_offset], lda, &tau[1], &work[1], lwork, & iinfo); } else { /* If m < k, assume m = n Shift the vectors which define the elementary reflectors one column to the right, and set the first row and column of Q to those of the unit matrix */ for (j = *m; j >= 2; --j) { a_ref(1, j) = 0.; i__1 = *m; for (i__ = j + 1; i__ <= i__1; ++i__) { a_ref(i__, j) = a_ref(i__, j - 1); /* L10: */ } /* L20: */ } a_ref(1, 1) = 1.; i__1 = *m; for (i__ = 2; i__ <= i__1; ++i__) { a_ref(i__, 1) = 0.; /* L30: */ } if (*m > 1) { /* Form Q(2:m,2:m) */ i__1 = *m - 1; i__2 = *m - 1; i__3 = *m - 1; dorgqr_(&i__1, &i__2, &i__3, &a_ref(2, 2), lda, &tau[1], & work[1], lwork, &iinfo); } } } else { /* Form P', determined by a call to DGEBRD to reduce a k-by-n matrix */ if (*k < *n) { /* If k < n, assume k <= m <= n */ dorglq_(m, n, k, &a[a_offset], lda, &tau[1], &work[1], lwork, & iinfo); } else { /* If k >= n, assume m = n Shift the vectors which define the elementary reflectors one row downward, and set the first row and column of P' to those of the unit matrix */ a_ref(1, 1) = 1.; i__1 = *n; for (i__ = 2; i__ <= i__1; ++i__) { a_ref(i__, 1) = 0.; /* L40: */ } i__1 = *n; for (j = 2; j <= i__1; ++j) { for (i__ = j - 1; i__ >= 2; --i__) { a_ref(i__, j) = a_ref(i__ - 1, j); /* L50: */ } a_ref(1, j) = 0.; /* L60: */ } if (*n > 1) { /* Form P'(2:n,2:n) */ i__1 = *n - 1; i__2 = *n - 1; i__3 = *n - 1; dorglq_(&i__1, &i__2, &i__3, &a_ref(2, 2), lda, &tau[1], & work[1], lwork, &iinfo); } } } work[1] = (doublereal) lwkopt; return 0; /* End of DORGBR */ } /* dorgbr_ */
/* Subroutine */ int derrqr_(char *path, integer *nunit) { /* Builtin functions */ integer s_wsle(cilist *), e_wsle(void); /* Subroutine */ int s_copy(char *, char *, ftnlen, ftnlen); /* Local variables */ doublereal a[4] /* was [2][2] */, b[2]; integer i__, j; doublereal w[2], x[2], af[4] /* was [2][2] */; integer info; extern /* Subroutine */ int dgeqr2_(integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *), dorg2r_( integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *), dorm2r_(char *, char *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *), alaesm_(char *, logical *, integer *), dgeqrf_(integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *), chkxer_(char *, integer *, integer *, logical *, logical *), dgeqrs_(integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, integer *), dorgqr_(integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *), dormqr_(char *, char *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, integer *); /* 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 */ /* ======= */ /* DERRQR tests the error exits for the DOUBLE PRECISION 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. / (doublereal) (i__ + j); af[i__ + (j << 1) - 3] = 1. / (doublereal) (i__ + j); /* L10: */ } b[j - 1] = 0.; w[j - 1] = 0.; x[j - 1] = 0.; /* L20: */ } infoc_1.ok = TRUE_; /* Error exits for QR factorization */ /* DGEQRF */ s_copy(srnamc_1.srnamt, "DGEQRF", (ftnlen)6, (ftnlen)6); infoc_1.infot = 1; dgeqrf_(&c_n1, &c__0, a, &c__1, b, w, &c__1, &info); chkxer_("DGEQRF", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; dgeqrf_(&c__0, &c_n1, a, &c__1, b, w, &c__1, &info); chkxer_("DGEQRF", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 4; dgeqrf_(&c__2, &c__1, a, &c__1, b, w, &c__1, &info); chkxer_("DGEQRF", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 7; dgeqrf_(&c__1, &c__2, a, &c__1, b, w, &c__1, &info); chkxer_("DGEQRF", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); /* DGEQR2 */ s_copy(srnamc_1.srnamt, "DGEQR2", (ftnlen)6, (ftnlen)6); infoc_1.infot = 1; dgeqr2_(&c_n1, &c__0, a, &c__1, b, w, &info); chkxer_("DGEQR2", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; dgeqr2_(&c__0, &c_n1, a, &c__1, b, w, &info); chkxer_("DGEQR2", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 4; dgeqr2_(&c__2, &c__1, a, &c__1, b, w, &info); chkxer_("DGEQR2", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); /* DGEQRS */ s_copy(srnamc_1.srnamt, "DGEQRS", (ftnlen)6, (ftnlen)6); infoc_1.infot = 1; dgeqrs_(&c_n1, &c__0, &c__0, a, &c__1, x, b, &c__1, w, &c__1, &info); chkxer_("DGEQRS", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; dgeqrs_(&c__0, &c_n1, &c__0, a, &c__1, x, b, &c__1, w, &c__1, &info); chkxer_("DGEQRS", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; dgeqrs_(&c__1, &c__2, &c__0, a, &c__2, x, b, &c__2, w, &c__1, &info); chkxer_("DGEQRS", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 3; dgeqrs_(&c__0, &c__0, &c_n1, a, &c__1, x, b, &c__1, w, &c__1, &info); chkxer_("DGEQRS", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; dgeqrs_(&c__2, &c__1, &c__0, a, &c__1, x, b, &c__2, w, &c__1, &info); chkxer_("DGEQRS", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 8; dgeqrs_(&c__2, &c__1, &c__0, a, &c__2, x, b, &c__1, w, &c__1, &info); chkxer_("DGEQRS", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 10; dgeqrs_(&c__1, &c__1, &c__2, a, &c__1, x, b, &c__1, w, &c__1, &info); chkxer_("DGEQRS", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); /* DORGQR */ s_copy(srnamc_1.srnamt, "DORGQR", (ftnlen)6, (ftnlen)6); infoc_1.infot = 1; dorgqr_(&c_n1, &c__0, &c__0, a, &c__1, x, w, &c__1, &info); chkxer_("DORGQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; dorgqr_(&c__0, &c_n1, &c__0, a, &c__1, x, w, &c__1, &info); chkxer_("DORGQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; dorgqr_(&c__1, &c__2, &c__0, a, &c__1, x, w, &c__2, &info); chkxer_("DORGQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 3; dorgqr_(&c__0, &c__0, &c_n1, a, &c__1, x, w, &c__1, &info); chkxer_("DORGQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 3; dorgqr_(&c__1, &c__1, &c__2, a, &c__1, x, w, &c__1, &info); chkxer_("DORGQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; dorgqr_(&c__2, &c__2, &c__0, a, &c__1, x, w, &c__2, &info); chkxer_("DORGQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 8; dorgqr_(&c__2, &c__2, &c__0, a, &c__2, x, w, &c__1, &info); chkxer_("DORGQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); /* DORG2R */ s_copy(srnamc_1.srnamt, "DORG2R", (ftnlen)6, (ftnlen)6); infoc_1.infot = 1; dorg2r_(&c_n1, &c__0, &c__0, a, &c__1, x, w, &info); chkxer_("DORG2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; dorg2r_(&c__0, &c_n1, &c__0, a, &c__1, x, w, &info); chkxer_("DORG2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; dorg2r_(&c__1, &c__2, &c__0, a, &c__1, x, w, &info); chkxer_("DORG2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 3; dorg2r_(&c__0, &c__0, &c_n1, a, &c__1, x, w, &info); chkxer_("DORG2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 3; dorg2r_(&c__2, &c__1, &c__2, a, &c__2, x, w, &info); chkxer_("DORG2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; dorg2r_(&c__2, &c__1, &c__0, a, &c__1, x, w, &info); chkxer_("DORG2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); /* DORMQR */ s_copy(srnamc_1.srnamt, "DORMQR", (ftnlen)6, (ftnlen)6); infoc_1.infot = 1; dormqr_("/", "N", &c__0, &c__0, &c__0, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("DORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; dormqr_("L", "/", &c__0, &c__0, &c__0, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("DORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 3; dormqr_("L", "N", &c_n1, &c__0, &c__0, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("DORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 4; dormqr_("L", "N", &c__0, &c_n1, &c__0, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("DORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; dormqr_("L", "N", &c__0, &c__0, &c_n1, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("DORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; dormqr_("L", "N", &c__0, &c__1, &c__1, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("DORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; dormqr_("R", "N", &c__1, &c__0, &c__1, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("DORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 7; dormqr_("L", "N", &c__2, &c__1, &c__0, a, &c__1, x, af, &c__2, w, &c__1, & info); chkxer_("DORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 7; dormqr_("R", "N", &c__1, &c__2, &c__0, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("DORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 10; dormqr_("L", "N", &c__2, &c__1, &c__0, a, &c__2, x, af, &c__1, w, &c__1, & info); chkxer_("DORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 12; dormqr_("L", "N", &c__1, &c__2, &c__0, a, &c__1, x, af, &c__1, w, &c__1, & info); chkxer_("DORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 12; dormqr_("R", "N", &c__2, &c__1, &c__0, a, &c__1, x, af, &c__2, w, &c__1, & info); chkxer_("DORMQR", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); /* DORM2R */ s_copy(srnamc_1.srnamt, "DORM2R", (ftnlen)6, (ftnlen)6); infoc_1.infot = 1; dorm2r_("/", "N", &c__0, &c__0, &c__0, a, &c__1, x, af, &c__1, w, &info); chkxer_("DORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; dorm2r_("L", "/", &c__0, &c__0, &c__0, a, &c__1, x, af, &c__1, w, &info); chkxer_("DORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 3; dorm2r_("L", "N", &c_n1, &c__0, &c__0, a, &c__1, x, af, &c__1, w, &info); chkxer_("DORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 4; dorm2r_("L", "N", &c__0, &c_n1, &c__0, a, &c__1, x, af, &c__1, w, &info); chkxer_("DORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; dorm2r_("L", "N", &c__0, &c__0, &c_n1, a, &c__1, x, af, &c__1, w, &info); chkxer_("DORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; dorm2r_("L", "N", &c__0, &c__1, &c__1, a, &c__1, x, af, &c__1, w, &info); chkxer_("DORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; dorm2r_("R", "N", &c__1, &c__0, &c__1, a, &c__1, x, af, &c__1, w, &info); chkxer_("DORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 7; dorm2r_("L", "N", &c__2, &c__1, &c__0, a, &c__1, x, af, &c__2, w, &info); chkxer_("DORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 7; dorm2r_("R", "N", &c__1, &c__2, &c__0, a, &c__1, x, af, &c__1, w, &info); chkxer_("DORM2R", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 10; dorm2r_("L", "N", &c__2, &c__1, &c__0, a, &c__2, x, af, &c__1, w, &info); chkxer_("DORM2R", &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 DERRQR */ } /* derrqr_ */
/* Subroutine */ int dgegv_(char *jobvl, char *jobvr, integer *n, doublereal * a, integer *lda, doublereal *b, integer *ldb, doublereal *alphar, doublereal *alphai, doublereal *beta, doublereal *vl, integer *ldvl, doublereal *vr, integer *ldvr, doublereal *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; doublereal d__1, d__2, d__3, d__4; /* Local variables */ integer jc, nb, in, jr, nb1, nb2, nb3, ihi, ilo; doublereal eps; logical ilv; doublereal absb, anrm, bnrm; integer itau; doublereal temp; logical ilvl, ilvr; integer lopt; doublereal anrm1, anrm2, bnrm1, bnrm2, absai, scale, absar, sbeta; integer ileft, iinfo, icols, iwork, irows; doublereal salfai; doublereal salfar; doublereal safmin; doublereal safmax; char chtemp[1]; logical ldumma[1]; integer ijobvl, iright; logical ilimit; integer ijobvr; doublereal 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 DGGEV. */ /* DGEGV 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) DOUBLE PRECISION 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 DGGHRD and */ /* DHGEQZ for details. */ /* LDA (input) INTEGER */ /* The leading dimension of A. LDA >= max(1,N). */ /* B (input/output) DOUBLE PRECISION 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 DGGHRD and DHGEQZ for details. */ /* LDB (input) INTEGER */ /* The leading dimension of B. LDB >= max(1,N). */ /* ALPHAR (output) DOUBLE PRECISION array, dimension (N) */ /* The real parts of each scalar alpha defining an eigenvalue of */ /* GNEP. */ /* ALPHAI (output) DOUBLE PRECISION 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) DOUBLE PRECISION 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) DOUBLE PRECISION 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) DOUBLE PRECISION 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) DOUBLE PRECISION 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 DGEQRF, DORMQR, and DORGQR.) Then compute: */ /* NB -- MAX of the blocksizes for DGEQRF, DORMQR, and DORGQR; */ /* 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 DGGBAL */ /* =N+2: error return from DGEQRF */ /* =N+3: error return from DORMQR */ /* =N+4: error return from DORGQR */ /* =N+5: error return from DGGHRD */ /* =N+6: error return from DHGEQZ (other than failed */ /* iteration) */ /* =N+7: error return from DTGEVC */ /* =N+8: error return from DGGBAK (computing VL) */ /* =N+9: error return from DGGBAK (computing VR) */ /* =N+10: error return from DLASCL (various calls) */ /* Further Details */ /* =============== */ /* Balancing */ /* --------- */ /* This driver calls DGGBAL 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, DGGBAK 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 DHGEQZ, DGEGS, 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] = (doublereal) 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, "DGEQRF", " ", n, n, &c_n1, &c_n1); nb2 = ilaenv_(&c__1, "DORMQR", " ", n, n, n, &c_n1); nb3 = ilaenv_(&c__1, "DORGQR", " ", 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] = (doublereal) lopt; } if (*info != 0) { i__1 = -(*info); xerbla_("DGEGV ", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*n == 0) { return 0; } /* Get machine constants */ eps = dlamch_("E") * dlamch_("B"); safmin = dlamch_("S"); safmin += safmin; safmax = 1. / safmin; onepls = eps * 4 + 1.; /* Scale A */ anrm = dlange_("M", n, n, &a[a_offset], lda, &work[1]); anrm1 = anrm; anrm2 = 1.; if (anrm < 1.) { if (safmax * anrm < 1.) { anrm1 = safmin; anrm2 = safmax * anrm; } } if (anrm > 0.) { dlascl_("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 = dlange_("M", n, n, &b[b_offset], ldb, &work[1]); bnrm1 = bnrm; bnrm2 = 1.; if (bnrm < 1.) { if (safmax * bnrm < 1.) { bnrm1 = safmin; bnrm2 = safmax * bnrm; } } if (bnrm > 0.) { dlascl_("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; dggbal_("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; dgeqrf_(&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; dormqr_("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) { dlaset_("Full", n, n, &c_b38, &c_b27, &vl[vl_offset], ldvl) ; i__1 = irows - 1; i__2 = irows - 1; dlacpy_("L", &i__1, &i__2, &b[ilo + 1 + ilo * b_dim1], ldb, &vl[ilo + 1 + ilo * vl_dim1], ldvl); i__1 = *lwork + 1 - iwork; dorgqr_(&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) { dlaset_("Full", n, n, &c_b38, &c_b27, &vr[vr_offset], ldvr) ; } /* Reduce to generalized Hessenberg form */ if (ilv) { /* Eigenvectors requested -- work on whole matrix. */ dgghrd_(jobvl, jobvr, n, &ilo, &ihi, &a[a_offset], lda, &b[b_offset], ldb, &vl[vl_offset], ldvl, &vr[vr_offset], ldvr, &iinfo); } else { dgghrd_("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; dhgeqz_(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 (DTGEVC requires 6*N words of workspace) */ if (ilvl) { if (ilvr) { *(unsigned char *)chtemp = 'B'; } else { *(unsigned char *)chtemp = 'L'; } } else { *(unsigned char *)chtemp = 'R'; } dtgevc_(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) { dggbak_("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.) { goto L50; } temp = 0.; if (alphai[jc] == 0.) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ d__2 = temp, d__3 = (d__1 = vl[jr + jc * vl_dim1], abs(d__1)); temp = max(d__2,d__3); } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ d__3 = temp, d__4 = (d__1 = vl[jr + jc * vl_dim1], abs(d__1)) + (d__2 = vl[jr + (jc + 1) * vl_dim1], abs(d__2)); temp = max(d__3,d__4); } } if (temp < safmin) { goto L50; } temp = 1. / temp; if (alphai[jc] == 0.) { 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) { dggbak_("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.) { goto L100; } temp = 0.; if (alphai[jc] == 0.) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ d__2 = temp, d__3 = (d__1 = vr[jr + jc * vr_dim1], abs(d__1)); temp = max(d__2,d__3); } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ d__3 = temp, d__4 = (d__1 = vr[jr + jc * vr_dim1], abs(d__1)) + (d__2 = vr[jr + (jc + 1) * vr_dim1], abs(d__2)); temp = max(d__3,d__4); } } if (temp < safmin) { goto L100; } temp = 1. / temp; if (alphai[jc] == 0.) { 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 = (d__1 = alphar[jc], abs(d__1)); absai = (d__1 = alphai[jc], abs(d__1)); absb = (d__1 = beta[jc], abs(d__1)); salfar = anrm * alphar[jc]; salfai = anrm * alphai[jc]; sbeta = bnrm * beta[jc]; ilimit = FALSE_; scale = 1.; /* Check for significant underflow in ALPHAI */ /* Computing MAX */ d__1 = safmin, d__2 = eps * absar, d__1 = max(d__1,d__2), d__2 = eps * absb; if (abs(salfai) < safmin && absai >= max(d__1,d__2)) { ilimit = TRUE_; /* Computing MAX */ d__1 = onepls * safmin, d__2 = anrm2 * absai; scale = onepls * safmin / anrm1 / max(d__1,d__2); } else if (salfai == 0.) { /* If insignificant underflow in ALPHAI, then make the */ /* conjugate eigenvalue real. */ if (alphai[jc] < 0. && jc > 1) { alphai[jc - 1] = 0.; } else if (alphai[jc] > 0. && jc < *n) { alphai[jc + 1] = 0.; } } /* Check for significant underflow in ALPHAR */ /* Computing MAX */ d__1 = safmin, d__2 = eps * absai, d__1 = max(d__1,d__2), d__2 = eps * absb; if (abs(salfar) < safmin && absar >= max(d__1,d__2)) { ilimit = TRUE_; /* Computing MAX */ /* Computing MAX */ d__3 = onepls * safmin, d__4 = anrm2 * absar; d__1 = scale, d__2 = onepls * safmin / anrm1 / max(d__3,d__4); scale = max(d__1,d__2); } /* Check for significant underflow in BETA */ /* Computing MAX */ d__1 = safmin, d__2 = eps * absar, d__1 = max(d__1,d__2), d__2 = eps * absai; if (abs(sbeta) < safmin && absb >= max(d__1,d__2)) { ilimit = TRUE_; /* Computing MAX */ /* Computing MAX */ d__3 = onepls * safmin, d__4 = bnrm2 * absb; d__1 = scale, d__2 = onepls * safmin / bnrm1 / max(d__3,d__4); scale = max(d__1,d__2); } /* Check for possible overflow when limiting scaling */ if (ilimit) { /* Computing MAX */ d__1 = abs(salfar), d__2 = abs(salfai), d__1 = max(d__1,d__2), d__2 = abs(sbeta); temp = scale * safmin * max(d__1,d__2); if (temp > 1.) { scale /= temp; } if (scale < 1.) { 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] = (doublereal) lwkopt; return 0; /* End of DGEGV */ } /* dgegv_ */
/* Subroutine */ int dgges_(char *jobvsl, char *jobvsr, char *sort, L_fp selctg, integer *n, doublereal *a, integer *lda, doublereal *b, integer *ldb, integer *sdim, doublereal *alphar, doublereal *alphai, doublereal *beta, doublereal *vsl, integer *ldvsl, doublereal *vsr, integer *ldvsr, doublereal *work, integer *lwork, 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; doublereal d__1; /* Local variables */ integer i__, ip; doublereal dif[2]; integer ihi, ilo; doublereal eps, anrm, bnrm; integer idum[1], ierr, itau, iwrk; doublereal pvsl, pvsr; integer ileft, icols; logical cursl, ilvsl, ilvsr; integer irows; logical lst2sl; logical ilascl, ilbscl; doublereal safmin; doublereal safmax; doublereal bignum; integer ijobvl, iright; integer ijobvr; doublereal anrmto, bnrmto; logical lastsl; integer minwrk, maxwrk; doublereal smlnum; logical wantst, lquery; /* -- LAPACK driver routine (version 3.2) -- */ /* November 2006 */ /* Purpose */ /* ======= */ /* DGGES 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 */ /* DGGEV 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 (external procedure) LOGICAL FUNCTION of three DOUBLE PRECISION 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) DOUBLE PRECISION 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) DOUBLE PRECISION 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) DOUBLE PRECISION array, dimension (N) */ /* ALPHAI (output) DOUBLE PRECISION array, dimension (N) */ /* BETA (output) DOUBLE PRECISION array, dimension (N) */ /* be the generalized eigenvalues. ALPHAR(j) + ALPHAI(j)*i, */ /* 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) DOUBLE PRECISION 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) DOUBLE PRECISION 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) DOUBLE PRECISION 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 LWORK >= 8*N+16. */ /* 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. */ /* 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. */ /* The QZ iteration failed. (A,B) are not in Schur */ /* form, but ALPHAR(j), ALPHAI(j), and BETA(j) should */ /* > N: =N+1: other than QZ iteration failed in DHGEQZ. */ /* =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 DTGSEN. */ /* ===================================================================== */ /* 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; --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.) */ 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, "DGEQRF", " ", n, & c__1, n, &c__0); /* Computing MAX */ i__1 = maxwrk, i__2 = minwrk - *n + *n * ilaenv_(&c__1, "DORMQR", " ", 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, "DOR" "GQR", " ", n, &c__1, n, &c_n1); maxwrk = max(i__1,i__2); } } else { minwrk = 1; maxwrk = 1; } work[1] = (doublereal) maxwrk; if (*lwork < minwrk && ! lquery) { *info = -19; } } if (*info != 0) { i__1 = -(*info); xerbla_("DGGES ", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*n == 0) { *sdim = 0; return 0; } /* Get machine constants */ eps = dlamch_("P"); safmin = dlamch_("S"); safmax = 1. / safmin; dlabad_(&safmin, &safmax); smlnum = sqrt(safmin) / eps; bignum = 1. / smlnum; /* Scale A if max element outside range [SMLNUM,BIGNUM] */ anrm = dlange_("M", n, n, &a[a_offset], lda, &work[1]); ilascl = FALSE_; if (anrm > 0. && anrm < smlnum) { anrmto = smlnum; ilascl = TRUE_; } else if (anrm > bignum) { anrmto = bignum; ilascl = TRUE_; } if (ilascl) { dlascl_("G", &c__0, &c__0, &anrm, &anrmto, n, n, &a[a_offset], lda, & ierr); } /* Scale B if max element outside range [SMLNUM,BIGNUM] */ bnrm = dlange_("M", n, n, &b[b_offset], ldb, &work[1]); ilbscl = FALSE_; if (bnrm > 0. && bnrm < smlnum) { bnrmto = smlnum; ilbscl = TRUE_; } else if (bnrm > bignum) { bnrmto = bignum; ilbscl = TRUE_; } if (ilbscl) { dlascl_("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; dggbal_("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; dgeqrf_(&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; dormqr_("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) { dlaset_("Full", n, n, &c_b38, &c_b39, &vsl[vsl_offset], ldvsl); if (irows > 1) { i__1 = irows - 1; i__2 = irows - 1; dlacpy_("L", &i__1, &i__2, &b[ilo + 1 + ilo * b_dim1], ldb, &vsl[ ilo + 1 + ilo * vsl_dim1], ldvsl); } i__1 = *lwork + 1 - iwrk; dorgqr_(&irows, &irows, &irows, &vsl[ilo + ilo * vsl_dim1], ldvsl, & work[itau], &work[iwrk], &i__1, &ierr); } /* Initialize VSR */ if (ilvsr) { dlaset_("Full", n, n, &c_b38, &c_b39, &vsr[vsr_offset], ldvsr); } /* Reduce to generalized Hessenberg form */ /* (Workspace: none needed) */ dgghrd_(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; dhgeqz_("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 if desired */ /* (Workspace: need 4*N+16 ) */ *sdim = 0; if (wantst) { /* Undo scaling on eigenvalues before SELCTGing */ if (ilascl) { dlascl_("G", &c__0, &c__0, &anrmto, &anrm, n, &c__1, &alphar[1], n, &ierr); dlascl_("G", &c__0, &c__0, &anrmto, &anrm, n, &c__1, &alphai[1], n, &ierr); } if (ilbscl) { dlascl_("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__]); } i__1 = *lwork - iwrk + 1; dtgsen_(&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) { dggbak_("P", "L", n, &ilo, &ihi, &work[ileft], &work[iright], n, &vsl[ vsl_offset], ldvsl, &ierr); } if (ilvsr) { dggbak_("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.) { if (alphar[i__] / safmax > anrmto / anrm || safmin / alphar[ i__] > anrm / anrmto) { work[1] = (d__1 = a[i__ + i__ * a_dim1] / alphar[i__], abs(d__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] = (d__1 = a[i__ + (i__ + 1) * a_dim1] / alphai[ i__], abs(d__1)); beta[i__] *= work[1]; alphar[i__] *= work[1]; alphai[i__] *= work[1]; } } } } if (ilbscl) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (alphai[i__] != 0.) { if (beta[i__] / safmax > bnrmto / bnrm || safmin / beta[i__] > bnrm / bnrmto) { work[1] = (d__1 = b[i__ + i__ * b_dim1] / beta[i__], abs( d__1)); beta[i__] *= work[1]; alphar[i__] *= work[1]; alphai[i__] *= work[1]; } } } } /* Undo scaling */ if (ilascl) { dlascl_("H", &c__0, &c__0, &anrmto, &anrm, n, n, &a[a_offset], lda, & ierr); dlascl_("G", &c__0, &c__0, &anrmto, &anrm, n, &c__1, &alphar[1], n, & ierr); dlascl_("G", &c__0, &c__0, &anrmto, &anrm, n, &c__1, &alphai[1], n, & ierr); } if (ilbscl) { dlascl_("U", &c__0, &c__0, &bnrmto, &bnrm, n, n, &b[b_offset], ldb, & ierr); dlascl_("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.) { 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; } } L50: work[1] = (doublereal) maxwrk; return 0; /* End of DGGES */ } /* dgges_ */
/* Subroutine */ int dorghr_(integer *n, integer *ilo, integer *ihi, doublereal *a, integer *lda, doublereal *tau, doublereal *work, integer *lwork, integer *info) { /* System generated locals */ integer a_dim1, a_offset, i__1, i__2; /* Local variables */ integer i__, j, nb, nh, iinfo; extern /* Subroutine */ int xerbla_(char *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *); extern /* Subroutine */ int dorgqr_(integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *); integer lwkopt; logical lquery; /* -- LAPACK routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DORGHR generates a real orthogonal matrix Q which is defined as the */ /* product of IHI-ILO elementary reflectors of order N, as returned by */ /* DGEHRD: */ /* Q = H(ilo) H(ilo+1) . . . H(ihi-1). */ /* Arguments */ /* ========= */ /* N (input) INTEGER */ /* The order of the matrix Q. N >= 0. */ /* ILO (input) INTEGER */ /* IHI (input) INTEGER */ /* ILO and IHI must have the same values as in the previous call */ /* of DGEHRD. Q is equal to the unit matrix except in the */ /* submatrix Q(ilo+1:ihi,ilo+1:ihi). */ /* 1 <= ILO <= IHI <= N, if N > 0; ILO=1 and IHI=0, if N=0. */ /* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) */ /* On entry, the vectors which define the elementary reflectors, */ /* as returned by DGEHRD. */ /* On exit, the N-by-N orthogonal matrix Q. */ /* LDA (input) INTEGER */ /* The leading dimension of the array A. LDA >= max(1,N). */ /* TAU (input) DOUBLE PRECISION array, dimension (N-1) */ /* TAU(i) must contain the scalar factor of the elementary */ /* reflector H(i), as returned by DGEHRD. */ /* WORK (workspace/output) DOUBLE PRECISION 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 >= IHI-ILO. */ /* For optimum performance LWORK >= (IHI-ILO)*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 */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input arguments */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; --tau; --work; /* Function Body */ *info = 0; nh = *ihi - *ilo; lquery = *lwork == -1; if (*n < 0) { *info = -1; } else if (*ilo < 1 || *ilo > max(1,*n)) { *info = -2; } else if (*ihi < min(*ilo,*n) || *ihi > *n) { *info = -3; } else if (*lda < max(1,*n)) { *info = -5; } else if (*lwork < max(1,nh) && ! lquery) { *info = -8; } if (*info == 0) { nb = ilaenv_(&c__1, "DORGQR", " ", &nh, &nh, &nh, &c_n1); lwkopt = max(1,nh) * nb; work[1] = (doublereal) lwkopt; } if (*info != 0) { i__1 = -(*info); xerbla_("DORGHR", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*n == 0) { work[1] = 1.; return 0; } /* Shift the vectors which define the elementary reflectors one */ /* column to the right, and set the first ilo and the last n-ihi */ /* rows and columns to those of the unit matrix */ i__1 = *ilo + 1; for (j = *ihi; j >= i__1; --j) { i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { a[i__ + j * a_dim1] = 0.; /* L10: */ } i__2 = *ihi; for (i__ = j + 1; i__ <= i__2; ++i__) { a[i__ + j * a_dim1] = a[i__ + (j - 1) * a_dim1]; /* L20: */ } i__2 = *n; for (i__ = *ihi + 1; i__ <= i__2; ++i__) { a[i__ + j * a_dim1] = 0.; /* L30: */ } /* L40: */ } i__1 = *ilo; for (j = 1; j <= i__1; ++j) { i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { a[i__ + j * a_dim1] = 0.; /* L50: */ } a[j + j * a_dim1] = 1.; /* L60: */ } i__1 = *n; for (j = *ihi + 1; j <= i__1; ++j) { i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { a[i__ + j * a_dim1] = 0.; /* L70: */ } a[j + j * a_dim1] = 1.; /* L80: */ } if (nh > 0) { /* Generate Q(ilo+1:ihi,ilo+1:ihi) */ dorgqr_(&nh, &nh, &nh, &a[*ilo + 1 + (*ilo + 1) * a_dim1], lda, &tau[* ilo], &work[1], lwork, &iinfo); } work[1] = (doublereal) lwkopt; return 0; /* End of DORGHR */ } /* dorghr_ */
/* Subroutine */ int dgegs_(char *jobvsl, char *jobvsr, integer *n, doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal * alphar, doublereal *alphai, doublereal *beta, doublereal *vsl, integer *ldvsl, doublereal *vsr, integer *ldvsr, doublereal *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 DGGES. DGEGS 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 DGEGV 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) DOUBLE PRECISION 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) DOUBLE PRECISION 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) DOUBLE PRECISION array, dimension (N) ALPHAI (output) DOUBLE PRECISION array, dimension (N) BETA (output) DOUBLE PRECISION 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) DOUBLE PRECISION 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) DOUBLE PRECISION 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) DOUBLE PRECISION 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 DGEQRF, DORMQR, and DORGQR.) Then compute: NB -- MAX of the blocksizes for DGEQRF, DORMQR, and DORGQR 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 DGGBAL =N+2: error return from DGEQRF =N+3: error return from DORMQR =N+4: error return from DORGQR =N+5: error return from DGGHRD =N+6: error return from DHGEQZ (other than failed iteration) =N+7: error return from DGGBAK (computing VSL) =N+8: error return from DGGBAK (computing VSR) =N+9: error return from DLASCL (various places) ===================================================================== Decode the input arguments Parameter adjustments */ /* Table of constant values */ static integer c__1 = 1; static integer c_n1 = -1; static doublereal c_b36 = 0.; static doublereal c_b37 = 1.; /* 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 doublereal 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; extern /* Subroutine */ int dggbak_(char *, char *, integer *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, integer *); static integer nb; extern /* Subroutine */ int dggbal_(char *, integer *, doublereal *, integer *, doublereal *, integer *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *); extern doublereal dlamch_(char *), dlange_(char *, integer *, integer *, doublereal *, integer *, doublereal *); extern /* Subroutine */ int dgghrd_(char *, char *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, integer *), dlascl_(char *, integer *, integer *, doublereal *, doublereal *, integer *, integer *, doublereal *, integer *, integer *); static logical ilascl, ilbscl; extern /* Subroutine */ int dgeqrf_(integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *), dlacpy_(char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *); static doublereal safmin; extern /* Subroutine */ int dlaset_(char *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *), xerbla_(char *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *, ftnlen, ftnlen); static doublereal bignum; extern /* Subroutine */ int dhgeqz_(char *, char *, char *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, integer *); static integer ijobvl, iright, ijobvr; extern /* Subroutine */ int dorgqr_(integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *); static doublereal anrmto; static integer lwkmin, nb1, nb2, nb3; static doublereal bnrmto; extern /* Subroutine */ int dormqr_(char *, char *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, integer *); static doublereal smlnum; static integer lwkopt; static logical lquery; static integer ihi, ilo; static doublereal 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] = (doublereal) 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, "DGEQRF", " ", n, n, &c_n1, &c_n1, (ftnlen)6, ( ftnlen)1); nb2 = ilaenv_(&c__1, "DORMQR", " ", n, n, n, &c_n1, (ftnlen)6, ( ftnlen)1); nb3 = ilaenv_(&c__1, "DORGQR", " ", 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] = (doublereal) lopt; } if (*info != 0) { i__1 = -(*info); xerbla_("DGEGS ", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*n == 0) { return 0; } /* Get machine constants */ eps = dlamch_("E") * dlamch_("B"); safmin = dlamch_("S"); smlnum = *n * safmin / eps; bignum = 1. / smlnum; /* Scale A if max element outside range [SMLNUM,BIGNUM] */ anrm = dlange_("M", n, n, &a[a_offset], lda, &work[1]); ilascl = FALSE_; if (anrm > 0. && anrm < smlnum) { anrmto = smlnum; ilascl = TRUE_; } else if (anrm > bignum) { anrmto = bignum; ilascl = TRUE_; } if (ilascl) { dlascl_("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 = dlange_("M", n, n, &b[b_offset], ldb, &work[1]); ilbscl = FALSE_; if (bnrm > 0. && bnrm < smlnum) { bnrmto = smlnum; ilbscl = TRUE_; } else if (bnrm > bignum) { bnrmto = bignum; ilbscl = TRUE_; } if (ilbscl) { dlascl_("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; dggbal_("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; dgeqrf_(&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; dormqr_("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) { dlaset_("Full", n, n, &c_b36, &c_b37, &vsl[vsl_offset], ldvsl); i__1 = irows - 1; i__2 = irows - 1; dlacpy_("L", &i__1, &i__2, &b_ref(ilo + 1, ilo), ldb, &vsl_ref(ilo + 1, ilo), ldvsl); i__1 = *lwork + 1 - iwork; dorgqr_(&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) { dlaset_("Full", n, n, &c_b36, &c_b37, &vsr[vsr_offset], ldvsr); } /* Reduce to generalized Hessenberg form */ dgghrd_(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; dhgeqz_("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) { dggbak_("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) { dggbak_("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) { dlascl_("H", &c_n1, &c_n1, &anrmto, &anrm, n, n, &a[a_offset], lda, & iinfo); if (iinfo != 0) { *info = *n + 9; return 0; } dlascl_("G", &c_n1, &c_n1, &anrmto, &anrm, n, &c__1, &alphar[1], n, & iinfo); if (iinfo != 0) { *info = *n + 9; return 0; } dlascl_("G", &c_n1, &c_n1, &anrmto, &anrm, n, &c__1, &alphai[1], n, & iinfo); if (iinfo != 0) { *info = *n + 9; return 0; } } if (ilbscl) { dlascl_("U", &c_n1, &c_n1, &bnrmto, &bnrm, n, n, &b[b_offset], ldb, & iinfo); if (iinfo != 0) { *info = *n + 9; return 0; } dlascl_("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] = (doublereal) lwkopt; return 0; /* End of DGEGS */ } /* dgegs_ */
/* Subroutine */ int dgegv_(char *jobvl, char *jobvr, integer *n, doublereal * a, integer *lda, doublereal *b, integer *ldb, doublereal *alphar, doublereal *alphai, doublereal *beta, doublereal *vl, integer *ldvl, doublereal *vr, integer *ldvr, doublereal *work, integer *lwork, integer *info, ftnlen jobvl_len, ftnlen jobvr_len) { /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, vl_dim1, vl_offset, vr_dim1, vr_offset, i__1, i__2; doublereal d__1, d__2, d__3, d__4; /* Local variables */ static integer jc, nb, in, jr, nb1, nb2, nb3, ihi, ilo; static doublereal eps; static logical ilv; static doublereal absb, anrm, bnrm; static integer itau; static doublereal temp; static logical ilvl, ilvr; static integer lopt; static doublereal anrm1, anrm2, bnrm1, bnrm2, absai, scale, absar, sbeta; extern logical lsame_(char *, char *, ftnlen, ftnlen); static integer ileft, iinfo, icols, iwork, irows; extern /* Subroutine */ int dggbak_(char *, char *, integer *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, integer *, ftnlen, ftnlen), dggbal_(char *, integer *, doublereal *, integer *, doublereal *, integer *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *, ftnlen); extern doublereal dlamch_(char *, ftnlen), dlange_(char *, integer *, integer *, doublereal *, integer *, doublereal *, ftnlen); static doublereal salfai; extern /* Subroutine */ int dgghrd_(char *, char *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, integer *, ftnlen, ftnlen), dlascl_(char *, integer *, integer *, doublereal *, doublereal *, integer *, integer *, doublereal *, integer *, integer *, ftnlen); static doublereal salfar; extern /* Subroutine */ int dgeqrf_(integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *), dlacpy_(char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, ftnlen); static doublereal safmin; extern /* Subroutine */ int dlaset_(char *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *, ftnlen); static doublereal safmax; static char chtemp[1]; static logical ldumma[1]; extern /* Subroutine */ int dhgeqz_(char *, char *, char *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, integer *, ftnlen, ftnlen, ftnlen), dtgevc_(char *, char *, logical *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, integer *, integer *, doublereal *, integer *, ftnlen, ftnlen), xerbla_(char *, integer *, ftnlen); static integer ijobvl, iright; static logical ilimit; extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *, ftnlen, ftnlen); static integer ijobvr; extern /* Subroutine */ int dorgqr_(integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *); static doublereal onepls; static integer lwkmin; extern /* Subroutine */ int dormqr_(char *, char *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, integer *, ftnlen, ftnlen); static integer lwkopt; static logical lquery; /* -- 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 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* This routine is deprecated and has been replaced by routine DGGEV. */ /* DGEGV computes for a pair of n-by-n real nonsymmetric matrices A and */ /* B, the generalized eigenvalues (alphar +/- alphai*i, beta), and */ /* optionally, the left and/or right generalized eigenvectors (VL and */ /* VR). */ /* 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) */ /* A right generalized eigenvector corresponding to a generalized */ /* eigenvalue w for a pair of matrices (A,B) is a vector r such */ /* that (A - w B) r = 0 . A left generalized eigenvector is a vector */ /* l such that l**H * (A - w B) = 0, where l**H is the */ /* conjugate-transpose of l. */ /* 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. */ /* 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) DOUBLE PRECISION array, dimension (LDA, N) */ /* On entry, the first of the pair of matrices whose */ /* generalized eigenvalues and (optionally) generalized */ /* eigenvectors are to be computed. */ /* On exit, the contents will have been destroyed. (For a */ /* description of the contents of A on exit, see "Further */ /* Details", below.) */ /* LDA (input) INTEGER */ /* The leading dimension of A. LDA >= max(1,N). */ /* B (input/output) DOUBLE PRECISION array, dimension (LDB, N) */ /* On entry, the second of the pair of matrices whose */ /* generalized eigenvalues and (optionally) generalized */ /* eigenvectors are to be computed. */ /* On exit, the contents will have been destroyed. (For a */ /* description of the contents of B on exit, see "Further */ /* Details", below.) */ /* LDB (input) INTEGER */ /* The leading dimension of B. LDB >= max(1,N). */ /* ALPHAR (output) DOUBLE PRECISION array, dimension (N) */ /* ALPHAI (output) DOUBLE PRECISION array, dimension (N) */ /* BETA (output) DOUBLE PRECISION 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) DOUBLE PRECISION array, dimension (LDVL,N) */ /* If JOBVL = 'V', the left generalized eigenvectors. (See */ /* "Purpose", above.) Real eigenvectors take one column, */ /* complex take two columns, the first for the real part and */ /* the second for the imaginary part. Complex eigenvectors */ /* correspond to an eigenvalue with positive imaginary part. */ /* Each eigenvector will be scaled so the largest component */ /* will have abs(real part) + abs(imag. part) = 1, *except* */ /* that for eigenvalues with alpha=beta=0, a zero vector will */ /* be returned as the corresponding eigenvector. */ /* 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) DOUBLE PRECISION array, dimension (LDVR,N) */ /* If JOBVR = 'V', the right generalized eigenvectors. (See */ /* "Purpose", above.) Real eigenvectors take one column, */ /* complex take two columns, the first for the real part and */ /* the second for the imaginary part. Complex eigenvectors */ /* correspond to an eigenvalue with positive imaginary part. */ /* Each eigenvector will be scaled so the largest component */ /* will have abs(real part) + abs(imag. part) = 1, *except* */ /* that for eigenvalues with alpha=beta=0, a zero vector will */ /* be returned as the corresponding eigenvector. */ /* 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) DOUBLE PRECISION 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. */ /* To compute the optimal value of LWORK, call ILAENV to get */ /* blocksizes (for DGEQRF, DORMQR, and DORGQR.) Then compute: */ /* NB -- MAX of the blocksizes for DGEQRF, DORMQR, and DORGQR; */ /* 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. */ /* = 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: errors that usually indicate LAPACK problems: */ /* =N+1: error return from DGGBAL */ /* =N+2: error return from DGEQRF */ /* =N+3: error return from DORMQR */ /* =N+4: error return from DORGQR */ /* =N+5: error return from DGGHRD */ /* =N+6: error return from DHGEQZ (other than failed */ /* iteration) */ /* =N+7: error return from DTGEVC */ /* =N+8: error return from DGGBAK (computing VL) */ /* =N+9: error return from DGGBAK (computing VR) */ /* =N+10: error return from DLASCL (various calls) */ /* Further Details */ /* =============== */ /* Balancing */ /* --------- */ /* This driver calls DGGBAL 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, DGGBAK 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 DHGEQZ, DGEGS, or read the book "Matrix Computations", */ /* by Golub & van Loan, pub. by Johns Hopkins U. Press. */ /* ===================================================================== */ /* .. 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", (ftnlen)1, (ftnlen)1)) { ijobvl = 1; ilvl = FALSE_; } else if (lsame_(jobvl, "V", (ftnlen)1, (ftnlen)1)) { ijobvl = 2; ilvl = TRUE_; } else { ijobvl = -1; ilvl = FALSE_; } if (lsame_(jobvr, "N", (ftnlen)1, (ftnlen)1)) { ijobvr = 1; ilvr = FALSE_; } else if (lsame_(jobvr, "V", (ftnlen)1, (ftnlen)1)) { 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] = (doublereal) 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, "DGEQRF", " ", n, n, &c_n1, &c_n1, (ftnlen)6, ( ftnlen)1); nb2 = ilaenv_(&c__1, "DORMQR", " ", n, n, n, &c_n1, (ftnlen)6, ( ftnlen)1); nb3 = ilaenv_(&c__1, "DORGQR", " ", n, n, n, &c_n1, (ftnlen)6, ( ftnlen)1); /* 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] = (doublereal) lopt; } if (*info != 0) { i__1 = -(*info); xerbla_("DGEGV ", &i__1, (ftnlen)6); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*n == 0) { return 0; } /* Get machine constants */ eps = dlamch_("E", (ftnlen)1) * dlamch_("B", (ftnlen)1); safmin = dlamch_("S", (ftnlen)1); safmin += safmin; safmax = 1. / safmin; onepls = eps * 4 + 1.; /* Scale A */ anrm = dlange_("M", n, n, &a[a_offset], lda, &work[1], (ftnlen)1); anrm1 = anrm; anrm2 = 1.; if (anrm < 1.) { if (safmax * anrm < 1.) { anrm1 = safmin; anrm2 = safmax * anrm; } } if (anrm > 0.) { dlascl_("G", &c_n1, &c_n1, &anrm, &c_b27, n, n, &a[a_offset], lda, & iinfo, (ftnlen)1); if (iinfo != 0) { *info = *n + 10; return 0; } } /* Scale B */ bnrm = dlange_("M", n, n, &b[b_offset], ldb, &work[1], (ftnlen)1); bnrm1 = bnrm; bnrm2 = 1.; if (bnrm < 1.) { if (safmax * bnrm < 1.) { bnrm1 = safmin; bnrm2 = safmax * bnrm; } } if (bnrm > 0.) { dlascl_("G", &c_n1, &c_n1, &bnrm, &c_b27, n, n, &b[b_offset], ldb, & iinfo, (ftnlen)1); 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; dggbal_("P", n, &a[a_offset], lda, &b[b_offset], ldb, &ilo, &ihi, &work[ ileft], &work[iright], &work[iwork], &iinfo, (ftnlen)1); 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; dgeqrf_(&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; dormqr_("L", "T", &irows, &icols, &irows, &b[ilo + ilo * b_dim1], ldb, & work[itau], &a[ilo + ilo * a_dim1], lda, &work[iwork], &i__1, & iinfo, (ftnlen)1, (ftnlen)1); 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) { dlaset_("Full", n, n, &c_b38, &c_b27, &vl[vl_offset], ldvl, (ftnlen)4) ; i__1 = irows - 1; i__2 = irows - 1; dlacpy_("L", &i__1, &i__2, &b[ilo + 1 + ilo * b_dim1], ldb, &vl[ilo + 1 + ilo * vl_dim1], ldvl, (ftnlen)1); i__1 = *lwork + 1 - iwork; dorgqr_(&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) { dlaset_("Full", n, n, &c_b38, &c_b27, &vr[vr_offset], ldvr, (ftnlen)4) ; } /* Reduce to generalized Hessenberg form */ if (ilv) { /* Eigenvectors requested -- work on whole matrix. */ dgghrd_(jobvl, jobvr, n, &ilo, &ihi, &a[a_offset], lda, &b[b_offset], ldb, &vl[vl_offset], ldvl, &vr[vr_offset], ldvr, &iinfo, ( ftnlen)1, (ftnlen)1); } else { dgghrd_("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, (ftnlen)1, (ftnlen)1); } 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; dhgeqz_(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, (ftnlen) 1, (ftnlen)1, (ftnlen)1); 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 (DTGEVC requires 6*N words of workspace) */ if (ilvl) { if (ilvr) { *(unsigned char *)chtemp = 'B'; } else { *(unsigned char *)chtemp = 'L'; } } else { *(unsigned char *)chtemp = 'R'; } dtgevc_(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, (ftnlen)1, (ftnlen)1); if (iinfo != 0) { *info = *n + 7; goto L120; } /* Undo balancing on VL and VR, rescale */ if (ilvl) { dggbak_("P", "L", n, &ilo, &ihi, &work[ileft], &work[iright], n, & vl[vl_offset], ldvl, &iinfo, (ftnlen)1, (ftnlen)1); if (iinfo != 0) { *info = *n + 8; goto L120; } i__1 = *n; for (jc = 1; jc <= i__1; ++jc) { if (alphai[jc] < 0.) { goto L50; } temp = 0.; if (alphai[jc] == 0.) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ d__2 = temp, d__3 = (d__1 = vl[jr + jc * vl_dim1], abs(d__1)); temp = max(d__2,d__3); /* L10: */ } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ d__3 = temp, d__4 = (d__1 = vl[jr + jc * vl_dim1], abs(d__1)) + (d__2 = vl[jr + (jc + 1) * vl_dim1], abs(d__2)); temp = max(d__3,d__4); /* L20: */ } } if (temp < safmin) { goto L50; } temp = 1. / temp; if (alphai[jc] == 0.) { 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) { dggbak_("P", "R", n, &ilo, &ihi, &work[ileft], &work[iright], n, & vr[vr_offset], ldvr, &iinfo, (ftnlen)1, (ftnlen)1); if (iinfo != 0) { *info = *n + 9; goto L120; } i__1 = *n; for (jc = 1; jc <= i__1; ++jc) { if (alphai[jc] < 0.) { goto L100; } temp = 0.; if (alphai[jc] == 0.) { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ d__2 = temp, d__3 = (d__1 = vr[jr + jc * vr_dim1], abs(d__1)); temp = max(d__2,d__3); /* L60: */ } } else { i__2 = *n; for (jr = 1; jr <= i__2; ++jr) { /* Computing MAX */ d__3 = temp, d__4 = (d__1 = vr[jr + jc * vr_dim1], abs(d__1)) + (d__2 = vr[jr + (jc + 1) * vr_dim1], abs(d__2)); temp = max(d__3,d__4); /* L70: */ } } if (temp < safmin) { goto L100; } temp = 1. / temp; if (alphai[jc] == 0.) { 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 = (d__1 = alphar[jc], abs(d__1)); absai = (d__1 = alphai[jc], abs(d__1)); absb = (d__1 = beta[jc], abs(d__1)); salfar = anrm * alphar[jc]; salfai = anrm * alphai[jc]; sbeta = bnrm * beta[jc]; ilimit = FALSE_; scale = 1.; /* Check for significant underflow in ALPHAI */ /* Computing MAX */ d__1 = safmin, d__2 = eps * absar, d__1 = max(d__1,d__2), d__2 = eps * absb; if (abs(salfai) < safmin && absai >= max(d__1,d__2)) { ilimit = TRUE_; /* Computing MAX */ d__1 = onepls * safmin, d__2 = anrm2 * absai; scale = onepls * safmin / anrm1 / max(d__1,d__2); } else if (salfai == 0.) { /* If insignificant underflow in ALPHAI, then make the */ /* conjugate eigenvalue real. */ if (alphai[jc] < 0. && jc > 1) { alphai[jc - 1] = 0.; } else if (alphai[jc] > 0. && jc < *n) { alphai[jc + 1] = 0.; } } /* Check for significant underflow in ALPHAR */ /* Computing MAX */ d__1 = safmin, d__2 = eps * absai, d__1 = max(d__1,d__2), d__2 = eps * absb; if (abs(salfar) < safmin && absar >= max(d__1,d__2)) { ilimit = TRUE_; /* Computing MAX */ /* Computing MAX */ d__3 = onepls * safmin, d__4 = anrm2 * absar; d__1 = scale, d__2 = onepls * safmin / anrm1 / max(d__3,d__4); scale = max(d__1,d__2); } /* Check for significant underflow in BETA */ /* Computing MAX */ d__1 = safmin, d__2 = eps * absar, d__1 = max(d__1,d__2), d__2 = eps * absai; if (abs(sbeta) < safmin && absb >= max(d__1,d__2)) { ilimit = TRUE_; /* Computing MAX */ /* Computing MAX */ d__3 = onepls * safmin, d__4 = bnrm2 * absb; d__1 = scale, d__2 = onepls * safmin / bnrm1 / max(d__3,d__4); scale = max(d__1,d__2); } /* Check for possible overflow when limiting scaling */ if (ilimit) { /* Computing MAX */ d__1 = abs(salfar), d__2 = abs(salfai), d__1 = max(d__1,d__2), d__2 = abs(sbeta); temp = scale * safmin * max(d__1,d__2); if (temp > 1.) { scale /= temp; } if (scale < 1.) { 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] = (doublereal) lwkopt; return 0; /* End of DGEGV */ } /* dgegv_ */
/* Subroutine */ int dqrt03_(integer *m, integer *n, integer *k, doublereal * af, doublereal *c__, doublereal *cc, doublereal *q, integer *lda, doublereal *tau, doublereal *work, integer *lwork, doublereal *rwork, doublereal *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; doublereal eps; char side[1]; integer info; extern /* Subroutine */ int dgemm_(char *, char *, integer *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *); integer iside; extern logical lsame_(char *, char *); doublereal resid, cnorm; char trans[1]; extern doublereal dlamch_(char *), dlange_(char *, integer *, integer *, doublereal *, integer *, doublereal *); extern /* Subroutine */ int dlacpy_(char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *), dlaset_(char *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *), dlarnv_(integer *, integer *, integer *, doublereal *), dorgqr_(integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *); integer itrans; extern /* Subroutine */ int dormqr_(char *, char *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *, 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 */ /* ======= */ /* DQRT03 tests DORMQR, which computes Q*C, Q'*C, C*Q or C*Q'. */ /* DQRT03 compares the results of a call to DORMQR with the results of */ /* forming Q explicitly by a call to DORGQR and then performing matrix */ /* multiplication by a call to DGEMM. */ /* 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) DOUBLE PRECISION array, dimension (LDA,N) */ /* Details of the QR factorization of an m-by-n matrix, as */ /* returnedby DGEQRF. See SGEQRF for further details. */ /* C (workspace) DOUBLE PRECISION array, dimension (LDA,N) */ /* CC (workspace) DOUBLE PRECISION array, dimension (LDA,N) */ /* Q (workspace) DOUBLE PRECISION array, dimension (LDA,M) */ /* LDA (input) INTEGER */ /* The leading dimension of the arrays AF, C, CC, and Q. */ /* TAU (input) DOUBLE PRECISION array, dimension (min(M,N)) */ /* The scalar factors of the elementary reflectors corresponding */ /* to the QR factorization in AF. */ /* WORK (workspace) DOUBLE PRECISION 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) DOUBLE PRECISION array, dimension (M) */ /* RESULT (output) DOUBLE PRECISION 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 = dlamch_("Epsilon"); /* Copy the first k columns of the factorization to the array Q */ dlaset_("Full", m, m, &c_b4, &c_b4, &q[q_offset], lda); i__1 = *m - 1; dlacpy_("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, "DORGQR", (ftnlen)6, (ftnlen)6); dorgqr_(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) { dlarnv_(&c__2, iseed, &mc, &c__[j * c_dim1 + 1]); /* L10: */ } cnorm = dlange_("1", &mc, &nc, &c__[c_offset], lda, &rwork[1]); if (cnorm == 0.) { cnorm = 1.; } for (itrans = 1; itrans <= 2; ++itrans) { if (itrans == 1) { *(unsigned char *)trans = 'N'; } else { *(unsigned char *)trans = 'T'; } /* Copy C */ dlacpy_("Full", &mc, &nc, &c__[c_offset], lda, &cc[cc_offset], lda); /* Apply Q or Q' to C */ s_copy(srnamc_1.srnamt, "DORMQR", (ftnlen)6, (ftnlen)6); dormqr_(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")) { dgemm_(trans, "No transpose", &mc, &nc, &mc, &c_b21, &q[ q_offset], lda, &c__[c_offset], lda, &c_b22, &cc[ cc_offset], lda); } else { dgemm_("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 = dlange_("1", &mc, &nc, &cc[cc_offset], lda, &rwork[1]); result[(iside - 1 << 1) + itrans] = resid / ((doublereal) max(1,* m) * cnorm * eps); /* L20: */ } /* L30: */ } return 0; /* End of DQRT03 */ } /* dqrt03_ */
/* Subroutine */ int dorgbr_(char *vect, integer *m, integer *n, integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *work, integer *lwork, integer *info) { /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3; /* Local variables */ integer i__, j, nb, mn; extern logical lsame_(char *, char *); integer iinfo; logical wantq; extern /* Subroutine */ int xerbla_(char *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *); extern /* Subroutine */ int dorglq_(integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *), dorgqr_(integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *); integer lwkopt; logical lquery; /* -- LAPACK routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DORGBR generates one of the real orthogonal matrices Q or P**T */ /* determined by DGEBRD 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) or G(i) respectively. */ /* If VECT = 'Q', A is assumed to have been an M-by-K matrix, and Q */ /* is of order M: */ /* if m >= k, Q = H(1) H(2) . . . H(k) and DORGBR returns the first n */ /* columns of Q, where m >= n >= k; */ /* if m < k, Q = H(1) H(2) . . . H(m-1) and DORGBR returns Q as an */ /* M-by-M matrix. */ /* If VECT = 'P', A is assumed to have been a K-by-N matrix, and P**T */ /* is of order N: */ /* if k < n, P**T = G(k) . . . G(2) G(1) and DORGBR returns the first m */ /* rows of P**T, where n >= m >= k; */ /* if k >= n, P**T = G(n-1) . . . G(2) G(1) and DORGBR returns P**T as */ /* an N-by-N matrix. */ /* Arguments */ /* ========= */ /* VECT (input) CHARACTER*1 */ /* Specifies whether the matrix Q or the matrix P**T is */ /* required, as defined in the transformation applied by DGEBRD: */ /* = 'Q': generate Q; */ /* = 'P': generate P**T. */ /* M (input) INTEGER */ /* The number of rows of the matrix Q or P**T to be returned. */ /* M >= 0. */ /* N (input) INTEGER */ /* The number of columns of the matrix Q or P**T to be returned. */ /* N >= 0. */ /* If VECT = 'Q', M >= N >= min(M,K); */ /* if VECT = 'P', N >= M >= min(N,K). */ /* K (input) INTEGER */ /* If VECT = 'Q', the number of columns in the original M-by-K */ /* matrix reduced by DGEBRD. */ /* If VECT = 'P', the number of rows in the original K-by-N */ /* matrix reduced by DGEBRD. */ /* K >= 0. */ /* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) */ /* On entry, the vectors which define the elementary reflectors, */ /* as returned by DGEBRD. */ /* On exit, the M-by-N matrix Q or P**T. */ /* LDA (input) INTEGER */ /* The leading dimension of the array A. LDA >= max(1,M). */ /* TAU (input) DOUBLE PRECISION array, dimension */ /* (min(M,K)) if VECT = 'Q' */ /* (min(N,K)) if VECT = 'P' */ /* TAU(i) must contain the scalar factor of the elementary */ /* reflector H(i) or G(i), which determines Q or P**T, as */ /* returned by DGEBRD in its array argument TAUQ or TAUP. */ /* WORK (workspace/output) DOUBLE PRECISION 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,min(M,N)). */ /* For optimum performance LWORK >= min(M,N)*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 */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. 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; --work; /* Function Body */ *info = 0; wantq = lsame_(vect, "Q"); mn = min(*m,*n); lquery = *lwork == -1; if (! wantq && ! lsame_(vect, "P")) { *info = -1; } else if (*m < 0) { *info = -2; } else if (*n < 0 || wantq && (*n > *m || *n < min(*m,*k)) || ! wantq && ( *m > *n || *m < min(*n,*k))) { *info = -3; } else if (*k < 0) { *info = -4; } else if (*lda < max(1,*m)) { *info = -6; } else if (*lwork < max(1,mn) && ! lquery) { *info = -9; } if (*info == 0) { if (wantq) { nb = ilaenv_(&c__1, "DORGQR", " ", m, n, k, &c_n1); } else { nb = ilaenv_(&c__1, "DORGLQ", " ", m, n, k, &c_n1); } lwkopt = max(1,mn) * nb; work[1] = (doublereal) lwkopt; } if (*info != 0) { i__1 = -(*info); xerbla_("DORGBR", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*m == 0 || *n == 0) { work[1] = 1.; return 0; } if (wantq) { /* Form Q, determined by a call to DGEBRD to reduce an m-by-k */ /* matrix */ if (*m >= *k) { /* If m >= k, assume m >= n >= k */ dorgqr_(m, n, k, &a[a_offset], lda, &tau[1], &work[1], lwork, & iinfo); } else { /* If m < k, assume m = n */ /* Shift the vectors which define the elementary reflectors one */ /* column to the right, and set the first row and column of Q */ /* to those of the unit matrix */ for (j = *m; j >= 2; --j) { a[j * a_dim1 + 1] = 0.; i__1 = *m; for (i__ = j + 1; i__ <= i__1; ++i__) { a[i__ + j * a_dim1] = a[i__ + (j - 1) * a_dim1]; /* L10: */ } /* L20: */ } a[a_dim1 + 1] = 1.; i__1 = *m; for (i__ = 2; i__ <= i__1; ++i__) { a[i__ + a_dim1] = 0.; /* L30: */ } if (*m > 1) { /* Form Q(2:m,2:m) */ i__1 = *m - 1; i__2 = *m - 1; i__3 = *m - 1; dorgqr_(&i__1, &i__2, &i__3, &a[(a_dim1 << 1) + 2], lda, &tau[ 1], &work[1], lwork, &iinfo); } } } else { /* Form P', determined by a call to DGEBRD to reduce a k-by-n */ /* matrix */ if (*k < *n) { /* If k < n, assume k <= m <= n */ dorglq_(m, n, k, &a[a_offset], lda, &tau[1], &work[1], lwork, & iinfo); } else { /* If k >= n, assume m = n */ /* Shift the vectors which define the elementary reflectors one */ /* row downward, and set the first row and column of P' to */ /* those of the unit matrix */ a[a_dim1 + 1] = 1.; i__1 = *n; for (i__ = 2; i__ <= i__1; ++i__) { a[i__ + a_dim1] = 0.; /* L40: */ } i__1 = *n; for (j = 2; j <= i__1; ++j) { for (i__ = j - 1; i__ >= 2; --i__) { a[i__ + j * a_dim1] = a[i__ - 1 + j * a_dim1]; /* L50: */ } a[j * a_dim1 + 1] = 0.; /* L60: */ } if (*n > 1) { /* Form P'(2:n,2:n) */ i__1 = *n - 1; i__2 = *n - 1; i__3 = *n - 1; dorglq_(&i__1, &i__2, &i__3, &a[(a_dim1 << 1) + 2], lda, &tau[ 1], &work[1], lwork, &iinfo); } } } work[1] = (doublereal) lwkopt; return 0; /* End of DORGBR */ } /* dorgbr_ */
gretl_matrix *model_leverage (const MODEL *pmod, DATASET *dset, gretlopt opt, PRN *prn, int *err) { integer info, lwork; integer m, n, lda; gretl_matrix *Q, *S = NULL; doublereal *tau, *work; double Xvalcrit; int i, j, s, t, vi; /* allow for missing obs in model range */ int modn = pmod->t2 - pmod->t1 + 1; m = pmod->nobs; /* # of rows = # of observations */ lda = m; /* leading dimension of Q */ n = pmod->list[0] - 1; /* # of cols = # of variables */ Q = gretl_matrix_alloc(m, n); /* dim of tau is min (m, n) */ tau = malloc(n * sizeof *tau); work = malloc(sizeof *work); if (Q == NULL || tau == NULL || work == NULL) { *err = E_ALLOC; goto qr_cleanup; } /* copy independent var values into Q, skipping missing obs */ j = 0; for (i=2; i<=pmod->list[0]; i++) { vi = pmod->list[i]; for (t=pmod->t1; t<=pmod->t2; t++) { if (!na(pmod->uhat[t])) { Q->val[j++] = dset->Z[vi][t]; } } } /* do a workspace size query */ lwork = -1; info = 0; dgeqrf_(&m, &n, Q->val, &lda, tau, work, &lwork, &info); if (info != 0) { fprintf(stderr, "dgeqrf: info = %d\n", (int) info); *err = 1; goto qr_cleanup; } /* set up optimally sized work array */ lwork = (integer) work[0]; work = realloc(work, (size_t) lwork * sizeof *work); if (work == NULL) { *err = E_ALLOC; goto qr_cleanup; } /* run actual QR factorization */ dgeqrf_(&m, &n, Q->val, &lda, tau, work, &lwork, &info); if (info != 0) { fprintf(stderr, "dgeqrf: info = %d\n", (int) info); *err = 1; goto qr_cleanup; } /* obtain the real "Q" matrix */ dorgqr_(&m, &n, &n, Q->val, &lda, tau, work, &lwork, &info); if (info != 0) { *err = 1; goto qr_cleanup; } S = gretl_matrix_alloc(modn, 3); if (S == NULL) { *err = E_ALLOC; goto qr_cleanup; } gretl_matrix_set_t1(S, pmod->t1); /* do the "h" calculations */ s = 0; for (t=pmod->t1, j=0; t<=pmod->t2; t++, j++) { double q, h; if (na(pmod->uhat[t])) { h = NADBL; } else { h = 0.0; for (i=0; i<n; i++) { q = gretl_matrix_get(Q, s, i); h += q * q; } s++; } gretl_matrix_set(S, j, 0, h); } Xvalcrit = 0.0; /* compute the influence series and the cross-validation criterion */ for (t=pmod->t1, j=0; t<=pmod->t2; t++, j++) { double f = NADBL; if (!na(pmod->uhat[t])) { double h = gretl_matrix_get(S, j, 0); if (h < 1.0) { f = pmod->uhat[t] / (1.0 - h); Xvalcrit += f * f; f -= pmod->uhat[t]; } } gretl_matrix_set(S, j, 1, f); } record_test_result(Xvalcrit, NADBL, _("Cross-validation criterion")); /* put studentized residuals into S[,2] */ studentized_residuals(pmod, S); /* print the results, unless in quiet mode */ if (!(opt & OPT_Q)) { leverage_print(pmod, S, Xvalcrit, dset, prn); if (gnuplot_graph_wanted(PLOT_LEVERAGE, opt)) { leverage_plot(pmod, S, dset); } } qr_cleanup: gretl_matrix_free(Q); free(tau); free(work); return S; }
/* Subroutine */ int dorgtr_(char *uplo, integer *n, doublereal *a, integer * lda, doublereal *tau, doublereal *work, integer *lwork, integer *info, ftnlen uplo_len) { /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3; /* Local variables */ static integer i__, j, nb; extern logical lsame_(char *, char *, ftnlen, ftnlen); static integer iinfo; static logical upper; extern /* Subroutine */ int xerbla_(char *, integer *, ftnlen); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *, ftnlen, ftnlen); extern /* Subroutine */ int dorgql_(integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *), dorgqr_(integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *); static integer lwkopt; static logical lquery; /* -- 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 */ /* ======= */ /* DORGTR generates a real orthogonal matrix Q which is defined as the */ /* product of n-1 elementary reflectors of order N, as returned by */ /* DSYTRD: */ /* if UPLO = 'U', Q = H(n-1) . . . H(2) H(1), */ /* if UPLO = 'L', Q = H(1) H(2) . . . H(n-1). */ /* Arguments */ /* ========= */ /* UPLO (input) CHARACTER*1 */ /* = 'U': Upper triangle of A contains elementary reflectors */ /* from DSYTRD; */ /* = 'L': Lower triangle of A contains elementary reflectors */ /* from DSYTRD. */ /* N (input) INTEGER */ /* The order of the matrix Q. N >= 0. */ /* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) */ /* On entry, the vectors which define the elementary reflectors, */ /* as returned by DSYTRD. */ /* On exit, the N-by-N orthogonal matrix Q. */ /* LDA (input) INTEGER */ /* The leading dimension of the array A. LDA >= max(1,N). */ /* TAU (input) DOUBLE PRECISION array, dimension (N-1) */ /* TAU(i) must contain the scalar factor of the elementary */ /* reflector H(i), as returned by DSYTRD. */ /* WORK (workspace/output) DOUBLE PRECISION 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-1). */ /* For optimum performance LWORK >= (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 */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. 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; --work; /* Function Body */ *info = 0; lquery = *lwork == -1; upper = lsame_(uplo, "U", (ftnlen)1, (ftnlen)1); if (! upper && ! lsame_(uplo, "L", (ftnlen)1, (ftnlen)1)) { *info = -1; } else if (*n < 0) { *info = -2; } else if (*lda < max(1,*n)) { *info = -4; } else /* if(complicated condition) */ { /* Computing MAX */ i__1 = 1, i__2 = *n - 1; if (*lwork < max(i__1,i__2) && ! lquery) { *info = -7; } } if (*info == 0) { if (upper) { i__1 = *n - 1; i__2 = *n - 1; i__3 = *n - 1; nb = ilaenv_(&c__1, "DORGQL", " ", &i__1, &i__2, &i__3, &c_n1, ( ftnlen)6, (ftnlen)1); } else { i__1 = *n - 1; i__2 = *n - 1; i__3 = *n - 1; nb = ilaenv_(&c__1, "DORGQR", " ", &i__1, &i__2, &i__3, &c_n1, ( ftnlen)6, (ftnlen)1); } /* Computing MAX */ i__1 = 1, i__2 = *n - 1; lwkopt = max(i__1,i__2) * nb; work[1] = (doublereal) lwkopt; } if (*info != 0) { i__1 = -(*info); xerbla_("DORGTR", &i__1, (ftnlen)6); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*n == 0) { work[1] = 1.; return 0; } if (upper) { /* Q was determined by a call to DSYTRD with UPLO = 'U' */ /* Shift the vectors which define the elementary reflectors one */ /* column to the left, and set the last row and column of Q to */ /* those of the unit matrix */ i__1 = *n - 1; for (j = 1; j <= i__1; ++j) { i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { a[i__ + j * a_dim1] = a[i__ + (j + 1) * a_dim1]; /* L10: */ } a[*n + j * a_dim1] = 0.; /* L20: */ } i__1 = *n - 1; for (i__ = 1; i__ <= i__1; ++i__) { a[i__ + *n * a_dim1] = 0.; /* L30: */ } a[*n + *n * a_dim1] = 1.; /* Generate Q(1:n-1,1:n-1) */ i__1 = *n - 1; i__2 = *n - 1; i__3 = *n - 1; dorgql_(&i__1, &i__2, &i__3, &a[a_offset], lda, &tau[1], &work[1], lwork, &iinfo); } else { /* Q was determined by a call to DSYTRD with UPLO = 'L'. */ /* Shift the vectors which define the elementary reflectors one */ /* column to the right, and set the first row and column of Q to */ /* those of the unit matrix */ for (j = *n; j >= 2; --j) { a[j * a_dim1 + 1] = 0.; i__1 = *n; for (i__ = j + 1; i__ <= i__1; ++i__) { a[i__ + j * a_dim1] = a[i__ + (j - 1) * a_dim1]; /* L40: */ } /* L50: */ } a[a_dim1 + 1] = 1.; i__1 = *n; for (i__ = 2; i__ <= i__1; ++i__) { a[i__ + a_dim1] = 0.; /* L60: */ } if (*n > 1) { /* Generate Q(2:n,2:n) */ i__1 = *n - 1; i__2 = *n - 1; i__3 = *n - 1; dorgqr_(&i__1, &i__2, &i__3, &a[(a_dim1 << 1) + 2], lda, &tau[1], &work[1], lwork, &iinfo); } } work[1] = (doublereal) lwkopt; return 0; /* End of DORGTR */ } /* dorgtr_ */
GURLS_EXPORT void orgqr(int *m, int *n, int *k, double *a, int *lda, double *tau, double *work, int *lwork, int *info) { dorgqr_(m, n, k, a, lda, tau, work, lwork, info); }
void Stiefel::qfRetraction(Variable *x, Vector *etax, Variable *result) const { //x->Print("x in qf:");//--- const double *U = x->ObtainReadData(); const double *V; Vector *exetax = nullptr; if (IsIntrApproach) { exetax = EMPTYEXTR->ConstructEmpty(); ObtainExtr(x, etax, exetax); V = exetax->ObtainReadData(); //exetax->Print("exetax:");//--- } else { V = etax->ObtainReadData(); } double *resultM = result->ObtainWriteEntireData(); SharedSpace *HouseHolderResult = new SharedSpace(2, x->Getsize()[0], x->Getsize()[1]); double *ptrHHR = HouseHolderResult->ObtainWriteEntireData(); SharedSpace *HHRTau = new SharedSpace(1, x->Getsize()[1]); double *tau = HHRTau->ObtainWriteEntireData(); integer N = x->Getsize()[0], P = x->Getsize()[1], Length = N * P, inc = 1; double one = 1, zero = 0; dcopy_(&Length, const_cast<double *> (V), &inc, ptrHHR, &inc); daxpy_(&Length, &one, const_cast<double *> (U), &inc, ptrHHR, &inc); integer *jpvt = new integer[P]; integer info; integer lwork = -1; double lworkopt; for (integer i = 0; i < P; i++) jpvt[i] = i + 1; dgeqp3_(&N, &P, ptrHHR, &N, jpvt, tau, &lworkopt, &lwork, &info); lwork = static_cast<integer> (lworkopt); double *work = new double[lwork]; dgeqp3_(&N, &P, ptrHHR, &N, jpvt, tau, work, &lwork, &info); if (info < 0) Rcpp::Rcout << "Error in qr decomposition!" << std::endl; for (integer i = 0; i < P; i++) { if (jpvt[i] != (i + 1)) Rcpp::Rcout << "Error in qf retraction!" << std::endl; } double *signs = new double[P]; for (integer i = 0; i < P; i++) signs[i] = (ptrHHR[i + i * N] >= 0) ? 1 : -1; dcopy_(&Length, ptrHHR, &inc, resultM, &inc); dorgqr_(&N, &P, &P, resultM, &N, tau, work, &lwork, &info); if (info < 0) Rcpp::Rcout << "Error in forming Q matrix!" << std::endl; for (integer i = 0; i < P; i++) dscal_(&N, signs + i, resultM + i * N, &inc); result->AddToTempData("HHR", HouseHolderResult); result->AddToTempData("HHRTau", HHRTau); delete[] jpvt; delete[] work; delete[] signs; if (exetax != nullptr) delete exetax; //result->Print("result in qf:");//--- };
int constrained_least_squares(int m, int n, double **matrix, int c, int *constrained) { //check problem dimensions if(m < 1 || n < 1 || n > m || c > n) return LS_DIMENSION_ERROR; //counters int i, j; //extra problem dimensions int f = m - c, u = n - c; //lapack and blas inputs char transa, transb; double alpha, beta; //lapack output int info; //lapack workspace int lwork = m*m; double *work; if(!allocate_double_vector(&work, lwork)) { return LS_MEMORY_ERROR; } //lapack LU pivot indices int *ipiv; if(!allocate_integer_vector(&ipiv,c)) { return LS_MEMORY_ERROR; } //lapack coefficients of QR elementary reflectors double *tau; if(!allocate_double_vector(&tau,c)) { return LS_MEMORY_ERROR; } //matrices used double **t_matrix; if(!allocate_double_matrix(&t_matrix, m, m)) { return LS_MEMORY_ERROR; } double **c_matrix; if(!allocate_double_matrix(&c_matrix, n, n)) { return LS_MEMORY_ERROR; } double **r_matrix; if(!allocate_double_matrix(&r_matrix, c, c)) { return LS_MEMORY_ERROR; } double **a_matrix; if(!allocate_double_matrix(&a_matrix, n, f)) { return LS_MEMORY_ERROR; } double **d_matrix; if(!allocate_double_matrix(&d_matrix, f, f)) { return LS_MEMORY_ERROR; } //indices of unconstrained equations int *temp, *unconstrained; if(!allocate_integer_vector(&temp,m)) { return LS_MEMORY_ERROR; } if(!allocate_integer_vector(&unconstrained,f)) { return LS_MEMORY_ERROR; } //create vector of unconstrained indices for(i = 0; i < m; i ++) temp[i] = 0; for(i = 0; i < c; i ++) temp[constrained[i]] = 1; j = 0; for(i = 0; i < m; i ++) if(!temp[i]) unconstrained[j++] = i; //copy unconstrained equations from input matrix -> t_matrix for(i = 0; i < f; i ++) for(j = 0; j < n; j ++) t_matrix[i][j] = matrix[j][unconstrained[i]]; //copy constrained equations from input matrix -> c_matrix for(i = 0; i < c; i ++) for(j = 0; j < n; j ++) c_matrix[i][j] = matrix[j][constrained[i]]; //QR decomposition of the transposed constrained equations -> c_matrix dgeqrf_(&n, &c, c_matrix[0], &n, tau, work, &lwork, &info); //copy R out of the above QR decomposition -> r_matrix for(i = 0; i < c; i ++) for(j = 0; j < c; j ++) r_matrix[i][j] = ((j >= i) ? c_matrix[j][i] : 0); //form the square matrix Q from the above QR decomposition -> c_matrix' dorgqr_(&n, &n, &c, c_matrix[0], &n, tau, work, &lwork, &info); //multiply unconstrained eqations by Q -> a_matrix' transa = 'T'; transb = 'N'; alpha = 1.0; beta = 0.0; dgemm_(&transa, &transb, &f, &n, &n, &alpha, t_matrix[0], &m, c_matrix[0], &n, &beta, a_matrix[0], &f); //invert R' of the above QR decomposition -> r_matrix dgetrf_(&c, &c, r_matrix[0], &c, ipiv, &info); dgetri_(&c, r_matrix[0], &c, ipiv, work, &lwork, &info); //LS inversion of the non-square parts from unconstrained * Q -> d_matrix' for(i = 0; i < f; i ++) for(j = 0; j < u; j ++) t_matrix[j][i] = a_matrix[j+c][i]; for(i = 0; i < f; i ++) for(j = 0; j < f; j ++) d_matrix[i][j] = (i == j); transa = 'N'; dgels_(&transa, &f, &u, &f, t_matrix[0], &m, d_matrix[0], &f, work, &lwork, &info); //multiply matrices together to form the CLS solution -> t_matrix' transa = transb = 'N'; alpha = 1.0; beta = 0.0; dgemm_(&transa, &transb, &n, &f, &u, &alpha, c_matrix[c], &n, d_matrix[0], &f, &beta, t_matrix[0], &m); alpha = -1.0; beta = 1.0; dgemm_(&transa, &transb, &n, &c, &f, &alpha, t_matrix[0], &m, a_matrix[0], &f, &beta, c_matrix[0], &n); alpha = 1.0; beta = 0.0; dgemm_(&transa, &transb, &n, &c, &c, &alpha, c_matrix[0], &n, r_matrix[0], &c, &beta, t_matrix[f], &m); //copy the result out of the temporary matrix -> matrix for(i = 0; i < n; i ++) for(j = 0; j < f; j ++) matrix[i][unconstrained[j]] = t_matrix[j][i]; for(i = 0; i < n; i ++) for(j = 0; j < c; j ++) matrix[i][constrained[j]] = t_matrix[j+f][i]; //clean up and return successful free_vector(work); free_vector(ipiv); free_vector(tau); free_vector(temp); free_vector(unconstrained); free_matrix((void **)t_matrix); free_matrix((void **)c_matrix); free_matrix((void **)r_matrix); free_matrix((void **)a_matrix); free_matrix((void **)d_matrix); return LS_SUCCESS; }
/* Subroutine */ int dgqrts_(integer *n, integer *m, integer *p, doublereal * a, doublereal *af, doublereal *q, doublereal *r__, integer *lda, doublereal *taua, doublereal *b, doublereal *bf, doublereal *z__, doublereal *t, doublereal *bwk, integer *ldb, doublereal *taub, doublereal *work, integer *lwork, doublereal *rwork, doublereal * result) { /* System generated locals */ integer a_dim1, a_offset, af_dim1, af_offset, b_dim1, b_offset, bf_dim1, bf_offset, bwk_dim1, bwk_offset, q_dim1, q_offset, r_dim1, r_offset, t_dim1, t_offset, z_dim1, z_offset, i__1, i__2; doublereal d__1; /* Local variables */ static integer info; static doublereal unfl; extern /* Subroutine */ int dgemm_(char *, char *, integer *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *); static doublereal resid, anorm, bnorm; extern /* Subroutine */ int dsyrk_(char *, char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, integer *); extern doublereal dlamch_(char *), dlange_(char *, integer *, integer *, doublereal *, integer *, doublereal *); extern /* Subroutine */ int dggqrf_(integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *), dlacpy_(char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *), dlaset_(char *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *); extern doublereal dlansy_(char *, char *, integer *, doublereal *, integer *, doublereal *); extern /* Subroutine */ int dorgqr_(integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *), dorgrq_(integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *); static doublereal ulp; #define q_ref(a_1,a_2) q[(a_2)*q_dim1 + a_1] #define t_ref(a_1,a_2) t[(a_2)*t_dim1 + a_1] #define z___ref(a_1,a_2) z__[(a_2)*z_dim1 + a_1] #define af_ref(a_1,a_2) af[(a_2)*af_dim1 + a_1] #define bf_ref(a_1,a_2) bf[(a_2)*bf_dim1 + a_1] /* -- LAPACK test routine (version 3.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University September 30, 1994 Purpose ======= DGQRTS tests DGGQRF, which computes the GQR factorization of an N-by-M matrix A and a N-by-P matrix B: A = Q*R and B = Q*T*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) DOUBLE PRECISION array, dimension (LDA,M) The N-by-M matrix A. AF (output) DOUBLE PRECISION array, dimension (LDA,N) Details of the GQR factorization of A and B, as returned by DGGQRF, see SGGQRF for further details. Q (output) DOUBLE PRECISION array, dimension (LDA,N) The M-by-M orthogonal matrix Q. R (workspace) DOUBLE PRECISION array, dimension (LDA,MAX(M,N)) LDA (input) INTEGER The leading dimension of the arrays A, AF, R and Q. LDA >= max(M,N). TAUA (output) DOUBLE PRECISION array, dimension (min(M,N)) The scalar factors of the elementary reflectors, as returned by DGGQRF. B (input) DOUBLE PRECISION array, dimension (LDB,P) On entry, the N-by-P matrix A. BF (output) DOUBLE PRECISION array, dimension (LDB,N) Details of the GQR factorization of A and B, as returned by DGGQRF, see SGGQRF for further details. Z (output) DOUBLE PRECISION array, dimension (LDB,P) The P-by-P orthogonal matrix Z. T (workspace) DOUBLE PRECISION array, dimension (LDB,max(P,N)) BWK (workspace) DOUBLE PRECISION array, dimension (LDB,N) LDB (input) INTEGER The leading dimension of the arrays B, BF, Z and T. LDB >= max(P,N). TAUB (output) DOUBLE PRECISION array, dimension (min(P,N)) The scalar factors of the elementary reflectors, as returned by DGGRQF. WORK (workspace) DOUBLE PRECISION array, dimension (LWORK) LWORK (input) INTEGER The dimension of the array WORK, LWORK >= max(N,M,P)**2. RWORK (workspace) DOUBLE PRECISION array, dimension (max(N,M,P)) RESULT (output) DOUBLE PRECISION array, dimension (4) The test ratios: RESULT(1) = norm( R - Q'*A ) / ( MAX(M,N)*norm(A)*ULP) RESULT(2) = norm( T*Z - Q'*B ) / (MAX(P,N)*norm(B)*ULP) RESULT(3) = norm( I - Q'*Q ) / ( M*ULP ) RESULT(4) = norm( I - Z'*Z ) / ( P*ULP ) ===================================================================== Parameter adjustments */ r_dim1 = *lda; r_offset = 1 + r_dim1 * 1; r__ -= r_offset; q_dim1 = *lda; q_offset = 1 + q_dim1 * 1; q -= q_offset; af_dim1 = *lda; af_offset = 1 + af_dim1 * 1; af -= af_offset; a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; --taua; bwk_dim1 = *ldb; bwk_offset = 1 + bwk_dim1 * 1; bwk -= bwk_offset; t_dim1 = *ldb; t_offset = 1 + t_dim1 * 1; t -= t_offset; z_dim1 = *ldb; z_offset = 1 + z_dim1 * 1; z__ -= z_offset; bf_dim1 = *ldb; bf_offset = 1 + bf_dim1 * 1; bf -= bf_offset; b_dim1 = *ldb; b_offset = 1 + b_dim1 * 1; b -= b_offset; --taub; --work; --rwork; --result; /* Function Body */ ulp = dlamch_("Precision"); unfl = dlamch_("Safe minimum"); /* Copy the matrix A to the array AF. */ dlacpy_("Full", n, m, &a[a_offset], lda, &af[af_offset], lda); dlacpy_("Full", n, p, &b[b_offset], ldb, &bf[bf_offset], ldb); /* Computing MAX */ d__1 = dlange_("1", n, m, &a[a_offset], lda, &rwork[1]); anorm = max(d__1,unfl); /* Computing MAX */ d__1 = dlange_("1", n, p, &b[b_offset], ldb, &rwork[1]); bnorm = max(d__1,unfl); /* Factorize the matrices A and B in the arrays AF and BF. */ dggqrf_(n, m, p, &af[af_offset], lda, &taua[1], &bf[bf_offset], ldb, & taub[1], &work[1], lwork, &info); /* Generate the N-by-N matrix Q */ dlaset_("Full", n, n, &c_b9, &c_b9, &q[q_offset], lda); i__1 = *n - 1; dlacpy_("Lower", &i__1, m, &af_ref(2, 1), lda, &q_ref(2, 1), lda); i__1 = min(*n,*m); dorgqr_(n, n, &i__1, &q[q_offset], lda, &taua[1], &work[1], lwork, &info); /* Generate the P-by-P matrix Z */ dlaset_("Full", p, p, &c_b9, &c_b9, &z__[z_offset], ldb); if (*n <= *p) { if (*n > 0 && *n < *p) { i__1 = *p - *n; dlacpy_("Full", n, &i__1, &bf[bf_offset], ldb, &z___ref(*p - *n + 1, 1), ldb); } if (*n > 1) { i__1 = *n - 1; i__2 = *n - 1; dlacpy_("Lower", &i__1, &i__2, &bf_ref(2, *p - *n + 1), ldb, & z___ref(*p - *n + 2, *p - *n + 1), ldb); } } else { if (*p > 1) { i__1 = *p - 1; i__2 = *p - 1; dlacpy_("Lower", &i__1, &i__2, &bf_ref(*n - *p + 2, 1), ldb, & z___ref(2, 1), ldb); } } i__1 = min(*n,*p); dorgrq_(p, p, &i__1, &z__[z_offset], ldb, &taub[1], &work[1], lwork, & info); /* Copy R */ dlaset_("Full", n, m, &c_b19, &c_b19, &r__[r_offset], lda); dlacpy_("Upper", n, m, &af[af_offset], lda, &r__[r_offset], lda); /* Copy T */ dlaset_("Full", n, p, &c_b19, &c_b19, &t[t_offset], ldb); if (*n <= *p) { dlacpy_("Upper", n, n, &bf_ref(1, *p - *n + 1), ldb, &t_ref(1, *p - * n + 1), ldb); } else { i__1 = *n - *p; dlacpy_("Full", &i__1, p, &bf[bf_offset], ldb, &t[t_offset], ldb); dlacpy_("Upper", p, p, &bf_ref(*n - *p + 1, 1), ldb, &t_ref(*n - *p + 1, 1), ldb); } /* Compute R - Q'*A */ dgemm_("Transpose", "No transpose", n, m, n, &c_b30, &q[q_offset], lda, & a[a_offset], lda, &c_b31, &r__[r_offset], lda); /* Compute norm( R - Q'*A ) / ( MAX(M,N)*norm(A)*ULP ) . */ resid = dlange_("1", n, m, &r__[r_offset], lda, &rwork[1]); if (anorm > 0.) { /* Computing MAX */ i__1 = max(1,*m); result[1] = resid / (doublereal) max(i__1,*n) / anorm / ulp; } else { result[1] = 0.; } /* Compute T*Z - Q'*B */ dgemm_("No Transpose", "No transpose", n, p, p, &c_b31, &t[t_offset], ldb, &z__[z_offset], ldb, &c_b19, &bwk[bwk_offset], ldb); dgemm_("Transpose", "No transpose", n, p, n, &c_b30, &q[q_offset], lda, & b[b_offset], ldb, &c_b31, &bwk[bwk_offset], ldb); /* Compute norm( T*Z - Q'*B ) / ( MAX(P,N)*norm(A)*ULP ) . */ resid = dlange_("1", n, p, &bwk[bwk_offset], ldb, &rwork[1]); if (bnorm > 0.) { /* Computing MAX */ i__1 = max(1,*p); result[2] = resid / (doublereal) max(i__1,*n) / bnorm / ulp; } else { result[2] = 0.; } /* Compute I - Q'*Q */ dlaset_("Full", n, n, &c_b19, &c_b31, &r__[r_offset], lda); dsyrk_("Upper", "Transpose", n, n, &c_b30, &q[q_offset], lda, &c_b31, & r__[r_offset], lda); /* Compute norm( I - Q'*Q ) / ( N * ULP ) . */ resid = dlansy_("1", "Upper", n, &r__[r_offset], lda, &rwork[1]); result[3] = resid / (doublereal) max(1,*n) / ulp; /* Compute I - Z'*Z */ dlaset_("Full", p, p, &c_b19, &c_b31, &t[t_offset], ldb); dsyrk_("Upper", "Transpose", p, p, &c_b30, &z__[z_offset], ldb, &c_b31, & t[t_offset], ldb); /* Compute norm( I - Z'*Z ) / ( P*ULP ) . */ resid = dlansy_("1", "Upper", p, &t[t_offset], ldb, &rwork[1]); result[4] = resid / (doublereal) max(1,*p) / ulp; return 0; /* End of DGQRTS */ } /* dgqrts_ */