/* -- translated by f2c (version 20201020 (for_lapack)). -- */ #include "f2c.h" //> \brief \b DAXPY // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // // Definition: // =========== // // SUBROUTINE DAXPY(N,DA,DX,INCX,DY,INCY) // // .. Scalar Arguments .. // DOUBLE PRECISION DA // INTEGER INCX,INCY,N // .. // .. Array Arguments .. // DOUBLE PRECISION DX(*),DY(*) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> DAXPY constant times a vector plus a vector. //> uses unrolled loops for increments equal to one. //> \endverbatim // // Arguments: // ========== // //> \param[in] N //> \verbatim //> N is INTEGER //> number of elements in input vector(s) //> \endverbatim //> //> \param[in] DA //> \verbatim //> DA is DOUBLE PRECISION //> On entry, DA specifies the scalar alpha. //> \endverbatim //> //> \param[in] DX //> \verbatim //> DX is DOUBLE PRECISION array, dimension ( 1 + ( N - 1 )*abs( INCX ) ) //> \endverbatim //> //> \param[in] INCX //> \verbatim //> INCX is INTEGER //> storage spacing between elements of DX //> \endverbatim //> //> \param[in,out] DY //> \verbatim //> DY is DOUBLE PRECISION array, dimension ( 1 + ( N - 1 )*abs( INCY ) ) //> \endverbatim //> //> \param[in] INCY //> \verbatim //> INCY is INTEGER //> storage spacing between elements of DY //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date November 2017 // //> \ingroup double_blas_level1 // //> \par Further Details: // ===================== //> //> \verbatim //> //> jack dongarra, linpack, 3/11/78. //> modified 12/3/93, array(1) declarations changed to array(*) //> \endverbatim //> // ===================================================================== /* Subroutine */ int daxpy_(int *n, double *da, double *dx, int *incx, double *dy, int *incy) { // System generated locals int i__1; // Local variables int i__, m, ix, iy, mp1; // // -- Reference BLAS level1 routine (version 3.8.0) -- // -- Reference BLAS is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // November 2017 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // // ===================================================================== // // .. Local Scalars .. // .. // .. Intrinsic Functions .. // .. // Parameter adjustments --dy; --dx; // Function Body if (*n <= 0) { return 0; } if (*da == 0.) { return 0; } if (*incx == 1 && *incy == 1) { // // code for both increments equal to 1 // // // clean-up loop // m = *n % 4; if (m != 0) { i__1 = m; for (i__ = 1; i__ <= i__1; ++i__) { dy[i__] += *da * dx[i__]; } } if (*n < 4) { return 0; } mp1 = m + 1; i__1 = *n; for (i__ = mp1; i__ <= i__1; i__ += 4) { dy[i__] += *da * dx[i__]; dy[i__ + 1] += *da * dx[i__ + 1]; dy[i__ + 2] += *da * dx[i__ + 2]; dy[i__ + 3] += *da * dx[i__ + 3]; } } else { // // code for unequal increments or equal increments // not equal to 1 // ix = 1; iy = 1; if (*incx < 0) { ix = (-(*n) + 1) * *incx + 1; } if (*incy < 0) { iy = (-(*n) + 1) * *incy + 1; } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { dy[iy] += *da * dx[ix]; ix += *incx; iy += *incy; } } return 0; } // daxpy_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DGEBAK // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DGEBAK + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DGEBAK( JOB, SIDE, N, ILO, IHI, SCALE, M, V, LDV, // INFO ) // // .. Scalar Arguments .. // CHARACTER JOB, SIDE // INTEGER IHI, ILO, INFO, LDV, M, N // .. // .. Array Arguments .. // DOUBLE PRECISION SCALE( * ), V( LDV, * ) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> DGEBAK forms the right or left eigenvectors of a real general matrix //> by backward transformation on the computed eigenvectors of the //> balanced matrix output by DGEBAL. //> \endverbatim // // Arguments: // ========== // //> \param[in] JOB //> \verbatim //> JOB is CHARACTER*1 //> Specifies the type of backward transformation required: //> = 'N': do nothing, return immediately; //> = 'P': do backward transformation for permutation only; //> = 'S': do backward transformation for scaling only; //> = 'B': do backward transformations for both permutation and //> scaling. //> JOB must be the same as the argument JOB supplied to DGEBAL. //> \endverbatim //> //> \param[in] SIDE //> \verbatim //> SIDE is CHARACTER*1 //> = 'R': V contains right eigenvectors; //> = 'L': V contains left eigenvectors. //> \endverbatim //> //> \param[in] N //> \verbatim //> N is INTEGER //> The number of rows of the matrix V. N >= 0. //> \endverbatim //> //> \param[in] ILO //> \verbatim //> ILO is INTEGER //> \endverbatim //> //> \param[in] IHI //> \verbatim //> IHI is INTEGER //> The integers ILO and IHI determined by DGEBAL. //> 1 <= ILO <= IHI <= N, if N > 0; ILO=1 and IHI=0, if N=0. //> \endverbatim //> //> \param[in] SCALE //> \verbatim //> SCALE is DOUBLE PRECISION array, dimension (N) //> Details of the permutation and scaling factors, as returned //> by DGEBAL. //> \endverbatim //> //> \param[in] M //> \verbatim //> M is INTEGER //> The number of columns of the matrix V. M >= 0. //> \endverbatim //> //> \param[in,out] V //> \verbatim //> V is DOUBLE PRECISION array, dimension (LDV,M) //> On entry, the matrix of right or left eigenvectors to be //> transformed, as returned by DHSEIN or DTREVC. //> On exit, V is overwritten by the transformed eigenvectors. //> \endverbatim //> //> \param[in] LDV //> \verbatim //> LDV is INTEGER //> The leading dimension of the array V. LDV >= max(1,N). //> \endverbatim //> //> \param[out] INFO //> \verbatim //> INFO is INTEGER //> = 0: successful exit //> < 0: if INFO = -i, the i-th argument had an illegal value. //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date December 2016 // //> \ingroup doubleGEcomputational // // ===================================================================== /* Subroutine */ int dgebak_(char *job, char *side, int *n, int *ilo, int * ihi, double *scale, int *m, double *v, int *ldv, int *info) { // System generated locals int v_dim1, v_offset, i__1; // Local variables int i__, k; double s; int ii; extern /* Subroutine */ int dscal_(int *, double *, double *, int *); extern int lsame_(char *, char *); extern /* Subroutine */ int dswap_(int *, double *, int *, double *, int * ); int leftv; extern /* Subroutine */ int xerbla_(char *, int *); int rightv; // // -- LAPACK computational routine (version 3.7.0) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // December 2016 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // // ===================================================================== // // .. Parameters .. // .. // .. Local Scalars .. // .. // .. External Functions .. // .. // .. External Subroutines .. // .. // .. Intrinsic Functions .. // .. // .. Executable Statements .. // // Decode and Test the input parameters // // Parameter adjustments --scale; v_dim1 = *ldv; v_offset = 1 + v_dim1; v -= v_offset; // Function Body rightv = lsame_(side, "R"); leftv = lsame_(side, "L"); *info = 0; if (! lsame_(job, "N") && ! lsame_(job, "P") && ! lsame_(job, "S") && ! lsame_(job, "B")) { *info = -1; } else if (! rightv && ! leftv) { *info = -2; } else if (*n < 0) { *info = -3; } else if (*ilo < 1 || *ilo > max(1,*n)) { *info = -4; } else if (*ihi < min(*ilo,*n) || *ihi > *n) { *info = -5; } else if (*m < 0) { *info = -7; } else if (*ldv < max(1,*n)) { *info = -9; } if (*info != 0) { i__1 = -(*info); xerbla_("DGEBAK", &i__1); return 0; } // // Quick return if possible // if (*n == 0) { return 0; } if (*m == 0) { return 0; } if (lsame_(job, "N")) { return 0; } if (*ilo == *ihi) { goto L30; } // // Backward balance // if (lsame_(job, "S") || lsame_(job, "B")) { if (rightv) { i__1 = *ihi; for (i__ = *ilo; i__ <= i__1; ++i__) { s = scale[i__]; dscal_(m, &s, &v[i__ + v_dim1], ldv); // L10: } } if (leftv) { i__1 = *ihi; for (i__ = *ilo; i__ <= i__1; ++i__) { s = 1. / scale[i__]; dscal_(m, &s, &v[i__ + v_dim1], ldv); // L20: } } } // // Backward permutation // // For I = ILO-1 step -1 until 1, // IHI+1 step 1 until N do -- // L30: if (lsame_(job, "P") || lsame_(job, "B")) { if (rightv) { i__1 = *n; for (ii = 1; ii <= i__1; ++ii) { i__ = ii; if (i__ >= *ilo && i__ <= *ihi) { goto L40; } if (i__ < *ilo) { i__ = *ilo - ii; } k = (int) scale[i__]; if (k == i__) { goto L40; } dswap_(m, &v[i__ + v_dim1], ldv, &v[k + v_dim1], ldv); L40: ; } } if (leftv) { i__1 = *n; for (ii = 1; ii <= i__1; ++ii) { i__ = ii; if (i__ >= *ilo && i__ <= *ihi) { goto L50; } if (i__ < *ilo) { i__ = *ilo - ii; } k = (int) scale[i__]; if (k == i__) { goto L50; } dswap_(m, &v[i__ + v_dim1], ldv, &v[k + v_dim1], ldv); L50: ; } } } return 0; // // End of DGEBAK // } // dgebak_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DGEBAL // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DGEBAL + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DGEBAL( JOB, N, A, LDA, ILO, IHI, SCALE, INFO ) // // .. Scalar Arguments .. // CHARACTER JOB // INTEGER IHI, ILO, INFO, LDA, N // .. // .. Array Arguments .. // DOUBLE PRECISION A( LDA, * ), SCALE( * ) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> DGEBAL balances a general real matrix A. This involves, first, //> permuting A by a similarity transformation to isolate eigenvalues //> in the first 1 to ILO-1 and last IHI+1 to N elements on the //> diagonal; and second, applying a diagonal similarity transformation //> to rows and columns ILO to IHI to make the rows and columns as //> close in norm as possible. Both steps are optional. //> //> Balancing may reduce the 1-norm of the matrix, and improve the //> accuracy of the computed eigenvalues and/or eigenvectors. //> \endverbatim // // Arguments: // ========== // //> \param[in] JOB //> \verbatim //> JOB is CHARACTER*1 //> Specifies the operations to be performed on A: //> = 'N': none: simply set ILO = 1, IHI = N, SCALE(I) = 1.0 //> for i = 1,...,N; //> = 'P': permute only; //> = 'S': scale only; //> = 'B': both permute and scale. //> \endverbatim //> //> \param[in] N //> \verbatim //> N is INTEGER //> The order of the matrix A. N >= 0. //> \endverbatim //> //> \param[in,out] A //> \verbatim //> A is DOUBLE PRECISION array, dimension (LDA,N) //> On entry, the input matrix A. //> On exit, A is overwritten by the balanced matrix. //> If JOB = 'N', A is not referenced. //> See Further Details. //> \endverbatim //> //> \param[in] LDA //> \verbatim //> LDA is INTEGER //> The leading dimension of the array A. LDA >= max(1,N). //> \endverbatim //> //> \param[out] ILO //> \verbatim //> ILO is INTEGER //> \endverbatim //> \param[out] IHI //> \verbatim //> IHI is INTEGER //> ILO and IHI are set to integers such that on exit //> A(i,j) = 0 if i > j and j = 1,...,ILO-1 or I = IHI+1,...,N. //> If JOB = 'N' or 'S', ILO = 1 and IHI = N. //> \endverbatim //> //> \param[out] SCALE //> \verbatim //> SCALE is DOUBLE PRECISION array, dimension (N) //> Details of the permutations and scaling factors applied to //> A. If P(j) is the index of the row and column interchanged //> with row and column j and D(j) is the scaling factor //> applied to row and column j, then //> SCALE(j) = P(j) for j = 1,...,ILO-1 //> = D(j) for j = ILO,...,IHI //> = P(j) for j = IHI+1,...,N. //> The order in which the interchanges are made is N to IHI+1, //> then 1 to ILO-1. //> \endverbatim //> //> \param[out] INFO //> \verbatim //> INFO is INTEGER //> = 0: successful exit. //> < 0: if INFO = -i, the i-th argument had an illegal value. //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date June 2017 // //> \ingroup doubleGEcomputational // //> \par Further Details: // ===================== //> //> \verbatim //> //> The permutations consist of row and column interchanges which put //> the matrix in the form //> //> ( T1 X Y ) //> P A P = ( 0 B Z ) //> ( 0 0 T2 ) //> //> where T1 and T2 are upper triangular matrices whose eigenvalues lie //> along the diagonal. The column indices ILO and IHI mark the starting //> and ending columns of the submatrix B. Balancing consists of applying //> a diagonal similarity transformation inv(D) * B * D to make the //> 1-norms of each row of B and its corresponding column nearly equal. //> The output matrix is //> //> ( T1 X*D Y ) //> ( 0 inv(D)*B*D inv(D)*Z ). //> ( 0 0 T2 ) //> //> Information about the permutations P and the diagonal matrix D is //> returned in the vector SCALE. //> //> This subroutine is based on the EISPACK routine BALANC. //> //> Modified by Tzu-Yi Chen, Computer Science Division, University of //> California at Berkeley, USA //> \endverbatim //> // ===================================================================== /* Subroutine */ int dgebal_(char *job, int *n, double *a, int *lda, int *ilo, int *ihi, double *scale, int *info) { // Table of constant values int c__1 = 1; // System generated locals int a_dim1, a_offset, i__1, i__2; double d__1, d__2; // Local variables double c__, f, g; int i__, j, k, l, m; double r__, s, ca, ra; int ica, ira, iexc; extern double dnrm2_(int *, double *, int *); extern /* Subroutine */ int dscal_(int *, double *, double *, int *); extern int lsame_(char *, char *); extern /* Subroutine */ int dswap_(int *, double *, int *, double *, int * ); double sfmin1, sfmin2, sfmax1, sfmax2; extern double dlamch_(char *); extern int idamax_(int *, double *, int *); extern int disnan_(double *); extern /* Subroutine */ int xerbla_(char *, int *); int noconv; // // -- LAPACK computational routine (version 3.7.1) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // June 2017 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // // ===================================================================== // // .. Parameters .. // .. // .. Local Scalars .. // .. // .. External Functions .. // .. // .. External Subroutines .. // .. // .. Intrinsic Functions .. // .. // Test the input parameters // // Parameter adjustments a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; --scale; // Function Body *info = 0; if (! lsame_(job, "N") && ! lsame_(job, "P") && ! lsame_(job, "S") && ! lsame_(job, "B")) { *info = -1; } else if (*n < 0) { *info = -2; } else if (*lda < max(1,*n)) { *info = -4; } if (*info != 0) { i__1 = -(*info); xerbla_("DGEBAL", &i__1); return 0; } k = 1; l = *n; if (*n == 0) { goto L210; } if (lsame_(job, "N")) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { scale[i__] = 1.; // L10: } goto L210; } if (lsame_(job, "S")) { goto L120; } // // Permutation to isolate eigenvalues if possible // goto L50; // // Row and column exchange. // L20: scale[m] = (double) j; if (j == m) { goto L30; } dswap_(&l, &a[j * a_dim1 + 1], &c__1, &a[m * a_dim1 + 1], &c__1); i__1 = *n - k + 1; dswap_(&i__1, &a[j + k * a_dim1], lda, &a[m + k * a_dim1], lda); L30: switch (iexc) { case 1: goto L40; case 2: goto L80; } // // Search for rows isolating an eigenvalue and push them down. // L40: if (l == 1) { goto L210; } --l; L50: for (j = l; j >= 1; --j) { i__1 = l; for (i__ = 1; i__ <= i__1; ++i__) { if (i__ == j) { goto L60; } if (a[j + i__ * a_dim1] != 0.) { goto L70; } L60: ; } m = l; iexc = 1; goto L20; L70: ; } goto L90; // // Search for columns isolating an eigenvalue and push them left. // L80: ++k; L90: i__1 = l; for (j = k; j <= i__1; ++j) { i__2 = l; for (i__ = k; i__ <= i__2; ++i__) { if (i__ == j) { goto L100; } if (a[i__ + j * a_dim1] != 0.) { goto L110; } L100: ; } m = k; iexc = 2; goto L20; L110: ; } L120: i__1 = l; for (i__ = k; i__ <= i__1; ++i__) { scale[i__] = 1.; // L130: } if (lsame_(job, "P")) { goto L210; } // // Balance the submatrix in rows K to L. // // Iterative loop for norm reduction // sfmin1 = dlamch_("S") / dlamch_("P"); sfmax1 = 1. / sfmin1; sfmin2 = sfmin1 * 2.; sfmax2 = 1. / sfmin2; L140: noconv = FALSE_; i__1 = l; for (i__ = k; i__ <= i__1; ++i__) { i__2 = l - k + 1; c__ = dnrm2_(&i__2, &a[k + i__ * a_dim1], &c__1); i__2 = l - k + 1; r__ = dnrm2_(&i__2, &a[i__ + k * a_dim1], lda); ica = idamax_(&l, &a[i__ * a_dim1 + 1], &c__1); ca = (d__1 = a[ica + i__ * a_dim1], abs(d__1)); i__2 = *n - k + 1; ira = idamax_(&i__2, &a[i__ + k * a_dim1], lda); ra = (d__1 = a[i__ + (ira + k - 1) * a_dim1], abs(d__1)); // // Guard against zero C or R due to underflow. // if (c__ == 0. || r__ == 0.) { goto L200; } g = r__ / 2.; f = 1.; s = c__ + r__; L160: // Computing MAX d__1 = max(f,c__); // Computing MIN d__2 = min(r__,g); if (c__ >= g || max(d__1,ca) >= sfmax2 || min(d__2,ra) <= sfmin2) { goto L170; } d__1 = c__ + f + ca + r__ + g + ra; if (disnan_(&d__1)) { // // Exit if NaN to avoid infinite loop // *info = -3; i__2 = -(*info); xerbla_("DGEBAL", &i__2); return 0; } f *= 2.; c__ *= 2.; ca *= 2.; r__ /= 2.; g /= 2.; ra /= 2.; goto L160; L170: g = c__ / 2.; L180: // Computing MIN d__1 = min(f,c__), d__1 = min(d__1,g); if (g < r__ || max(r__,ra) >= sfmax2 || min(d__1,ca) <= sfmin2) { goto L190; } f /= 2.; c__ /= 2.; g /= 2.; ca /= 2.; r__ *= 2.; ra *= 2.; goto L180; // // Now balance. // L190: if (c__ + r__ >= s * .95) { goto L200; } if (f < 1. && scale[i__] < 1.) { if (f * scale[i__] <= sfmin1) { goto L200; } } if (f > 1. && scale[i__] > 1.) { if (scale[i__] >= sfmax1 / f) { goto L200; } } g = 1. / f; scale[i__] *= f; noconv = TRUE_; i__2 = *n - k + 1; dscal_(&i__2, &g, &a[i__ + k * a_dim1], lda); dscal_(&l, &f, &a[i__ * a_dim1 + 1], &c__1); L200: ; } if (noconv) { goto L140; } L210: *ilo = k; *ihi = l; return 0; // // End of DGEBAL // } // dgebal_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief DGEEV computes the eigenvalues and, optionally, the left and/or right eigenvectors for GE matrices // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DGEEV + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DGEEV( JOBVL, JOBVR, N, A, LDA, WR, WI, VL, LDVL, VR, // LDVR, WORK, LWORK, INFO ) // // .. Scalar Arguments .. // CHARACTER JOBVL, JOBVR // INTEGER INFO, LDA, LDVL, LDVR, LWORK, N // .. // .. Array Arguments .. // DOUBLE PRECISION A( LDA, * ), VL( LDVL, * ), VR( LDVR, * ), // $ WI( * ), WORK( * ), WR( * ) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> DGEEV computes for an N-by-N real nonsymmetric matrix A, the //> eigenvalues and, optionally, the left and/or right eigenvectors. //> //> The right eigenvector v(j) of A satisfies //> A * v(j) = lambda(j) * v(j) //> where lambda(j) is its eigenvalue. //> The left eigenvector u(j) of A satisfies //> u(j)**H * A = lambda(j) * u(j)**H //> where u(j)**H denotes the conjugate-transpose of u(j). //> //> The computed eigenvectors are normalized to have Euclidean norm //> equal to 1 and largest component real. //> \endverbatim // // Arguments: // ========== // //> \param[in] JOBVL //> \verbatim //> JOBVL is CHARACTER*1 //> = 'N': left eigenvectors of A are not computed; //> = 'V': left eigenvectors of A are computed. //> \endverbatim //> //> \param[in] JOBVR //> \verbatim //> JOBVR is CHARACTER*1 //> = 'N': right eigenvectors of A are not computed; //> = 'V': right eigenvectors of A are computed. //> \endverbatim //> //> \param[in] N //> \verbatim //> N is INTEGER //> The order of the matrix A. N >= 0. //> \endverbatim //> //> \param[in,out] A //> \verbatim //> A is DOUBLE PRECISION array, dimension (LDA,N) //> On entry, the N-by-N matrix A. //> On exit, A has been overwritten. //> \endverbatim //> //> \param[in] LDA //> \verbatim //> LDA is INTEGER //> The leading dimension of the array A. LDA >= max(1,N). //> \endverbatim //> //> \param[out] WR //> \verbatim //> WR is DOUBLE PRECISION array, dimension (N) //> \endverbatim //> //> \param[out] WI //> \verbatim //> WI is DOUBLE PRECISION array, dimension (N) //> WR and WI contain the real and imaginary parts, //> respectively, of the computed eigenvalues. Complex //> conjugate pairs of eigenvalues appear consecutively //> with the eigenvalue having the positive imaginary part //> first. //> \endverbatim //> //> \param[out] VL //> \verbatim //> VL is 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 JOBVL = 'N', VL is not referenced. //> 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)-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). //> \endverbatim //> //> \param[in] LDVL //> \verbatim //> LDVL is INTEGER //> The leading dimension of the array VL. LDVL >= 1; if //> JOBVL = 'V', LDVL >= N. //> \endverbatim //> //> \param[out] VR //> \verbatim //> VR is 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 JOBVR = 'N', VR is not referenced. //> 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)-st 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). //> \endverbatim //> //> \param[in] LDVR //> \verbatim //> LDVR is INTEGER //> The leading dimension of the array VR. LDVR >= 1; if //> JOBVR = 'V', LDVR >= N. //> \endverbatim //> //> \param[out] WORK //> \verbatim //> WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK)) //> On exit, if INFO = 0, WORK(1) returns the optimal LWORK. //> \endverbatim //> //> \param[in] LWORK //> \verbatim //> LWORK is INTEGER //> The dimension of the array WORK. LWORK >= max(1,3*N), and //> if JOBVL = 'V' or JOBVR = 'V', LWORK >= 4*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. //> \endverbatim //> //> \param[out] INFO //> \verbatim //> INFO is INTEGER //> = 0: successful exit //> < 0: if INFO = -i, the i-th argument had an illegal value. //> > 0: if INFO = i, the QR algorithm failed to compute all the //> eigenvalues, and no eigenvectors have been computed; //> elements i+1:N of WR and WI contain eigenvalues which //> have converged. //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date June 2016 // // @precisions fortran d -> s // //> \ingroup doubleGEeigen // // ===================================================================== /* Subroutine */ int dgeev_(char *jobvl, char *jobvr, int *n, double *a, int * lda, double *wr, double *wi, double *vl, int *ldvl, double *vr, int * ldvr, double *work, int *lwork, int *info) { // Table of constant values int c__1 = 1; int c__0 = 0; int c_n1 = -1; // System generated locals int a_dim1, a_offset, vl_dim1, vl_offset, vr_dim1, vr_offset, i__1, i__2, i__3; double d__1, d__2; // Local variables int i__, k; double r__, cs, sn; int ihi; double scl; int ilo; double dum[1], eps; int lwork_trevc__, ibal; char side[1+1]={'\0'}; double anrm; int ierr, itau; extern /* Subroutine */ int drot_(int *, double *, int *, double *, int *, double *, double *); int iwrk, nout; extern double dnrm2_(int *, double *, int *); extern /* Subroutine */ int dscal_(int *, double *, double *, int *); extern int lsame_(char *, char *); extern double dlapy2_(double *, double *); extern /* Subroutine */ int dlabad_(double *, double *), dgebak_(char *, char *, int *, int *, int *, double *, int *, double *, int *, int *), dgebal_(char *, int *, double *, int *, int *, int *, double *, int *); int scalea; extern double dlamch_(char *); double cscale; extern double dlange_(char *, int *, int *, double *, int *, double *); extern /* Subroutine */ int dgehrd_(int *, int *, int *, double *, int *, double *, double *, int *, int *), dlascl_(char *, int *, int *, double *, double *, int *, int *, double *, int *, int *); extern int idamax_(int *, double *, int *); extern /* Subroutine */ int dlacpy_(char *, int *, int *, double *, int *, double *, int *), dlartg_(double *, double *, double *, double *, double *), xerbla_(char *, int *); int select[1]; extern int ilaenv_(int *, char *, char *, int *, int *, int *, int *); double bignum; extern /* Subroutine */ int dorghr_(int *, int *, int *, double *, int *, double *, double *, int *, int *), dhseqr_(char *, char *, int *, int *, int *, double *, int *, double *, double *, double *, int * , double *, int *, int *); int minwrk, maxwrk; int wantvl; double smlnum; int hswork; int lquery, wantvr; extern /* Subroutine */ int dtrevc3_(char *, char *, int *, int *, double *, int *, double *, int *, double *, int *, int *, int *, double * , int *, int *); // // -- LAPACK driver routine (version 3.7.0) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // June 2016 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // // ===================================================================== // // .. Parameters .. // .. // .. Local Scalars .. // .. // .. Local Arrays .. // .. // .. 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; --wr; --wi; 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 *info = 0; lquery = *lwork == -1; wantvl = lsame_(jobvl, "V"); wantvr = lsame_(jobvr, "V"); if (! wantvl && ! lsame_(jobvl, "N")) { *info = -1; } else if (! wantvr && ! lsame_(jobvr, "N")) { *info = -2; } else if (*n < 0) { *info = -3; } else if (*lda < max(1,*n)) { *info = -5; } else if (*ldvl < 1 || wantvl && *ldvl < *n) { *info = -9; } else if (*ldvr < 1 || wantvr && *ldvr < *n) { *info = -11; } // // 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. // HSWORK refers to the workspace preferred by DHSEQR, as // calculated below. HSWORK is computed assuming ILO=1 and IHI=N, // the worst case.) // if (*info == 0) { if (*n == 0) { minwrk = 1; maxwrk = 1; } else { maxwrk = (*n << 1) + *n * ilaenv_(&c__1, "DGEHRD", " ", n, &c__1, n, &c__0); if (wantvl) { minwrk = *n << 2; // Computing MAX i__1 = maxwrk, i__2 = (*n << 1) + (*n - 1) * ilaenv_(&c__1, "DORGHR", " ", n, &c__1, n, &c_n1); maxwrk = max(i__1,i__2); dhseqr_("S", "V", n, &c__1, n, &a[a_offset], lda, &wr[1], &wi[ 1], &vl[vl_offset], ldvl, &work[1], &c_n1, info); hswork = (int) work[1]; // Computing MAX i__1 = maxwrk, i__2 = *n + 1, i__1 = max(i__1,i__2), i__2 = * n + hswork; maxwrk = max(i__1,i__2); dtrevc3_("L", "B", select, n, &a[a_offset], lda, &vl[ vl_offset], ldvl, &vr[vr_offset], ldvr, n, &nout, & work[1], &c_n1, &ierr); lwork_trevc__ = (int) work[1]; // Computing MAX i__1 = maxwrk, i__2 = *n + lwork_trevc__; maxwrk = max(i__1,i__2); // Computing MAX i__1 = maxwrk, i__2 = *n << 2; maxwrk = max(i__1,i__2); } else if (wantvr) { minwrk = *n << 2; // Computing MAX i__1 = maxwrk, i__2 = (*n << 1) + (*n - 1) * ilaenv_(&c__1, "DORGHR", " ", n, &c__1, n, &c_n1); maxwrk = max(i__1,i__2); dhseqr_("S", "V", n, &c__1, n, &a[a_offset], lda, &wr[1], &wi[ 1], &vr[vr_offset], ldvr, &work[1], &c_n1, info); hswork = (int) work[1]; // Computing MAX i__1 = maxwrk, i__2 = *n + 1, i__1 = max(i__1,i__2), i__2 = * n + hswork; maxwrk = max(i__1,i__2); dtrevc3_("R", "B", select, n, &a[a_offset], lda, &vl[ vl_offset], ldvl, &vr[vr_offset], ldvr, n, &nout, & work[1], &c_n1, &ierr); lwork_trevc__ = (int) work[1]; // Computing MAX i__1 = maxwrk, i__2 = *n + lwork_trevc__; maxwrk = max(i__1,i__2); // Computing MAX i__1 = maxwrk, i__2 = *n << 2; maxwrk = max(i__1,i__2); } else { minwrk = *n * 3; dhseqr_("E", "N", n, &c__1, n, &a[a_offset], lda, &wr[1], &wi[ 1], &vr[vr_offset], ldvr, &work[1], &c_n1, info); hswork = (int) work[1]; // Computing MAX i__1 = maxwrk, i__2 = *n + 1, i__1 = max(i__1,i__2), i__2 = * n + hswork; maxwrk = max(i__1,i__2); } maxwrk = max(maxwrk,minwrk); } work[1] = (double) maxwrk; if (*lwork < minwrk && ! lquery) { *info = -13; } } if (*info != 0) { i__1 = -(*info); xerbla_("DGEEV ", &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, dum); scalea = FALSE_; if (anrm > 0. && anrm < smlnum) { scalea = TRUE_; cscale = smlnum; } else if (anrm > bignum) { scalea = TRUE_; cscale = bignum; } if (scalea) { dlascl_("G", &c__0, &c__0, &anrm, &cscale, n, n, &a[a_offset], lda, & ierr); } // // Balance the matrix // (Workspace: need N) // ibal = 1; dgebal_("B", n, &a[a_offset], lda, &ilo, &ihi, &work[ibal], &ierr); // // Reduce to upper Hessenberg form // (Workspace: need 3*N, prefer 2*N+N*NB) // itau = ibal + *n; iwrk = itau + *n; i__1 = *lwork - iwrk + 1; dgehrd_(n, &ilo, &ihi, &a[a_offset], lda, &work[itau], &work[iwrk], &i__1, &ierr); if (wantvl) { // // Want left eigenvectors // Copy Householder vectors to VL // *(unsigned char *)side = 'L'; dlacpy_("L", n, n, &a[a_offset], lda, &vl[vl_offset], ldvl); // // Generate orthogonal matrix in VL // (Workspace: need 3*N-1, prefer 2*N+(N-1)*NB) // i__1 = *lwork - iwrk + 1; dorghr_(n, &ilo, &ihi, &vl[vl_offset], ldvl, &work[itau], &work[iwrk], &i__1, &ierr); // // Perform QR iteration, accumulating Schur vectors in VL // (Workspace: need N+1, prefer N+HSWORK (see comments) ) // iwrk = itau; i__1 = *lwork - iwrk + 1; dhseqr_("S", "V", n, &ilo, &ihi, &a[a_offset], lda, &wr[1], &wi[1], & vl[vl_offset], ldvl, &work[iwrk], &i__1, info); if (wantvr) { // // Want left and right eigenvectors // Copy Schur vectors to VR // *(unsigned char *)side = 'B'; dlacpy_("F", n, n, &vl[vl_offset], ldvl, &vr[vr_offset], ldvr); } } else if (wantvr) { // // Want right eigenvectors // Copy Householder vectors to VR // *(unsigned char *)side = 'R'; dlacpy_("L", n, n, &a[a_offset], lda, &vr[vr_offset], ldvr); // // Generate orthogonal matrix in VR // (Workspace: need 3*N-1, prefer 2*N+(N-1)*NB) // i__1 = *lwork - iwrk + 1; dorghr_(n, &ilo, &ihi, &vr[vr_offset], ldvr, &work[itau], &work[iwrk], &i__1, &ierr); // // Perform QR iteration, accumulating Schur vectors in VR // (Workspace: need N+1, prefer N+HSWORK (see comments) ) // iwrk = itau; i__1 = *lwork - iwrk + 1; dhseqr_("S", "V", n, &ilo, &ihi, &a[a_offset], lda, &wr[1], &wi[1], & vr[vr_offset], ldvr, &work[iwrk], &i__1, info); } else { // // Compute eigenvalues only // (Workspace: need N+1, prefer N+HSWORK (see comments) ) // iwrk = itau; i__1 = *lwork - iwrk + 1; dhseqr_("E", "N", n, &ilo, &ihi, &a[a_offset], lda, &wr[1], &wi[1], & vr[vr_offset], ldvr, &work[iwrk], &i__1, info); } // // If INFO .NE. 0 from DHSEQR, then quit // if (*info != 0) { goto L50; } if (wantvl || wantvr) { // // Compute left and/or right eigenvectors // (Workspace: need 4*N, prefer N + N + 2*N*NB) // i__1 = *lwork - iwrk + 1; dtrevc3_(side, "B", select, n, &a[a_offset], lda, &vl[vl_offset], ldvl, &vr[vr_offset], ldvr, n, &nout, &work[iwrk], &i__1, & ierr); } if (wantvl) { // // Undo balancing of left eigenvectors // (Workspace: need N) // dgebak_("B", "L", n, &ilo, &ihi, &work[ibal], n, &vl[vl_offset], ldvl, &ierr); // // Normalize left eigenvectors and make largest component real // i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (wi[i__] == 0.) { scl = 1. / dnrm2_(n, &vl[i__ * vl_dim1 + 1], &c__1); dscal_(n, &scl, &vl[i__ * vl_dim1 + 1], &c__1); } else if (wi[i__] > 0.) { d__1 = dnrm2_(n, &vl[i__ * vl_dim1 + 1], &c__1); d__2 = dnrm2_(n, &vl[(i__ + 1) * vl_dim1 + 1], &c__1); scl = 1. / dlapy2_(&d__1, &d__2); dscal_(n, &scl, &vl[i__ * vl_dim1 + 1], &c__1); dscal_(n, &scl, &vl[(i__ + 1) * vl_dim1 + 1], &c__1); i__2 = *n; for (k = 1; k <= i__2; ++k) { // Computing 2nd power d__1 = vl[k + i__ * vl_dim1]; // Computing 2nd power d__2 = vl[k + (i__ + 1) * vl_dim1]; work[iwrk + k - 1] = d__1 * d__1 + d__2 * d__2; // L10: } k = idamax_(n, &work[iwrk], &c__1); dlartg_(&vl[k + i__ * vl_dim1], &vl[k + (i__ + 1) * vl_dim1], &cs, &sn, &r__); drot_(n, &vl[i__ * vl_dim1 + 1], &c__1, &vl[(i__ + 1) * vl_dim1 + 1], &c__1, &cs, &sn); vl[k + (i__ + 1) * vl_dim1] = 0.; } // L20: } } if (wantvr) { // // Undo balancing of right eigenvectors // (Workspace: need N) // dgebak_("B", "R", n, &ilo, &ihi, &work[ibal], n, &vr[vr_offset], ldvr, &ierr); // // Normalize right eigenvectors and make largest component real // i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (wi[i__] == 0.) { scl = 1. / dnrm2_(n, &vr[i__ * vr_dim1 + 1], &c__1); dscal_(n, &scl, &vr[i__ * vr_dim1 + 1], &c__1); } else if (wi[i__] > 0.) { d__1 = dnrm2_(n, &vr[i__ * vr_dim1 + 1], &c__1); d__2 = dnrm2_(n, &vr[(i__ + 1) * vr_dim1 + 1], &c__1); scl = 1. / dlapy2_(&d__1, &d__2); dscal_(n, &scl, &vr[i__ * vr_dim1 + 1], &c__1); dscal_(n, &scl, &vr[(i__ + 1) * vr_dim1 + 1], &c__1); i__2 = *n; for (k = 1; k <= i__2; ++k) { // Computing 2nd power d__1 = vr[k + i__ * vr_dim1]; // Computing 2nd power d__2 = vr[k + (i__ + 1) * vr_dim1]; work[iwrk + k - 1] = d__1 * d__1 + d__2 * d__2; // L30: } k = idamax_(n, &work[iwrk], &c__1); dlartg_(&vr[k + i__ * vr_dim1], &vr[k + (i__ + 1) * vr_dim1], &cs, &sn, &r__); drot_(n, &vr[i__ * vr_dim1 + 1], &c__1, &vr[(i__ + 1) * vr_dim1 + 1], &c__1, &cs, &sn); vr[k + (i__ + 1) * vr_dim1] = 0.; } // L40: } } // // Undo scaling if necessary // L50: if (scalea) { i__1 = *n - *info; // Computing MAX i__3 = *n - *info; i__2 = max(i__3,1); dlascl_("G", &c__0, &c__0, &cscale, &anrm, &i__1, &c__1, &wr[*info + 1], &i__2, &ierr); i__1 = *n - *info; // Computing MAX i__3 = *n - *info; i__2 = max(i__3,1); dlascl_("G", &c__0, &c__0, &cscale, &anrm, &i__1, &c__1, &wi[*info + 1], &i__2, &ierr); if (*info > 0) { i__1 = ilo - 1; dlascl_("G", &c__0, &c__0, &cscale, &anrm, &i__1, &c__1, &wr[1], n, &ierr); i__1 = ilo - 1; dlascl_("G", &c__0, &c__0, &cscale, &anrm, &i__1, &c__1, &wi[1], n, &ierr); } } work[1] = (double) maxwrk; return 0; // // End of DGEEV // } // dgeev_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DGEHD2 reduces a general square matrix to upper Hessenberg form using an unblocked algorithm. // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DGEHD2 + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DGEHD2( N, ILO, IHI, A, LDA, TAU, WORK, INFO ) // // .. Scalar Arguments .. // INTEGER IHI, ILO, INFO, LDA, N // .. // .. Array Arguments .. // DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> DGEHD2 reduces a real general matrix A to upper Hessenberg form H by //> an orthogonal similarity transformation: Q**T * A * Q = H . //> \endverbatim // // Arguments: // ========== // //> \param[in] N //> \verbatim //> N is INTEGER //> The order of the matrix A. N >= 0. //> \endverbatim //> //> \param[in] ILO //> \verbatim //> ILO is INTEGER //> \endverbatim //> //> \param[in] IHI //> \verbatim //> IHI is INTEGER //> //> It is assumed that A is already upper triangular in rows //> and columns 1:ILO-1 and IHI+1:N. ILO and IHI are normally //> set by a previous call to DGEBAL; otherwise they should be //> set to 1 and N respectively. See Further Details. //> 1 <= ILO <= IHI <= max(1,N). //> \endverbatim //> //> \param[in,out] A //> \verbatim //> A is DOUBLE PRECISION array, dimension (LDA,N) //> On entry, the n by n general matrix to be reduced. //> On exit, the upper triangle and the first subdiagonal of A //> are overwritten with the upper Hessenberg matrix H, and the //> elements below the first subdiagonal, with the array TAU, //> represent the orthogonal matrix Q as a product of elementary //> reflectors. See Further Details. //> \endverbatim //> //> \param[in] LDA //> \verbatim //> LDA is INTEGER //> The leading dimension of the array A. LDA >= max(1,N). //> \endverbatim //> //> \param[out] TAU //> \verbatim //> TAU is DOUBLE PRECISION array, dimension (N-1) //> The scalar factors of the elementary reflectors (see Further //> Details). //> \endverbatim //> //> \param[out] WORK //> \verbatim //> WORK is DOUBLE PRECISION array, dimension (N) //> \endverbatim //> //> \param[out] INFO //> \verbatim //> INFO is INTEGER //> = 0: successful exit. //> < 0: if INFO = -i, the i-th argument had an illegal value. //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date December 2016 // //> \ingroup doubleGEcomputational // //> \par Further Details: // ===================== //> //> \verbatim //> //> The matrix Q is represented as a product of (ihi-ilo) elementary //> reflectors //> //> Q = H(ilo) H(ilo+1) . . . H(ihi-1). //> //> Each H(i) has the form //> //> H(i) = I - tau * v * v**T //> //> where tau is a real scalar, and v is a real vector with //> v(1:i) = 0, v(i+1) = 1 and v(ihi+1:n) = 0; v(i+2:ihi) is stored on //> exit in A(i+2:ihi,i), and tau in TAU(i). //> //> The contents of A are illustrated by the following example, with //> n = 7, ilo = 2 and ihi = 6: //> //> on entry, on exit, //> //> ( a a a a a a a ) ( a a h h h h a ) //> ( a a a a a a ) ( a h h h h a ) //> ( a a a a a a ) ( h h h h h h ) //> ( a a a a a a ) ( v2 h h h h h ) //> ( a a a a a a ) ( v2 v3 h h h h ) //> ( a a a a a a ) ( v2 v3 v4 h h h ) //> ( a ) ( a ) //> //> where a denotes an element of the original matrix A, h denotes a //> modified element of the upper Hessenberg matrix H, and vi denotes an //> element of the vector defining H(i). //> \endverbatim //> // ===================================================================== /* Subroutine */ int dgehd2_(int *n, int *ilo, int *ihi, double *a, int *lda, double *tau, double *work, int *info) { // Table of constant values int c__1 = 1; // System generated locals int a_dim1, a_offset, i__1, i__2, i__3; // Local variables int i__; double aii; extern /* Subroutine */ int dlarf_(char *, int *, int *, double *, int *, double *, double *, int *, double *), dlarfg_(int *, double *, double *, int *, double *), xerbla_(char *, int *); // // -- LAPACK computational routine (version 3.7.0) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // December 2016 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // // ===================================================================== // // .. Parameters .. // .. // .. Local Scalars .. // .. // .. External Subroutines .. // .. // .. Intrinsic Functions .. // .. // .. Executable Statements .. // // Test the input parameters // // Parameter adjustments a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; --tau; --work; // Function Body *info = 0; 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; } if (*info != 0) { i__1 = -(*info); xerbla_("DGEHD2", &i__1); return 0; } i__1 = *ihi - 1; for (i__ = *ilo; i__ <= i__1; ++i__) { // // Compute elementary reflector H(i) to annihilate A(i+2:ihi,i) // i__2 = *ihi - i__; // Computing MIN i__3 = i__ + 2; dlarfg_(&i__2, &a[i__ + 1 + i__ * a_dim1], &a[min(i__3,*n) + i__ * a_dim1], &c__1, &tau[i__]); aii = a[i__ + 1 + i__ * a_dim1]; a[i__ + 1 + i__ * a_dim1] = 1.; // // Apply H(i) to A(1:ihi,i+1:ihi) from the right // i__2 = *ihi - i__; dlarf_("Right", ihi, &i__2, &a[i__ + 1 + i__ * a_dim1], &c__1, &tau[ i__], &a[(i__ + 1) * a_dim1 + 1], lda, &work[1]); // // Apply H(i) to A(i+1:ihi,i+1:n) from the left // i__2 = *ihi - i__; i__3 = *n - i__; dlarf_("Left", &i__2, &i__3, &a[i__ + 1 + i__ * a_dim1], &c__1, &tau[ i__], &a[i__ + 1 + (i__ + 1) * a_dim1], lda, &work[1]); a[i__ + 1 + i__ * a_dim1] = aii; // L10: } return 0; // // End of DGEHD2 // } // dgehd2_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DGEHRD // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DGEHRD + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DGEHRD( N, ILO, IHI, A, LDA, TAU, WORK, LWORK, INFO ) // // .. Scalar Arguments .. // INTEGER IHI, ILO, INFO, LDA, LWORK, N // .. // .. Array Arguments .. // DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> DGEHRD reduces a real general matrix A to upper Hessenberg form H by //> an orthogonal similarity transformation: Q**T * A * Q = H . //> \endverbatim // // Arguments: // ========== // //> \param[in] N //> \verbatim //> N is INTEGER //> The order of the matrix A. N >= 0. //> \endverbatim //> //> \param[in] ILO //> \verbatim //> ILO is INTEGER //> \endverbatim //> //> \param[in] IHI //> \verbatim //> IHI is INTEGER //> //> It is assumed that A is already upper triangular in rows //> and columns 1:ILO-1 and IHI+1:N. ILO and IHI are normally //> set by a previous call to DGEBAL; otherwise they should be //> set to 1 and N respectively. See Further Details. //> 1 <= ILO <= IHI <= N, if N > 0; ILO=1 and IHI=0, if N=0. //> \endverbatim //> //> \param[in,out] A //> \verbatim //> A is DOUBLE PRECISION array, dimension (LDA,N) //> On entry, the N-by-N general matrix to be reduced. //> On exit, the upper triangle and the first subdiagonal of A //> are overwritten with the upper Hessenberg matrix H, and the //> elements below the first subdiagonal, with the array TAU, //> represent the orthogonal matrix Q as a product of elementary //> reflectors. See Further Details. //> \endverbatim //> //> \param[in] LDA //> \verbatim //> LDA is INTEGER //> The leading dimension of the array A. LDA >= max(1,N). //> \endverbatim //> //> \param[out] TAU //> \verbatim //> TAU is DOUBLE PRECISION array, dimension (N-1) //> The scalar factors of the elementary reflectors (see Further //> Details). Elements 1:ILO-1 and IHI:N-1 of TAU are set to //> zero. //> \endverbatim //> //> \param[out] WORK //> \verbatim //> WORK is DOUBLE PRECISION array, dimension (LWORK) //> On exit, if INFO = 0, WORK(1) returns the optimal LWORK. //> \endverbatim //> //> \param[in] LWORK //> \verbatim //> LWORK is INTEGER //> The length of the array WORK. LWORK >= max(1,N). //> For good performance, LWORK should generally be larger. //> //> If LWORK = -1, then a workspace query is assumed; the routine //> only calculates the optimal size of the WORK array, returns //> this value as the first entry of the WORK array, and no error //> message related to LWORK is issued by XERBLA. //> \endverbatim //> //> \param[out] INFO //> \verbatim //> INFO is INTEGER //> = 0: successful exit //> < 0: if INFO = -i, the i-th argument had an illegal value. //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date December 2016 // //> \ingroup doubleGEcomputational // //> \par Further Details: // ===================== //> //> \verbatim //> //> The matrix Q is represented as a product of (ihi-ilo) elementary //> reflectors //> //> Q = H(ilo) H(ilo+1) . . . H(ihi-1). //> //> Each H(i) has the form //> //> H(i) = I - tau * v * v**T //> //> where tau is a real scalar, and v is a real vector with //> v(1:i) = 0, v(i+1) = 1 and v(ihi+1:n) = 0; v(i+2:ihi) is stored on //> exit in A(i+2:ihi,i), and tau in TAU(i). //> //> The contents of A are illustrated by the following example, with //> n = 7, ilo = 2 and ihi = 6: //> //> on entry, on exit, //> //> ( a a a a a a a ) ( a a h h h h a ) //> ( a a a a a a ) ( a h h h h a ) //> ( a a a a a a ) ( h h h h h h ) //> ( a a a a a a ) ( v2 h h h h h ) //> ( a a a a a a ) ( v2 v3 h h h h ) //> ( a a a a a a ) ( v2 v3 v4 h h h ) //> ( a ) ( a ) //> //> where a denotes an element of the original matrix A, h denotes a //> modified element of the upper Hessenberg matrix H, and vi denotes an //> element of the vector defining H(i). //> //> This file is a slight modification of LAPACK-3.0's DGEHRD //> subroutine incorporating improvements proposed by Quintana-Orti and //> Van de Geijn (2006). (See DLAHR2.) //> \endverbatim //> // ===================================================================== /* Subroutine */ int dgehrd_(int *n, int *ilo, int *ihi, double *a, int *lda, double *tau, double *work, int *lwork, int *info) { // Table of constant values int c__1 = 1; int c_n1 = -1; int c__3 = 3; int c__2 = 2; int c__65 = 65; double c_b25 = -1.; double c_b26 = 1.; // System generated locals int a_dim1, a_offset, i__1, i__2, i__3, i__4; // Local variables int i__, j, ib; double ei; int nb, nh, nx, iwt; extern /* Subroutine */ int dgemm_(char *, char *, int *, int *, int *, double *, double *, int *, double *, int *, double *, double *, int *); int nbmin, iinfo; extern /* Subroutine */ int dtrmm_(char *, char *, char *, char *, int *, int *, double *, double *, int *, double *, int *), daxpy_(int *, double *, double *, int *, double *, int *), dgehd2_(int *, int *, int *, double *, int *, double *, double *, int *), dlahr2_(int * , int *, int *, double *, int *, double *, double *, int *, double *, int *), dlarfb_(char *, char *, char *, char *, int *, int *, int *, double *, int *, double *, int *, double *, int *, double *, int *), xerbla_(char *, int *); extern int ilaenv_(int *, char *, char *, int *, int *, int *, int *); int ldwork, lwkopt; int lquery; // // -- LAPACK computational routine (version 3.7.0) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // December 2016 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // // ===================================================================== // // .. Parameters .. // .. // .. Local Scalars .. // .. // .. External Subroutines .. // .. // .. Intrinsic Functions .. // .. // .. External Functions .. // .. // .. Executable Statements .. // // Test the input parameters // // Parameter adjustments a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; --tau; --work; // Function Body *info = 0; 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,*n) && ! lquery) { *info = -8; } if (*info == 0) { // // Compute the workspace requirements // // Computing MIN i__1 = 64, i__2 = ilaenv_(&c__1, "DGEHRD", " ", n, ilo, ihi, &c_n1); nb = min(i__1,i__2); lwkopt = *n * nb + 4160; work[1] = (double) lwkopt; } if (*info != 0) { i__1 = -(*info); xerbla_("DGEHRD", &i__1); return 0; } else if (lquery) { return 0; } // // Set elements 1:ILO-1 and IHI:N-1 of TAU to zero // i__1 = *ilo - 1; for (i__ = 1; i__ <= i__1; ++i__) { tau[i__] = 0.; // L10: } i__1 = *n - 1; for (i__ = max(1,*ihi); i__ <= i__1; ++i__) { tau[i__] = 0.; // L20: } // // Quick return if possible // nh = *ihi - *ilo + 1; if (nh <= 1) { work[1] = 1.; return 0; } // // Determine the block size // // Computing MIN i__1 = 64, i__2 = ilaenv_(&c__1, "DGEHRD", " ", n, ilo, ihi, &c_n1); nb = min(i__1,i__2); nbmin = 2; if (nb > 1 && nb < nh) { // // Determine when to cross over from blocked to unblocked code // (last block is always handled by unblocked code) // // Computing MAX i__1 = nb, i__2 = ilaenv_(&c__3, "DGEHRD", " ", n, ilo, ihi, &c_n1); nx = max(i__1,i__2); if (nx < nh) { // // Determine if workspace is large enough for blocked code // if (*lwork < *n * nb + 4160) { // // Not enough workspace to use optimal NB: determine the // minimum value of NB, and reduce NB or force use of // unblocked code // // Computing MAX i__1 = 2, i__2 = ilaenv_(&c__2, "DGEHRD", " ", n, ilo, ihi, & c_n1); nbmin = max(i__1,i__2); if (*lwork >= *n * nbmin + 4160) { nb = (*lwork - 4160) / *n; } else { nb = 1; } } } } ldwork = *n; if (nb < nbmin || nb >= nh) { // // Use unblocked code below // i__ = *ilo; } else { // // Use blocked code // iwt = *n * nb + 1; i__1 = *ihi - 1 - nx; i__2 = nb; for (i__ = *ilo; i__2 < 0 ? i__ >= i__1 : i__ <= i__1; i__ += i__2) { // Computing MIN i__3 = nb, i__4 = *ihi - i__; ib = min(i__3,i__4); // // Reduce columns i:i+ib-1 to Hessenberg form, returning the // matrices V and T of the block reflector H = I - V*T*V**T // which performs the reduction, and also the matrix Y = A*V*T // dlahr2_(ihi, &i__, &ib, &a[i__ * a_dim1 + 1], lda, &tau[i__], & work[iwt], &c__65, &work[1], &ldwork); // // Apply the block reflector H to A(1:ihi,i+ib:ihi) from the // right, computing A := A - Y * V**T. V(i+ib,ib-1) must be set // to 1 // ei = a[i__ + ib + (i__ + ib - 1) * a_dim1]; a[i__ + ib + (i__ + ib - 1) * a_dim1] = 1.; i__3 = *ihi - i__ - ib + 1; dgemm_("No transpose", "Transpose", ihi, &i__3, &ib, &c_b25, & work[1], &ldwork, &a[i__ + ib + i__ * a_dim1], lda, & c_b26, &a[(i__ + ib) * a_dim1 + 1], lda); a[i__ + ib + (i__ + ib - 1) * a_dim1] = ei; // // Apply the block reflector H to A(1:i,i+1:i+ib-1) from the // right // i__3 = ib - 1; dtrmm_("Right", "Lower", "Transpose", "Unit", &i__, &i__3, &c_b26, &a[i__ + 1 + i__ * a_dim1], lda, &work[1], &ldwork); i__3 = ib - 2; for (j = 0; j <= i__3; ++j) { daxpy_(&i__, &c_b25, &work[ldwork * j + 1], &c__1, &a[(i__ + j + 1) * a_dim1 + 1], &c__1); // L30: } // // Apply the block reflector H to A(i+1:ihi,i+ib:n) from the // left // i__3 = *ihi - i__; i__4 = *n - i__ - ib + 1; dlarfb_("Left", "Transpose", "Forward", "Columnwise", &i__3, & i__4, &ib, &a[i__ + 1 + i__ * a_dim1], lda, &work[iwt], & c__65, &a[i__ + 1 + (i__ + ib) * a_dim1], lda, &work[1], & ldwork); // L40: } } // // Use unblocked code to reduce the rest of the matrix // dgehd2_(n, &i__, ihi, &a[a_offset], lda, &tau[1], &work[1], &iinfo); work[1] = (double) lwkopt; return 0; // // End of DGEHRD // } // dgehrd_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DHSEQR // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DHSEQR + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DHSEQR( JOB, COMPZ, N, ILO, IHI, H, LDH, WR, WI, Z, // LDZ, WORK, LWORK, INFO ) // // .. Scalar Arguments .. // INTEGER IHI, ILO, INFO, LDH, LDZ, LWORK, N // CHARACTER COMPZ, JOB // .. // .. Array Arguments .. // DOUBLE PRECISION H( LDH, * ), WI( * ), WORK( * ), WR( * ), // $ Z( LDZ, * ) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> DHSEQR computes the eigenvalues of a Hessenberg matrix H //> and, optionally, the matrices T and Z from the Schur decomposition //> H = Z T Z**T, where T is an upper quasi-triangular matrix (the //> Schur form), and Z is the orthogonal matrix of Schur vectors. //> //> Optionally Z may be postmultiplied into an input orthogonal //> matrix Q so that this routine can give the Schur factorization //> of a matrix A which has been reduced to the Hessenberg form H //> by the orthogonal matrix Q: A = Q*H*Q**T = (QZ)*T*(QZ)**T. //> \endverbatim // // Arguments: // ========== // //> \param[in] JOB //> \verbatim //> JOB is CHARACTER*1 //> = 'E': compute eigenvalues only; //> = 'S': compute eigenvalues and the Schur form T. //> \endverbatim //> //> \param[in] COMPZ //> \verbatim //> COMPZ is CHARACTER*1 //> = 'N': no Schur vectors are computed; //> = 'I': Z is initialized to the unit matrix and the matrix Z //> of Schur vectors of H is returned; //> = 'V': Z must contain an orthogonal matrix Q on entry, and //> the product Q*Z is returned. //> \endverbatim //> //> \param[in] N //> \verbatim //> N is INTEGER //> The order of the matrix H. N >= 0. //> \endverbatim //> //> \param[in] ILO //> \verbatim //> ILO is INTEGER //> \endverbatim //> //> \param[in] IHI //> \verbatim //> IHI is INTEGER //> //> It is assumed that H is already upper triangular in rows //> and columns 1:ILO-1 and IHI+1:N. ILO and IHI are normally //> set by a previous call to DGEBAL, and then passed to ZGEHRD //> when the matrix output by DGEBAL is reduced to Hessenberg //> form. Otherwise ILO and IHI should be set to 1 and N //> respectively. If N > 0, then 1 <= ILO <= IHI <= N. //> If N = 0, then ILO = 1 and IHI = 0. //> \endverbatim //> //> \param[in,out] H //> \verbatim //> H is DOUBLE PRECISION array, dimension (LDH,N) //> On entry, the upper Hessenberg matrix H. //> On exit, if INFO = 0 and JOB = 'S', then H contains the //> upper quasi-triangular matrix T from the Schur decomposition //> (the Schur form); 2-by-2 diagonal blocks (corresponding to //> complex conjugate pairs of eigenvalues) are returned in //> standard form, with H(i,i) = H(i+1,i+1) and //> H(i+1,i)*H(i,i+1) < 0. If INFO = 0 and JOB = 'E', the //> contents of H are unspecified on exit. (The output value of //> H when INFO > 0 is given under the description of INFO //> below.) //> //> Unlike earlier versions of DHSEQR, this subroutine may //> explicitly H(i,j) = 0 for i > j and j = 1, 2, ... ILO-1 //> or j = IHI+1, IHI+2, ... N. //> \endverbatim //> //> \param[in] LDH //> \verbatim //> LDH is INTEGER //> The leading dimension of the array H. LDH >= max(1,N). //> \endverbatim //> //> \param[out] WR //> \verbatim //> WR is DOUBLE PRECISION array, dimension (N) //> \endverbatim //> //> \param[out] WI //> \verbatim //> WI is DOUBLE PRECISION array, dimension (N) //> //> The real and imaginary parts, respectively, of the computed //> eigenvalues. If two eigenvalues are computed as a complex //> conjugate pair, they are stored in consecutive elements of //> WR and WI, say the i-th and (i+1)th, with WI(i) > 0 and //> WI(i+1) < 0. If JOB = 'S', the eigenvalues are stored in //> the same order as on the diagonal of the Schur form returned //> in H, with WR(i) = H(i,i) and, if H(i:i+1,i:i+1) is a 2-by-2 //> diagonal block, WI(i) = sqrt(-H(i+1,i)*H(i,i+1)) and //> WI(i+1) = -WI(i). //> \endverbatim //> //> \param[in,out] Z //> \verbatim //> Z is DOUBLE PRECISION array, dimension (LDZ,N) //> If COMPZ = 'N', Z is not referenced. //> If COMPZ = 'I', on entry Z need not be set and on exit, //> if INFO = 0, Z contains the orthogonal matrix Z of the Schur //> vectors of H. If COMPZ = 'V', on entry Z must contain an //> N-by-N matrix Q, which is assumed to be equal to the unit //> matrix except for the submatrix Z(ILO:IHI,ILO:IHI). On exit, //> if INFO = 0, Z contains Q*Z. //> Normally Q is the orthogonal matrix generated by DORGHR //> after the call to DGEHRD which formed the Hessenberg matrix //> H. (The output value of Z when INFO > 0 is given under //> the description of INFO below.) //> \endverbatim //> //> \param[in] LDZ //> \verbatim //> LDZ is INTEGER //> The leading dimension of the array Z. if COMPZ = 'I' or //> COMPZ = 'V', then LDZ >= MAX(1,N). Otherwise, LDZ >= 1. //> \endverbatim //> //> \param[out] WORK //> \verbatim //> WORK is DOUBLE PRECISION array, dimension (LWORK) //> On exit, if INFO = 0, WORK(1) returns an estimate of //> the optimal value for LWORK. //> \endverbatim //> //> \param[in] LWORK //> \verbatim //> LWORK is INTEGER //> The dimension of the array WORK. LWORK >= max(1,N) //> is sufficient and delivers very good and sometimes //> optimal performance. However, LWORK as large as 11*N //> may be required for optimal performance. A workspace //> query is recommended to determine the optimal workspace //> size. //> //> If LWORK = -1, then DHSEQR does a workspace query. //> In this case, DHSEQR checks the input parameters and //> estimates the optimal workspace size for the given //> values of N, ILO and IHI. The estimate is returned //> in WORK(1). No error message related to LWORK is //> issued by XERBLA. Neither H nor Z are accessed. //> \endverbatim //> //> \param[out] INFO //> \verbatim //> INFO is INTEGER //> = 0: successful exit //> < 0: if INFO = -i, the i-th argument had an illegal //> value //> > 0: if INFO = i, DHSEQR failed to compute all of //> the eigenvalues. Elements 1:ilo-1 and i+1:n of WR //> and WI contain those eigenvalues which have been //> successfully computed. (Failures are rare.) //> //> If INFO > 0 and JOB = 'E', then on exit, the //> remaining unconverged eigenvalues are the eigen- //> values of the upper Hessenberg matrix rows and //> columns ILO through INFO of the final, output //> value of H. //> //> If INFO > 0 and JOB = 'S', then on exit //> //> (*) (initial value of H)*U = U*(final value of H) //> //> where U is an orthogonal matrix. The final //> value of H is upper Hessenberg and quasi-triangular //> in rows and columns INFO+1 through IHI. //> //> If INFO > 0 and COMPZ = 'V', then on exit //> //> (final value of Z) = (initial value of Z)*U //> //> where U is the orthogonal matrix in (*) (regard- //> less of the value of JOB.) //> //> If INFO > 0 and COMPZ = 'I', then on exit //> (final value of Z) = U //> where U is the orthogonal matrix in (*) (regard- //> less of the value of JOB.) //> //> If INFO > 0 and COMPZ = 'N', then Z is not //> accessed. //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date December 2016 // //> \ingroup doubleOTHERcomputational // //> \par Contributors: // ================== //> //> Karen Braman and Ralph Byers, Department of Mathematics, //> University of Kansas, USA // //> \par Further Details: // ===================== //> //> \verbatim //> //> Default values supplied by //> ILAENV(ISPEC,'DHSEQR',JOB(:1)//COMPZ(:1),N,ILO,IHI,LWORK). //> It is suggested that these defaults be adjusted in order //> to attain best performance in each particular //> computational environment. //> //> ISPEC=12: The DLAHQR vs DLAQR0 crossover point. //> Default: 75. (Must be at least 11.) //> //> ISPEC=13: Recommended deflation window size. //> This depends on ILO, IHI and NS. NS is the //> number of simultaneous shifts returned //> by ILAENV(ISPEC=15). (See ISPEC=15 below.) //> The default for (IHI-ILO+1) <= 500 is NS. //> The default for (IHI-ILO+1) > 500 is 3*NS/2. //> //> ISPEC=14: Nibble crossover point. (See IPARMQ for //> details.) Default: 14% of deflation window //> size. //> //> ISPEC=15: Number of simultaneous shifts in a multishift //> QR iteration. //> //> If IHI-ILO+1 is ... //> //> greater than ...but less ... the //> or equal to ... than default is //> //> 1 30 NS = 2(+) //> 30 60 NS = 4(+) //> 60 150 NS = 10(+) //> 150 590 NS = ** //> 590 3000 NS = 64 //> 3000 6000 NS = 128 //> 6000 infinity NS = 256 //> //> (+) By default some or all matrices of this order //> are passed to the implicit double shift routine //> DLAHQR and this parameter is ignored. See //> ISPEC=12 above and comments in IPARMQ for //> details. //> //> (**) The asterisks (**) indicate an ad-hoc //> function of N increasing from 10 to 64. //> //> ISPEC=16: Select structured matrix multiply. //> If the number of simultaneous shifts (specified //> by ISPEC=15) is less than 14, then the default //> for ISPEC=16 is 0. Otherwise the default for //> ISPEC=16 is 2. //> \endverbatim // //> \par References: // ================ //> //> K. Braman, R. Byers and R. Mathias, The Multi-Shift QR //> Algorithm Part I: Maintaining Well Focused Shifts, and Level 3 //> Performance, SIAM Journal of Matrix Analysis, volume 23, pages //> 929--947, 2002. //> \n //> K. Braman, R. Byers and R. Mathias, The Multi-Shift QR //> Algorithm Part II: Aggressive Early Deflation, SIAM Journal //> of Matrix Analysis, volume 23, pages 948--973, 2002. // // ===================================================================== /* Subroutine */ int dhseqr_(char *job, char *compz, int *n, int *ilo, int * ihi, double *h__, int *ldh, double *wr, double *wi, double *z__, int * ldz, double *work, int *lwork, int *info) { // Table of constant values double c_b11 = 0.; double c_b12 = 1.; int c__12 = 12; int c__2 = 2; int c__49 = 49; // System generated locals address a__1[2]; int h_dim1, h_offset, z_dim1, z_offset, i__1, i__2[2], i__3; double d__1; char ch__1[2+1]={'\0'}; // Local variables int i__; double hl[2401] /* was [49][49] */; int kbot, nmin; extern int lsame_(char *, char *); int initz; double workl[49]; int wantt, wantz; extern /* Subroutine */ int dlaqr0_(int *, int *, int *, int *, int *, double *, int *, double *, double *, int *, int *, double *, int * , double *, int *, int *), dlahqr_(int *, int *, int *, int *, int *, double *, int *, double *, double *, int *, int *, double * , int *, int *), dlacpy_(char *, int *, int *, double *, int *, double *, int *), dlaset_(char *, int *, int *, double *, double * , double *, int *); extern int ilaenv_(int *, char *, char *, int *, int *, int *, int *); extern /* Subroutine */ int xerbla_(char *, int *); int lquery; // // -- LAPACK computational routine (version 3.7.0) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // December 2016 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // // ===================================================================== // // .. Parameters .. // // ==== Matrices of order NTINY or smaller must be processed by // . DLAHQR because of insufficient subdiagonal scratch space. // . (This is a hard limit.) ==== // // ==== NL allocates some local workspace to help small matrices // . through a rare DLAHQR failure. NL > NTINY = 11 is // . required and NL <= NMIN = ILAENV(ISPEC=12,...) is recom- // . mended. (The default value of NMIN is 75.) Using NL = 49 // . allows up to six simultaneous shifts and a 16-by-16 // . deflation window. ==== // .. // .. Local Arrays .. // .. // .. Local Scalars .. // .. // .. External Functions .. // .. // .. External Subroutines .. // .. // .. Intrinsic Functions .. // .. // .. Executable Statements .. // // ==== Decode and check the input parameters. ==== // // Parameter adjustments h_dim1 = *ldh; h_offset = 1 + h_dim1; h__ -= h_offset; --wr; --wi; z_dim1 = *ldz; z_offset = 1 + z_dim1; z__ -= z_offset; --work; // Function Body wantt = lsame_(job, "S"); initz = lsame_(compz, "I"); wantz = initz || lsame_(compz, "V"); work[1] = (double) max(1,*n); lquery = *lwork == -1; *info = 0; if (! lsame_(job, "E") && ! wantt) { *info = -1; } else if (! lsame_(compz, "N") && ! wantz) { *info = -2; } else if (*n < 0) { *info = -3; } else if (*ilo < 1 || *ilo > max(1,*n)) { *info = -4; } else if (*ihi < min(*ilo,*n) || *ihi > *n) { *info = -5; } else if (*ldh < max(1,*n)) { *info = -7; } else if (*ldz < 1 || wantz && *ldz < max(1,*n)) { *info = -11; } else if (*lwork < max(1,*n) && ! lquery) { *info = -13; } if (*info != 0) { // // ==== Quick return in case of invalid argument. ==== // i__1 = -(*info); xerbla_("DHSEQR", &i__1); return 0; } else if (*n == 0) { // // ==== Quick return in case N = 0; nothing to do. ==== // return 0; } else if (lquery) { // // ==== Quick return in case of a workspace query ==== // dlaqr0_(&wantt, &wantz, n, ilo, ihi, &h__[h_offset], ldh, &wr[1], &wi[ 1], ilo, ihi, &z__[z_offset], ldz, &work[1], lwork, info); // ==== Ensure reported workspace size is backward-compatible with // . previous LAPACK versions. ==== // Computing MAX d__1 = (double) max(1,*n); work[1] = max(d__1,work[1]); return 0; } else { // // ==== copy eigenvalues isolated by DGEBAL ==== // i__1 = *ilo - 1; for (i__ = 1; i__ <= i__1; ++i__) { wr[i__] = h__[i__ + i__ * h_dim1]; wi[i__] = 0.; // L10: } i__1 = *n; for (i__ = *ihi + 1; i__ <= i__1; ++i__) { wr[i__] = h__[i__ + i__ * h_dim1]; wi[i__] = 0.; // L20: } // // ==== Initialize Z, if requested ==== // if (initz) { dlaset_("A", n, n, &c_b11, &c_b12, &z__[z_offset], ldz); } // // ==== Quick return if possible ==== // if (*ilo == *ihi) { wr[*ilo] = h__[*ilo + *ilo * h_dim1]; wi[*ilo] = 0.; return 0; } // // ==== DLAHQR/DLAQR0 crossover point ==== // // Writing concatenation i__2[0] = 1, a__1[0] = job; i__2[1] = 1, a__1[1] = compz; s_cat(ch__1, a__1, i__2, &c__2); nmin = ilaenv_(&c__12, "DHSEQR", ch__1, n, ilo, ihi, lwork); nmin = max(11,nmin); // // ==== DLAQR0 for big matrices; DLAHQR for small ones ==== // if (*n > nmin) { dlaqr0_(&wantt, &wantz, n, ilo, ihi, &h__[h_offset], ldh, &wr[1], &wi[1], ilo, ihi, &z__[z_offset], ldz, &work[1], lwork, info); } else { // // ==== Small matrix ==== // dlahqr_(&wantt, &wantz, n, ilo, ihi, &h__[h_offset], ldh, &wr[1], &wi[1], ilo, ihi, &z__[z_offset], ldz, info); if (*info > 0) { // // ==== A rare DLAHQR failure! DLAQR0 sometimes succeeds // . when DLAHQR fails. ==== // kbot = *info; if (*n >= 49) { // // ==== Larger matrices have enough subdiagonal scratch // . space to call DLAQR0 directly. ==== // dlaqr0_(&wantt, &wantz, n, ilo, &kbot, &h__[h_offset], ldh, &wr[1], &wi[1], ilo, ihi, &z__[z_offset], ldz, &work[1], lwork, info); } else { // // ==== Tiny matrices don't have enough subdiagonal // . scratch space to benefit from DLAQR0. Hence, // . tiny matrices must be copied into a larger // . array before calling DLAQR0. ==== // dlacpy_("A", n, n, &h__[h_offset], ldh, hl, &c__49); hl[*n + 1 + *n * 49 - 50] = 0.; i__1 = 49 - *n; dlaset_("A", &c__49, &i__1, &c_b11, &c_b11, &hl[(*n + 1) * 49 - 49], &c__49); dlaqr0_(&wantt, &wantz, &c__49, ilo, &kbot, hl, &c__49, & wr[1], &wi[1], ilo, ihi, &z__[z_offset], ldz, workl, &c__49, info); if (wantt || *info != 0) { dlacpy_("A", n, n, hl, &c__49, &h__[h_offset], ldh); } } } } // // ==== Clear out the trash, if necessary. ==== // if ((wantt || *info != 0) && *n > 2) { i__1 = *n - 2; i__3 = *n - 2; dlaset_("L", &i__1, &i__3, &c_b11, &c_b11, &h__[h_dim1 + 3], ldh); } // // ==== Ensure reported workspace size is backward-compatible with // . previous LAPACK versions. ==== // // Computing MAX d__1 = (double) max(1,*n); work[1] = max(d__1,work[1]); } // // ==== End of DHSEQR ==== // return 0; } // dhseqr_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DLABAD // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DLABAD + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DLABAD( SMALL, LARGE ) // // .. Scalar Arguments .. // DOUBLE PRECISION LARGE, SMALL // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> DLABAD takes as input the values computed by DLAMCH for underflow and //> overflow, and returns the square root of each of these values if the //> log of LARGE is sufficiently large. This subroutine is intended to //> identify machines with a large exponent range, such as the Crays, and //> redefine the underflow and overflow limits to be the square roots of //> the values computed by DLAMCH. This subroutine is needed because //> DLAMCH does not compensate for poor arithmetic in the upper half of //> the exponent range, as is found on a Cray. //> \endverbatim // // Arguments: // ========== // //> \param[in,out] SMALL //> \verbatim //> SMALL is DOUBLE PRECISION //> On entry, the underflow threshold as computed by DLAMCH. //> On exit, if LOG10(LARGE) is sufficiently large, the square //> root of SMALL, otherwise unchanged. //> \endverbatim //> //> \param[in,out] LARGE //> \verbatim //> LARGE is DOUBLE PRECISION //> On entry, the overflow threshold as computed by DLAMCH. //> On exit, if LOG10(LARGE) is sufficiently large, the square //> root of LARGE, otherwise unchanged. //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date December 2016 // //> \ingroup OTHERauxiliary // // ===================================================================== /* Subroutine */ int dlabad_(double *small, double *large) { // // -- LAPACK auxiliary routine (version 3.7.0) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // December 2016 // // .. Scalar Arguments .. // .. // // ===================================================================== // // .. Intrinsic Functions .. // .. // .. Executable Statements .. // // If it looks like we're on a Cray, take the square root of // SMALL and LARGE to avoid overflow and underflow problems. // if (d_lg10(large) > 2e3) { *small = sqrt(*small); *large = sqrt(*large); } return 0; // // End of DLABAD // } // dlabad_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DLADIV performs complex division in real arithmetic, avoiding unnecessary overflow. // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DLADIV + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DLADIV( A, B, C, D, P, Q ) // // .. Scalar Arguments .. // DOUBLE PRECISION A, B, C, D, P, Q // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> DLADIV performs complex division in real arithmetic //> //> a + i*b //> p + i*q = --------- //> c + i*d //> //> The algorithm is due to Michael Baudin and Robert L. Smith //> and can be found in the paper //> "A Robust Complex Division in Scilab" //> \endverbatim // // Arguments: // ========== // //> \param[in] A //> \verbatim //> A is DOUBLE PRECISION //> \endverbatim //> //> \param[in] B //> \verbatim //> B is DOUBLE PRECISION //> \endverbatim //> //> \param[in] C //> \verbatim //> C is DOUBLE PRECISION //> \endverbatim //> //> \param[in] D //> \verbatim //> D is DOUBLE PRECISION //> The scalars a, b, c, and d in the above expression. //> \endverbatim //> //> \param[out] P //> \verbatim //> P is DOUBLE PRECISION //> \endverbatim //> //> \param[out] Q //> \verbatim //> Q is DOUBLE PRECISION //> The scalars p and q in the above expression. //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date January 2013 // //> \ingroup doubleOTHERauxiliary // // ===================================================================== /* Subroutine */ int dladiv_(double *a, double *b, double *c__, double *d__, double *p, double *q) { // System generated locals double d__1, d__2; // Local variables double s, aa, ab, bb, cc, cd, dd, be, un, ov, eps; extern double dlamch_(char *); extern /* Subroutine */ int dladiv1_(double *, double *, double *, double *, double *, double *); // // -- LAPACK auxiliary routine (version 3.7.0) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // January 2013 // // .. Scalar Arguments .. // .. // // ===================================================================== // // .. Parameters .. // // .. Local Scalars .. // .. // .. External Functions .. // .. // .. External Subroutines .. // .. // .. Intrinsic Functions .. // .. // .. Executable Statements .. // aa = *a; bb = *b; cc = *c__; dd = *d__; // Computing MAX d__1 = abs(*a), d__2 = abs(*b); ab = max(d__1,d__2); // Computing MAX d__1 = abs(*c__), d__2 = abs(*d__); cd = max(d__1,d__2); s = 1.; ov = dlamch_("Overflow threshold"); un = dlamch_("Safe minimum"); eps = dlamch_("Epsilon"); be = 2. / (eps * eps); if (ab >= ov * .5) { aa *= .5; bb *= .5; s *= 2.; } if (cd >= ov * .5) { cc *= .5; dd *= .5; s *= .5; } if (ab <= un * 2. / eps) { aa *= be; bb *= be; s /= be; } if (cd <= un * 2. / eps) { cc *= be; dd *= be; s *= be; } if (abs(*d__) <= abs(*c__)) { dladiv1_(&aa, &bb, &cc, &dd, p, q); } else { dladiv1_(&bb, &aa, &dd, &cc, p, q); *q = -(*q); } *p *= s; *q *= s; return 0; // // End of DLADIV // } // dladiv_ //> \ingroup doubleOTHERauxiliary /* Subroutine */ int dladiv1_(double *a, double *b, double *c__, double *d__, double *p, double *q) { double r__, t; extern double dladiv2_(double *, double *, double *, double *, double *, double *); // // -- LAPACK auxiliary routine (version 3.7.0) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // January 2013 // // .. Scalar Arguments .. // .. // // ===================================================================== // // .. Parameters .. // // .. Local Scalars .. // .. // .. External Functions .. // .. // .. Executable Statements .. // r__ = *d__ / *c__; t = 1. / (*c__ + *d__ * r__); *p = dladiv2_(a, b, c__, d__, &r__, &t); *a = -(*a); *q = dladiv2_(b, a, c__, d__, &r__, &t); return 0; // // End of DLADIV1 // } // dladiv1_ //> \ingroup doubleOTHERauxiliary double dladiv2_(double *a, double *b, double *c__, double *d__, double *r__, double *t) { // System generated locals double ret_val; // Local variables double br; // // -- LAPACK auxiliary routine (version 3.7.0) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // January 2013 // // .. Scalar Arguments .. // .. // // ===================================================================== // // .. Parameters .. // // .. Local Scalars .. // .. // .. Executable Statements .. // if (*r__ != 0.) { br = *b * *r__; if (br != 0.) { ret_val = (*a + br) * *t; } else { ret_val = *a * *t + *b * *t * *r__; } } else { ret_val = (*a + *d__ * (*b / *c__)) * *t; } return ret_val; // // End of DLADIV12 // } // dladiv2_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DLAEXC swaps adjacent diagonal blocks of a real upper quasi-triangular matrix in Schur canonical form, by an orthogonal similarity transformation. // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DLAEXC + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DLAEXC( WANTQ, N, T, LDT, Q, LDQ, J1, N1, N2, WORK, // INFO ) // // .. Scalar Arguments .. // LOGICAL WANTQ // INTEGER INFO, J1, LDQ, LDT, N, N1, N2 // .. // .. Array Arguments .. // DOUBLE PRECISION Q( LDQ, * ), T( LDT, * ), WORK( * ) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> DLAEXC swaps adjacent diagonal blocks T11 and T22 of order 1 or 2 in //> an upper quasi-triangular matrix T by an orthogonal similarity //> transformation. //> //> T must be in Schur canonical form, that is, block upper triangular //> with 1-by-1 and 2-by-2 diagonal blocks; each 2-by-2 diagonal block //> has its diagonal elemnts equal and its off-diagonal elements of //> opposite sign. //> \endverbatim // // Arguments: // ========== // //> \param[in] WANTQ //> \verbatim //> WANTQ is LOGICAL //> = .TRUE. : accumulate the transformation in the matrix Q; //> = .FALSE.: do not accumulate the transformation. //> \endverbatim //> //> \param[in] N //> \verbatim //> N is INTEGER //> The order of the matrix T. N >= 0. //> \endverbatim //> //> \param[in,out] T //> \verbatim //> T is DOUBLE PRECISION array, dimension (LDT,N) //> On entry, the upper quasi-triangular matrix T, in Schur //> canonical form. //> On exit, the updated matrix T, again in Schur canonical form. //> \endverbatim //> //> \param[in] LDT //> \verbatim //> LDT is INTEGER //> The leading dimension of the array T. LDT >= max(1,N). //> \endverbatim //> //> \param[in,out] Q //> \verbatim //> Q is DOUBLE PRECISION array, dimension (LDQ,N) //> On entry, if WANTQ is .TRUE., the orthogonal matrix Q. //> On exit, if WANTQ is .TRUE., the updated matrix Q. //> If WANTQ is .FALSE., Q is not referenced. //> \endverbatim //> //> \param[in] LDQ //> \verbatim //> LDQ is INTEGER //> The leading dimension of the array Q. //> LDQ >= 1; and if WANTQ is .TRUE., LDQ >= N. //> \endverbatim //> //> \param[in] J1 //> \verbatim //> J1 is INTEGER //> The index of the first row of the first block T11. //> \endverbatim //> //> \param[in] N1 //> \verbatim //> N1 is INTEGER //> The order of the first block T11. N1 = 0, 1 or 2. //> \endverbatim //> //> \param[in] N2 //> \verbatim //> N2 is INTEGER //> The order of the second block T22. N2 = 0, 1 or 2. //> \endverbatim //> //> \param[out] WORK //> \verbatim //> WORK is DOUBLE PRECISION array, dimension (N) //> \endverbatim //> //> \param[out] INFO //> \verbatim //> INFO is INTEGER //> = 0: successful exit //> = 1: the transformed matrix T would be too far from Schur //> form; the blocks are not swapped and T and Q are //> unchanged. //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date December 2016 // //> \ingroup doubleOTHERauxiliary // // ===================================================================== /* Subroutine */ int dlaexc_(int *wantq, int *n, double *t, int *ldt, double * q, int *ldq, int *j1, int *n1, int *n2, double *work, int *info) { // Table of constant values int c__1 = 1; int c__4 = 4; int c_false = FALSE_; int c_n1 = -1; int c__2 = 2; int c__3 = 3; // System generated locals int q_dim1, q_offset, t_dim1, t_offset, i__1; double d__1, d__2, d__3; // Local variables double d__[16] /* was [4][4] */; int k; double u[3], x[4] /* was [2][2] */; int j2, j3, j4; double u1[3], u2[3]; int nd; double cs, t11, t22, t33, sn, wi1, wi2, wr1, wr2, eps, tau, tau1, tau2; int ierr; double temp; extern /* Subroutine */ int drot_(int *, double *, int *, double *, int *, double *, double *); double scale, dnorm, xnorm; extern /* Subroutine */ int dlanv2_(double *, double *, double *, double * , double *, double *, double *, double *, double *, double *), dlasy2_(int *, int *, int *, int *, int *, double *, int *, double *, int *, double *, int *, double *, double *, int *, double *, int *); extern double dlamch_(char *), dlange_(char *, int *, int *, double *, int *, double *); extern /* Subroutine */ int dlarfg_(int *, double *, double *, int *, double *), dlacpy_(char *, int *, int *, double *, int *, double * , int *), dlartg_(double *, double *, double *, double *, double * ), dlarfx_(char *, int *, int *, double *, double *, double *, int *, double *); double thresh, smlnum; // // -- LAPACK auxiliary routine (version 3.7.0) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // December 2016 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // // ===================================================================== // // .. Parameters .. // .. // .. Local Scalars .. // .. // .. Local Arrays .. // .. // .. External Functions .. // .. // .. External Subroutines .. // .. // .. Intrinsic Functions .. // .. // .. Executable Statements .. // // Parameter adjustments t_dim1 = *ldt; t_offset = 1 + t_dim1; t -= t_offset; q_dim1 = *ldq; q_offset = 1 + q_dim1; q -= q_offset; --work; // Function Body *info = 0; // // Quick return if possible // if (*n == 0 || *n1 == 0 || *n2 == 0) { return 0; } if (*j1 + *n1 > *n) { return 0; } j2 = *j1 + 1; j3 = *j1 + 2; j4 = *j1 + 3; if (*n1 == 1 && *n2 == 1) { // // Swap two 1-by-1 blocks. // t11 = t[*j1 + *j1 * t_dim1]; t22 = t[j2 + j2 * t_dim1]; // // Determine the transformation to perform the interchange. // d__1 = t22 - t11; dlartg_(&t[*j1 + j2 * t_dim1], &d__1, &cs, &sn, &temp); // // Apply transformation to the matrix T. // if (j3 <= *n) { i__1 = *n - *j1 - 1; drot_(&i__1, &t[*j1 + j3 * t_dim1], ldt, &t[j2 + j3 * t_dim1], ldt, &cs, &sn); } i__1 = *j1 - 1; drot_(&i__1, &t[*j1 * t_dim1 + 1], &c__1, &t[j2 * t_dim1 + 1], &c__1, &cs, &sn); t[*j1 + *j1 * t_dim1] = t22; t[j2 + j2 * t_dim1] = t11; if (*wantq) { // // Accumulate transformation in the matrix Q. // drot_(n, &q[*j1 * q_dim1 + 1], &c__1, &q[j2 * q_dim1 + 1], &c__1, &cs, &sn); } } else { // // Swapping involves at least one 2-by-2 block. // // Copy the diagonal block of order N1+N2 to the local array D // and compute its norm. // nd = *n1 + *n2; dlacpy_("Full", &nd, &nd, &t[*j1 + *j1 * t_dim1], ldt, d__, &c__4); dnorm = dlange_("Max", &nd, &nd, d__, &c__4, &work[1]); // // Compute machine-dependent threshold for test for accepting // swap. // eps = dlamch_("P"); smlnum = dlamch_("S") / eps; // Computing MAX d__1 = eps * 10. * dnorm; thresh = max(d__1,smlnum); // // Solve T11*X - X*T22 = scale*T12 for X. // dlasy2_(&c_false, &c_false, &c_n1, n1, n2, d__, &c__4, &d__[*n1 + 1 + (*n1 + 1 << 2) - 5], &c__4, &d__[(*n1 + 1 << 2) - 4], &c__4, & scale, x, &c__2, &xnorm, &ierr); // // Swap the adjacent diagonal blocks. // k = *n1 + *n1 + *n2 - 3; switch (k) { case 1: goto L10; case 2: goto L20; case 3: goto L30; } L10: // // N1 = 1, N2 = 2: generate elementary reflector H so that: // // ( scale, X11, X12 ) H = ( 0, 0, * ) // u[0] = scale; u[1] = x[0]; u[2] = x[2]; dlarfg_(&c__3, &u[2], u, &c__1, &tau); u[2] = 1.; t11 = t[*j1 + *j1 * t_dim1]; // // Perform swap provisionally on diagonal block in D. // dlarfx_("L", &c__3, &c__3, u, &tau, d__, &c__4, &work[1]); dlarfx_("R", &c__3, &c__3, u, &tau, d__, &c__4, &work[1]); // // Test whether to reject swap. // // Computing MAX d__2 = abs(d__[2]), d__3 = abs(d__[6]), d__2 = max(d__2,d__3), d__3 = (d__1 = d__[10] - t11, abs(d__1)); if (max(d__2,d__3) > thresh) { goto L50; } // // Accept swap: apply transformation to the entire matrix T. // i__1 = *n - *j1 + 1; dlarfx_("L", &c__3, &i__1, u, &tau, &t[*j1 + *j1 * t_dim1], ldt, & work[1]); dlarfx_("R", &j2, &c__3, u, &tau, &t[*j1 * t_dim1 + 1], ldt, &work[1]) ; t[j3 + *j1 * t_dim1] = 0.; t[j3 + j2 * t_dim1] = 0.; t[j3 + j3 * t_dim1] = t11; if (*wantq) { // // Accumulate transformation in the matrix Q. // dlarfx_("R", n, &c__3, u, &tau, &q[*j1 * q_dim1 + 1], ldq, &work[ 1]); } goto L40; L20: // // N1 = 2, N2 = 1: generate elementary reflector H so that: // // H ( -X11 ) = ( * ) // ( -X21 ) = ( 0 ) // ( scale ) = ( 0 ) // u[0] = -x[0]; u[1] = -x[1]; u[2] = scale; dlarfg_(&c__3, u, &u[1], &c__1, &tau); u[0] = 1.; t33 = t[j3 + j3 * t_dim1]; // // Perform swap provisionally on diagonal block in D. // dlarfx_("L", &c__3, &c__3, u, &tau, d__, &c__4, &work[1]); dlarfx_("R", &c__3, &c__3, u, &tau, d__, &c__4, &work[1]); // // Test whether to reject swap. // // Computing MAX d__2 = abs(d__[1]), d__3 = abs(d__[2]), d__2 = max(d__2,d__3), d__3 = (d__1 = d__[0] - t33, abs(d__1)); if (max(d__2,d__3) > thresh) { goto L50; } // // Accept swap: apply transformation to the entire matrix T. // dlarfx_("R", &j3, &c__3, u, &tau, &t[*j1 * t_dim1 + 1], ldt, &work[1]) ; i__1 = *n - *j1; dlarfx_("L", &c__3, &i__1, u, &tau, &t[*j1 + j2 * t_dim1], ldt, &work[ 1]); t[*j1 + *j1 * t_dim1] = t33; t[j2 + *j1 * t_dim1] = 0.; t[j3 + *j1 * t_dim1] = 0.; if (*wantq) { // // Accumulate transformation in the matrix Q. // dlarfx_("R", n, &c__3, u, &tau, &q[*j1 * q_dim1 + 1], ldq, &work[ 1]); } goto L40; L30: // // N1 = 2, N2 = 2: generate elementary reflectors H(1) and H(2) so // that: // // H(2) H(1) ( -X11 -X12 ) = ( * * ) // ( -X21 -X22 ) ( 0 * ) // ( scale 0 ) ( 0 0 ) // ( 0 scale ) ( 0 0 ) // u1[0] = -x[0]; u1[1] = -x[1]; u1[2] = scale; dlarfg_(&c__3, u1, &u1[1], &c__1, &tau1); u1[0] = 1.; temp = -tau1 * (x[2] + u1[1] * x[3]); u2[0] = -temp * u1[1] - x[3]; u2[1] = -temp * u1[2]; u2[2] = scale; dlarfg_(&c__3, u2, &u2[1], &c__1, &tau2); u2[0] = 1.; // // Perform swap provisionally on diagonal block in D. // dlarfx_("L", &c__3, &c__4, u1, &tau1, d__, &c__4, &work[1]); dlarfx_("R", &c__4, &c__3, u1, &tau1, d__, &c__4, &work[1]); dlarfx_("L", &c__3, &c__4, u2, &tau2, &d__[1], &c__4, &work[1]); dlarfx_("R", &c__4, &c__3, u2, &tau2, &d__[4], &c__4, &work[1]); // // Test whether to reject swap. // // Computing MAX d__1 = abs(d__[2]), d__2 = abs(d__[6]), d__1 = max(d__1,d__2), d__2 = abs(d__[3]), d__1 = max(d__1,d__2), d__2 = abs(d__[7]); if (max(d__1,d__2) > thresh) { goto L50; } // // Accept swap: apply transformation to the entire matrix T. // i__1 = *n - *j1 + 1; dlarfx_("L", &c__3, &i__1, u1, &tau1, &t[*j1 + *j1 * t_dim1], ldt, & work[1]); dlarfx_("R", &j4, &c__3, u1, &tau1, &t[*j1 * t_dim1 + 1], ldt, &work[ 1]); i__1 = *n - *j1 + 1; dlarfx_("L", &c__3, &i__1, u2, &tau2, &t[j2 + *j1 * t_dim1], ldt, & work[1]); dlarfx_("R", &j4, &c__3, u2, &tau2, &t[j2 * t_dim1 + 1], ldt, &work[1] ); t[j3 + *j1 * t_dim1] = 0.; t[j3 + j2 * t_dim1] = 0.; t[j4 + *j1 * t_dim1] = 0.; t[j4 + j2 * t_dim1] = 0.; if (*wantq) { // // Accumulate transformation in the matrix Q. // dlarfx_("R", n, &c__3, u1, &tau1, &q[*j1 * q_dim1 + 1], ldq, & work[1]); dlarfx_("R", n, &c__3, u2, &tau2, &q[j2 * q_dim1 + 1], ldq, &work[ 1]); } L40: if (*n2 == 2) { // // Standardize new 2-by-2 block T11 // dlanv2_(&t[*j1 + *j1 * t_dim1], &t[*j1 + j2 * t_dim1], &t[j2 + * j1 * t_dim1], &t[j2 + j2 * t_dim1], &wr1, &wi1, &wr2, & wi2, &cs, &sn); i__1 = *n - *j1 - 1; drot_(&i__1, &t[*j1 + (*j1 + 2) * t_dim1], ldt, &t[j2 + (*j1 + 2) * t_dim1], ldt, &cs, &sn); i__1 = *j1 - 1; drot_(&i__1, &t[*j1 * t_dim1 + 1], &c__1, &t[j2 * t_dim1 + 1], & c__1, &cs, &sn); if (*wantq) { drot_(n, &q[*j1 * q_dim1 + 1], &c__1, &q[j2 * q_dim1 + 1], & c__1, &cs, &sn); } } if (*n1 == 2) { // // Standardize new 2-by-2 block T22 // j3 = *j1 + *n2; j4 = j3 + 1; dlanv2_(&t[j3 + j3 * t_dim1], &t[j3 + j4 * t_dim1], &t[j4 + j3 * t_dim1], &t[j4 + j4 * t_dim1], &wr1, &wi1, &wr2, &wi2, & cs, &sn); if (j3 + 2 <= *n) { i__1 = *n - j3 - 1; drot_(&i__1, &t[j3 + (j3 + 2) * t_dim1], ldt, &t[j4 + (j3 + 2) * t_dim1], ldt, &cs, &sn); } i__1 = j3 - 1; drot_(&i__1, &t[j3 * t_dim1 + 1], &c__1, &t[j4 * t_dim1 + 1], & c__1, &cs, &sn); if (*wantq) { drot_(n, &q[j3 * q_dim1 + 1], &c__1, &q[j4 * q_dim1 + 1], & c__1, &cs, &sn); } } } return 0; // // Exit with INFO = 1 if swap was rejected. // L50: *info = 1; return 0; // // End of DLAEXC // } // dlaexc_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DLAHQR computes the eigenvalues and Schur factorization of an upper Hessenberg matrix, using the double-shift/single-shift QR algorithm. // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DLAHQR + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DLAHQR( WANTT, WANTZ, N, ILO, IHI, H, LDH, WR, WI, // ILOZ, IHIZ, Z, LDZ, INFO ) // // .. Scalar Arguments .. // INTEGER IHI, IHIZ, ILO, ILOZ, INFO, LDH, LDZ, N // LOGICAL WANTT, WANTZ // .. // .. Array Arguments .. // DOUBLE PRECISION H( LDH, * ), WI( * ), WR( * ), Z( LDZ, * ) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> DLAHQR is an auxiliary routine called by DHSEQR to update the //> eigenvalues and Schur decomposition already computed by DHSEQR, by //> dealing with the Hessenberg submatrix in rows and columns ILO to //> IHI. //> \endverbatim // // Arguments: // ========== // //> \param[in] WANTT //> \verbatim //> WANTT is LOGICAL //> = .TRUE. : the full Schur form T is required; //> = .FALSE.: only eigenvalues are required. //> \endverbatim //> //> \param[in] WANTZ //> \verbatim //> WANTZ is LOGICAL //> = .TRUE. : the matrix of Schur vectors Z is required; //> = .FALSE.: Schur vectors are not required. //> \endverbatim //> //> \param[in] N //> \verbatim //> N is INTEGER //> The order of the matrix H. N >= 0. //> \endverbatim //> //> \param[in] ILO //> \verbatim //> ILO is INTEGER //> \endverbatim //> //> \param[in] IHI //> \verbatim //> IHI is INTEGER //> It is assumed that H is already upper quasi-triangular in //> rows and columns IHI+1:N, and that H(ILO,ILO-1) = 0 (unless //> ILO = 1). DLAHQR works primarily with the Hessenberg //> submatrix in rows and columns ILO to IHI, but applies //> transformations to all of H if WANTT is .TRUE.. //> 1 <= ILO <= max(1,IHI); IHI <= N. //> \endverbatim //> //> \param[in,out] H //> \verbatim //> H is DOUBLE PRECISION array, dimension (LDH,N) //> On entry, the upper Hessenberg matrix H. //> On exit, if INFO is zero and if WANTT is .TRUE., H is upper //> quasi-triangular in rows and columns ILO:IHI, with any //> 2-by-2 diagonal blocks in standard form. If INFO is zero //> and WANTT is .FALSE., the contents of H are unspecified on //> exit. The output state of H if INFO is nonzero is given //> below under the description of INFO. //> \endverbatim //> //> \param[in] LDH //> \verbatim //> LDH is INTEGER //> The leading dimension of the array H. LDH >= max(1,N). //> \endverbatim //> //> \param[out] WR //> \verbatim //> WR is DOUBLE PRECISION array, dimension (N) //> \endverbatim //> //> \param[out] WI //> \verbatim //> WI is DOUBLE PRECISION array, dimension (N) //> The real and imaginary parts, respectively, of the computed //> eigenvalues ILO to IHI are stored in the corresponding //> elements of WR and WI. If two eigenvalues are computed as a //> complex conjugate pair, they are stored in consecutive //> elements of WR and WI, say the i-th and (i+1)th, with //> WI(i) > 0 and WI(i+1) < 0. If WANTT is .TRUE., the //> eigenvalues are stored in the same order as on the diagonal //> of the Schur form returned in H, with WR(i) = H(i,i), and, if //> H(i:i+1,i:i+1) is a 2-by-2 diagonal block, //> WI(i) = sqrt(H(i+1,i)*H(i,i+1)) and WI(i+1) = -WI(i). //> \endverbatim //> //> \param[in] ILOZ //> \verbatim //> ILOZ is INTEGER //> \endverbatim //> //> \param[in] IHIZ //> \verbatim //> IHIZ is INTEGER //> Specify the rows of Z to which transformations must be //> applied if WANTZ is .TRUE.. //> 1 <= ILOZ <= ILO; IHI <= IHIZ <= N. //> \endverbatim //> //> \param[in,out] Z //> \verbatim //> Z is DOUBLE PRECISION array, dimension (LDZ,N) //> If WANTZ is .TRUE., on entry Z must contain the current //> matrix Z of transformations accumulated by DHSEQR, and on //> exit Z has been updated; transformations are applied only to //> the submatrix Z(ILOZ:IHIZ,ILO:IHI). //> If WANTZ is .FALSE., Z is not referenced. //> \endverbatim //> //> \param[in] LDZ //> \verbatim //> LDZ is INTEGER //> The leading dimension of the array Z. LDZ >= max(1,N). //> \endverbatim //> //> \param[out] INFO //> \verbatim //> INFO is INTEGER //> = 0: successful exit //> > 0: If INFO = i, DLAHQR failed to compute all the //> eigenvalues ILO to IHI in a total of 30 iterations //> per eigenvalue; elements i+1:ihi of WR and WI //> contain those eigenvalues which have been //> successfully computed. //> //> If INFO > 0 and WANTT is .FALSE., then on exit, //> the remaining unconverged eigenvalues are the //> eigenvalues of the upper Hessenberg matrix rows //> and columns ILO through INFO of the final, output //> value of H. //> //> If INFO > 0 and WANTT is .TRUE., then on exit //> (*) (initial value of H)*U = U*(final value of H) //> where U is an orthogonal matrix. The final //> value of H is upper Hessenberg and triangular in //> rows and columns INFO+1 through IHI. //> //> If INFO > 0 and WANTZ is .TRUE., then on exit //> (final value of Z) = (initial value of Z)*U //> where U is the orthogonal matrix in (*) //> (regardless of the value of WANTT.) //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date December 2016 // //> \ingroup doubleOTHERauxiliary // //> \par Further Details: // ===================== //> //> \verbatim //> //> 02-96 Based on modifications by //> David Day, Sandia National Laboratory, USA //> //> 12-04 Further modifications by //> Ralph Byers, University of Kansas, USA //> This is a modified version of DLAHQR from LAPACK version 3.0. //> It is (1) more robust against overflow and underflow and //> (2) adopts the more conservative Ahues & Tisseur stopping //> criterion (LAWN 122, 1997). //> \endverbatim //> // ===================================================================== /* Subroutine */ int dlahqr_(int *wantt, int *wantz, int *n, int *ilo, int * ihi, double *h__, int *ldh, double *wr, double *wi, int *iloz, int * ihiz, double *z__, int *ldz, int *info) { // Table of constant values int c__1 = 1; // System generated locals int h_dim1, h_offset, z_dim1, z_offset, i__1, i__2, i__3, i__4; double d__1, d__2, d__3, d__4; // Local variables int i__, j, k, l, m; double s, v[3]; int i1, i2; double t1, t2, t3, v2, v3, aa, ab, ba, bb, h11, h12, h21, h22, cs; int nh; double sn; int nr; double tr; int nz; double det, h21s; int its; double ulp, sum, tst, rt1i, rt2i, rt1r, rt2r; extern /* Subroutine */ int drot_(int *, double *, int *, double *, int *, double *, double *), dcopy_(int *, double *, int *, double *, int *); int itmax; extern /* Subroutine */ int dlanv2_(double *, double *, double *, double * , double *, double *, double *, double *, double *, double *), dlabad_(double *, double *); extern double dlamch_(char *); extern /* Subroutine */ int dlarfg_(int *, double *, double *, int *, double *); double safmin, safmax, rtdisc, smlnum; // // -- LAPACK auxiliary routine (version 3.7.0) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // December 2016 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // // ========================================================= // // .. Parameters .. // .. // .. Local Scalars .. // .. // .. Local Arrays .. // .. // .. External Functions .. // .. // .. External Subroutines .. // .. // .. Intrinsic Functions .. // .. // .. Executable Statements .. // // Parameter adjustments h_dim1 = *ldh; h_offset = 1 + h_dim1; h__ -= h_offset; --wr; --wi; z_dim1 = *ldz; z_offset = 1 + z_dim1; z__ -= z_offset; // Function Body *info = 0; // // Quick return if possible // if (*n == 0) { return 0; } if (*ilo == *ihi) { wr[*ilo] = h__[*ilo + *ilo * h_dim1]; wi[*ilo] = 0.; return 0; } // // ==== clear out the trash ==== i__1 = *ihi - 3; for (j = *ilo; j <= i__1; ++j) { h__[j + 2 + j * h_dim1] = 0.; h__[j + 3 + j * h_dim1] = 0.; // L10: } if (*ilo <= *ihi - 2) { h__[*ihi + (*ihi - 2) * h_dim1] = 0.; } nh = *ihi - *ilo + 1; nz = *ihiz - *iloz + 1; // // Set machine-dependent constants for the stopping criterion. // safmin = dlamch_("SAFE MINIMUM"); safmax = 1. / safmin; dlabad_(&safmin, &safmax); ulp = dlamch_("PRECISION"); smlnum = safmin * ((double) nh / ulp); // // I1 and I2 are the indices of the first row and last column of H // to which transformations must be applied. If eigenvalues only are // being computed, I1 and I2 are set inside the main loop. // if (*wantt) { i1 = 1; i2 = *n; } // // ITMAX is the total number of QR iterations allowed. // itmax = max(10,nh) * 30; // // The main loop begins here. I is the loop index and decreases from // IHI to ILO in steps of 1 or 2. Each iteration of the loop works // with the active submatrix in rows and columns L to I. // Eigenvalues I+1 to IHI have already converged. Either L = ILO or // H(L,L-1) is negligible so that the matrix splits. // i__ = *ihi; L20: l = *ilo; if (i__ < *ilo) { goto L160; } // // Perform QR iterations on rows and columns ILO to I until a // submatrix of order 1 or 2 splits off at the bottom because a // subdiagonal element has become negligible. // i__1 = itmax; for (its = 0; its <= i__1; ++its) { // // Look for a single small subdiagonal element. // i__2 = l + 1; for (k = i__; k >= i__2; --k) { if ((d__1 = h__[k + (k - 1) * h_dim1], abs(d__1)) <= smlnum) { goto L40; } tst = (d__1 = h__[k - 1 + (k - 1) * h_dim1], abs(d__1)) + (d__2 = h__[k + k * h_dim1], abs(d__2)); if (tst == 0.) { if (k - 2 >= *ilo) { tst += (d__1 = h__[k - 1 + (k - 2) * h_dim1], abs(d__1)); } if (k + 1 <= *ihi) { tst += (d__1 = h__[k + 1 + k * h_dim1], abs(d__1)); } } // ==== The following is a conservative small subdiagonal // . deflation criterion due to Ahues & Tisseur (LAWN 122, // . 1997). It has better mathematical foundation and // . improves accuracy in some cases. ==== if ((d__1 = h__[k + (k - 1) * h_dim1], abs(d__1)) <= ulp * tst) { // Computing MAX d__3 = (d__1 = h__[k + (k - 1) * h_dim1], abs(d__1)), d__4 = ( d__2 = h__[k - 1 + k * h_dim1], abs(d__2)); ab = max(d__3,d__4); // Computing MIN d__3 = (d__1 = h__[k + (k - 1) * h_dim1], abs(d__1)), d__4 = ( d__2 = h__[k - 1 + k * h_dim1], abs(d__2)); ba = min(d__3,d__4); // Computing MAX d__3 = (d__1 = h__[k + k * h_dim1], abs(d__1)), d__4 = (d__2 = h__[k - 1 + (k - 1) * h_dim1] - h__[k + k * h_dim1], abs(d__2)); aa = max(d__3,d__4); // Computing MIN d__3 = (d__1 = h__[k + k * h_dim1], abs(d__1)), d__4 = (d__2 = h__[k - 1 + (k - 1) * h_dim1] - h__[k + k * h_dim1], abs(d__2)); bb = min(d__3,d__4); s = aa + ab; // Computing MAX d__1 = smlnum, d__2 = ulp * (bb * (aa / s)); if (ba * (ab / s) <= max(d__1,d__2)) { goto L40; } } // L30: } L40: l = k; if (l > *ilo) { // // H(L,L-1) is negligible // h__[l + (l - 1) * h_dim1] = 0.; } // // Exit from loop if a submatrix of order 1 or 2 has split off. // if (l >= i__ - 1) { goto L150; } // // Now the active submatrix is in rows and columns L to I. If // eigenvalues only are being computed, only the active submatrix // need be transformed. // if (! (*wantt)) { i1 = l; i2 = i__; } if (its == 10) { // // Exceptional shift. // s = (d__1 = h__[l + 1 + l * h_dim1], abs(d__1)) + (d__2 = h__[l + 2 + (l + 1) * h_dim1], abs(d__2)); h11 = s * .75 + h__[l + l * h_dim1]; h12 = s * -.4375; h21 = s; h22 = h11; } else if (its == 20) { // // Exceptional shift. // s = (d__1 = h__[i__ + (i__ - 1) * h_dim1], abs(d__1)) + (d__2 = h__[i__ - 1 + (i__ - 2) * h_dim1], abs(d__2)); h11 = s * .75 + h__[i__ + i__ * h_dim1]; h12 = s * -.4375; h21 = s; h22 = h11; } else { // // Prepare to use Francis' double shift // (i.e. 2nd degree generalized Rayleigh quotient) // h11 = h__[i__ - 1 + (i__ - 1) * h_dim1]; h21 = h__[i__ + (i__ - 1) * h_dim1]; h12 = h__[i__ - 1 + i__ * h_dim1]; h22 = h__[i__ + i__ * h_dim1]; } s = abs(h11) + abs(h12) + abs(h21) + abs(h22); if (s == 0.) { rt1r = 0.; rt1i = 0.; rt2r = 0.; rt2i = 0.; } else { h11 /= s; h21 /= s; h12 /= s; h22 /= s; tr = (h11 + h22) / 2.; det = (h11 - tr) * (h22 - tr) - h12 * h21; rtdisc = sqrt((abs(det))); if (det >= 0.) { // // ==== complex conjugate shifts ==== // rt1r = tr * s; rt2r = rt1r; rt1i = rtdisc * s; rt2i = -rt1i; } else { // // ==== real shifts (use only one of them) ==== // rt1r = tr + rtdisc; rt2r = tr - rtdisc; if ((d__1 = rt1r - h22, abs(d__1)) <= (d__2 = rt2r - h22, abs( d__2))) { rt1r *= s; rt2r = rt1r; } else { rt2r *= s; rt1r = rt2r; } rt1i = 0.; rt2i = 0.; } } // // Look for two consecutive small subdiagonal elements. // i__2 = l; for (m = i__ - 2; m >= i__2; --m) { // Determine the effect of starting the double-shift QR // iteration at row M, and see if this would make H(M,M-1) // negligible. (The following uses scaling to avoid // overflows and most underflows.) // h21s = h__[m + 1 + m * h_dim1]; s = (d__1 = h__[m + m * h_dim1] - rt2r, abs(d__1)) + abs(rt2i) + abs(h21s); h21s = h__[m + 1 + m * h_dim1] / s; v[0] = h21s * h__[m + (m + 1) * h_dim1] + (h__[m + m * h_dim1] - rt1r) * ((h__[m + m * h_dim1] - rt2r) / s) - rt1i * (rt2i / s); v[1] = h21s * (h__[m + m * h_dim1] + h__[m + 1 + (m + 1) * h_dim1] - rt1r - rt2r); v[2] = h21s * h__[m + 2 + (m + 1) * h_dim1]; s = abs(v[0]) + abs(v[1]) + abs(v[2]); v[0] /= s; v[1] /= s; v[2] /= s; if (m == l) { goto L60; } if ((d__1 = h__[m + (m - 1) * h_dim1], abs(d__1)) * (abs(v[1]) + abs(v[2])) <= ulp * abs(v[0]) * ((d__2 = h__[m - 1 + (m - 1) * h_dim1], abs(d__2)) + (d__3 = h__[m + m * h_dim1], abs(d__3)) + (d__4 = h__[m + 1 + (m + 1) * h_dim1], abs( d__4)))) { goto L60; } // L50: } L60: // // Double-shift QR step // i__2 = i__ - 1; for (k = m; k <= i__2; ++k) { // // The first iteration of this loop determines a reflection G // from the vector V and applies it from left and right to H, // thus creating a nonzero bulge below the subdiagonal. // // Each subsequent iteration determines a reflection G to // restore the Hessenberg form in the (K-1)th column, and thus // chases the bulge one step toward the bottom of the active // submatrix. NR is the order of G. // // Computing MIN i__3 = 3, i__4 = i__ - k + 1; nr = min(i__3,i__4); if (k > m) { dcopy_(&nr, &h__[k + (k - 1) * h_dim1], &c__1, v, &c__1); } dlarfg_(&nr, v, &v[1], &c__1, &t1); if (k > m) { h__[k + (k - 1) * h_dim1] = v[0]; h__[k + 1 + (k - 1) * h_dim1] = 0.; if (k < i__ - 1) { h__[k + 2 + (k - 1) * h_dim1] = 0.; } } else if (m > l) { // ==== Use the following instead of // . H( K, K-1 ) = -H( K, K-1 ) to // . avoid a bug when v(2) and v(3) // . underflow. ==== h__[k + (k - 1) * h_dim1] *= 1. - t1; } v2 = v[1]; t2 = t1 * v2; if (nr == 3) { v3 = v[2]; t3 = t1 * v3; // // Apply G from the left to transform the rows of the matrix // in columns K to I2. // i__3 = i2; for (j = k; j <= i__3; ++j) { sum = h__[k + j * h_dim1] + v2 * h__[k + 1 + j * h_dim1] + v3 * h__[k + 2 + j * h_dim1]; h__[k + j * h_dim1] -= sum * t1; h__[k + 1 + j * h_dim1] -= sum * t2; h__[k + 2 + j * h_dim1] -= sum * t3; // L70: } // // Apply G from the right to transform the columns of the // matrix in rows I1 to min(K+3,I). // // Computing MIN i__4 = k + 3; i__3 = min(i__4,i__); for (j = i1; j <= i__3; ++j) { sum = h__[j + k * h_dim1] + v2 * h__[j + (k + 1) * h_dim1] + v3 * h__[j + (k + 2) * h_dim1]; h__[j + k * h_dim1] -= sum * t1; h__[j + (k + 1) * h_dim1] -= sum * t2; h__[j + (k + 2) * h_dim1] -= sum * t3; // L80: } if (*wantz) { // // Accumulate transformations in the matrix Z // i__3 = *ihiz; for (j = *iloz; j <= i__3; ++j) { sum = z__[j + k * z_dim1] + v2 * z__[j + (k + 1) * z_dim1] + v3 * z__[j + (k + 2) * z_dim1]; z__[j + k * z_dim1] -= sum * t1; z__[j + (k + 1) * z_dim1] -= sum * t2; z__[j + (k + 2) * z_dim1] -= sum * t3; // L90: } } } else if (nr == 2) { // // Apply G from the left to transform the rows of the matrix // in columns K to I2. // i__3 = i2; for (j = k; j <= i__3; ++j) { sum = h__[k + j * h_dim1] + v2 * h__[k + 1 + j * h_dim1]; h__[k + j * h_dim1] -= sum * t1; h__[k + 1 + j * h_dim1] -= sum * t2; // L100: } // // Apply G from the right to transform the columns of the // matrix in rows I1 to min(K+3,I). // i__3 = i__; for (j = i1; j <= i__3; ++j) { sum = h__[j + k * h_dim1] + v2 * h__[j + (k + 1) * h_dim1] ; h__[j + k * h_dim1] -= sum * t1; h__[j + (k + 1) * h_dim1] -= sum * t2; // L110: } if (*wantz) { // // Accumulate transformations in the matrix Z // i__3 = *ihiz; for (j = *iloz; j <= i__3; ++j) { sum = z__[j + k * z_dim1] + v2 * z__[j + (k + 1) * z_dim1]; z__[j + k * z_dim1] -= sum * t1; z__[j + (k + 1) * z_dim1] -= sum * t2; // L120: } } } // L130: } // L140: } // // Failure to converge in remaining number of iterations // *info = i__; return 0; L150: if (l == i__) { // // H(I,I-1) is negligible: one eigenvalue has converged. // wr[i__] = h__[i__ + i__ * h_dim1]; wi[i__] = 0.; } else if (l == i__ - 1) { // // H(I-1,I-2) is negligible: a pair of eigenvalues have converged. // // Transform the 2-by-2 submatrix to standard Schur form, // and compute and store the eigenvalues. // dlanv2_(&h__[i__ - 1 + (i__ - 1) * h_dim1], &h__[i__ - 1 + i__ * h_dim1], &h__[i__ + (i__ - 1) * h_dim1], &h__[i__ + i__ * h_dim1], &wr[i__ - 1], &wi[i__ - 1], &wr[i__], &wi[i__], &cs, &sn); if (*wantt) { // // Apply the transformation to the rest of H. // if (i2 > i__) { i__1 = i2 - i__; drot_(&i__1, &h__[i__ - 1 + (i__ + 1) * h_dim1], ldh, &h__[ i__ + (i__ + 1) * h_dim1], ldh, &cs, &sn); } i__1 = i__ - i1 - 1; drot_(&i__1, &h__[i1 + (i__ - 1) * h_dim1], &c__1, &h__[i1 + i__ * h_dim1], &c__1, &cs, &sn); } if (*wantz) { // // Apply the transformation to Z. // drot_(&nz, &z__[*iloz + (i__ - 1) * z_dim1], &c__1, &z__[*iloz + i__ * z_dim1], &c__1, &cs, &sn); } } // // return to start of the main loop with new value of I. // i__ = l - 1; goto L20; L160: return 0; // // End of DLAHQR // } // dlahqr_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DLAHR2 reduces the specified number of first columns of a general rectangular matrix A so that elements below the specified subdiagonal are zero, and returns auxiliary matrices which are needed to apply the transformation to the unreduced part of A. // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DLAHR2 + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DLAHR2( N, K, NB, A, LDA, TAU, T, LDT, Y, LDY ) // // .. Scalar Arguments .. // INTEGER K, LDA, LDT, LDY, N, NB // .. // .. Array Arguments .. // DOUBLE PRECISION A( LDA, * ), T( LDT, NB ), TAU( NB ), // $ Y( LDY, NB ) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> DLAHR2 reduces the first NB columns of A real general n-BY-(n-k+1) //> matrix A so that elements below the k-th subdiagonal are zero. The //> reduction is performed by an orthogonal similarity transformation //> Q**T * A * Q. The routine returns the matrices V and T which determine //> Q as a block reflector I - V*T*V**T, and also the matrix Y = A * V * T. //> //> This is an auxiliary routine called by DGEHRD. //> \endverbatim // // Arguments: // ========== // //> \param[in] N //> \verbatim //> N is INTEGER //> The order of the matrix A. //> \endverbatim //> //> \param[in] K //> \verbatim //> K is INTEGER //> The offset for the reduction. Elements below the k-th //> subdiagonal in the first NB columns are reduced to zero. //> K < N. //> \endverbatim //> //> \param[in] NB //> \verbatim //> NB is INTEGER //> The number of columns to be reduced. //> \endverbatim //> //> \param[in,out] A //> \verbatim //> A is DOUBLE PRECISION array, dimension (LDA,N-K+1) //> On entry, the n-by-(n-k+1) general matrix A. //> On exit, the elements on and above the k-th subdiagonal in //> the first NB columns are overwritten with the corresponding //> elements of the reduced matrix; the elements below the k-th //> subdiagonal, with the array TAU, represent the matrix Q as a //> product of elementary reflectors. The other columns of A are //> unchanged. See Further Details. //> \endverbatim //> //> \param[in] LDA //> \verbatim //> LDA is INTEGER //> The leading dimension of the array A. LDA >= max(1,N). //> \endverbatim //> //> \param[out] TAU //> \verbatim //> TAU is DOUBLE PRECISION array, dimension (NB) //> The scalar factors of the elementary reflectors. See Further //> Details. //> \endverbatim //> //> \param[out] T //> \verbatim //> T is DOUBLE PRECISION array, dimension (LDT,NB) //> The upper triangular matrix T. //> \endverbatim //> //> \param[in] LDT //> \verbatim //> LDT is INTEGER //> The leading dimension of the array T. LDT >= NB. //> \endverbatim //> //> \param[out] Y //> \verbatim //> Y is DOUBLE PRECISION array, dimension (LDY,NB) //> The n-by-nb matrix Y. //> \endverbatim //> //> \param[in] LDY //> \verbatim //> LDY is INTEGER //> The leading dimension of the array Y. LDY >= N. //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date December 2016 // //> \ingroup doubleOTHERauxiliary // //> \par Further Details: // ===================== //> //> \verbatim //> //> The matrix Q is represented as a product of nb elementary reflectors //> //> Q = H(1) H(2) . . . H(nb). //> //> Each H(i) has the form //> //> H(i) = I - tau * v * v**T //> //> where tau is a real scalar, and v is a real vector with //> v(1:i+k-1) = 0, v(i+k) = 1; v(i+k+1:n) is stored on exit in //> A(i+k+1:n,i), and tau in TAU(i). //> //> The elements of the vectors v together form the (n-k+1)-by-nb matrix //> V which is needed, with T and Y, to apply the transformation to the //> unreduced part of the matrix, using an update of the form: //> A := (I - V*T*V**T) * (A - Y*V**T). //> //> The contents of A on exit are illustrated by the following example //> with n = 7, k = 3 and nb = 2: //> //> ( a a a a a ) //> ( a a a a a ) //> ( a a a a a ) //> ( h h a a a ) //> ( v1 h a a a ) //> ( v1 v2 a a a ) //> ( v1 v2 a a a ) //> //> where a denotes an element of the original matrix A, h denotes a //> modified element of the upper Hessenberg matrix H, and vi denotes an //> element of the vector defining H(i). //> //> This subroutine is a slight modification of LAPACK-3.0's DLAHRD //> incorporating improvements proposed by Quintana-Orti and Van de //> Gejin. Note that the entries of A(1:K,2:NB) differ from those //> returned by the original LAPACK-3.0's DLAHRD routine. (This //> subroutine is not backward compatible with LAPACK-3.0's DLAHRD.) //> \endverbatim // //> \par References: // ================ //> //> Gregorio Quintana-Orti and Robert van de Geijn, "Improving the //> performance of reduction to Hessenberg form," ACM Transactions on //> Mathematical Software, 32(2):180-194, June 2006. //> // ===================================================================== /* Subroutine */ int dlahr2_(int *n, int *k, int *nb, double *a, int *lda, double *tau, double *t, int *ldt, double *y, int *ldy) { // Table of constant values double c_b4 = -1.; double c_b5 = 1.; int c__1 = 1; double c_b38 = 0.; // System generated locals int a_dim1, a_offset, t_dim1, t_offset, y_dim1, y_offset, i__1, i__2, i__3; double d__1; // Local variables int i__; double ei; extern /* Subroutine */ int dscal_(int *, double *, double *, int *), dgemm_(char *, char *, int *, int *, int *, double *, double *, int *, double *, int *, double *, double *, int *), dgemv_(char *, int *, int *, double *, double *, int *, double *, int *, double *, double *, int *), dcopy_(int *, double *, int *, double *, int *), dtrmm_(char *, char *, char *, char *, int *, int *, double *, double *, int *, double *, int *), daxpy_(int *, double *, double *, int *, double *, int *), dtrmv_(char *, char *, char *, int *, double *, int *, double *, int *), dlarfg_(int *, double *, double *, int *, double *), dlacpy_(char *, int *, int *, double *, int *, double *, int *); // // -- LAPACK auxiliary routine (version 3.7.0) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // December 2016 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // // ===================================================================== // // .. Parameters .. // .. // .. Local Scalars .. // .. // .. External Subroutines .. // .. // .. Intrinsic Functions .. // .. // .. Executable Statements .. // // Quick return if possible // // Parameter adjustments --tau; a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; t_dim1 = *ldt; t_offset = 1 + t_dim1; t -= t_offset; y_dim1 = *ldy; y_offset = 1 + y_dim1; y -= y_offset; // Function Body if (*n <= 1) { return 0; } i__1 = *nb; for (i__ = 1; i__ <= i__1; ++i__) { if (i__ > 1) { // // Update A(K+1:N,I) // // Update I-th column of A - Y * V**T // i__2 = *n - *k; i__3 = i__ - 1; dgemv_("NO TRANSPOSE", &i__2, &i__3, &c_b4, &y[*k + 1 + y_dim1], ldy, &a[*k + i__ - 1 + a_dim1], lda, &c_b5, &a[*k + 1 + i__ * a_dim1], &c__1); // // Apply I - V * T**T * V**T to this column (call it b) from the // left, using the last column of T as workspace // // Let V = ( V1 ) and b = ( b1 ) (first I-1 rows) // ( V2 ) ( b2 ) // // where V1 is unit lower triangular // // w := V1**T * b1 // i__2 = i__ - 1; dcopy_(&i__2, &a[*k + 1 + i__ * a_dim1], &c__1, &t[*nb * t_dim1 + 1], &c__1); i__2 = i__ - 1; dtrmv_("Lower", "Transpose", "UNIT", &i__2, &a[*k + 1 + a_dim1], lda, &t[*nb * t_dim1 + 1], &c__1); // // w := w + V2**T * b2 // i__2 = *n - *k - i__ + 1; i__3 = i__ - 1; dgemv_("Transpose", &i__2, &i__3, &c_b5, &a[*k + i__ + a_dim1], lda, &a[*k + i__ + i__ * a_dim1], &c__1, &c_b5, &t[*nb * t_dim1 + 1], &c__1); // // w := T**T * w // i__2 = i__ - 1; dtrmv_("Upper", "Transpose", "NON-UNIT", &i__2, &t[t_offset], ldt, &t[*nb * t_dim1 + 1], &c__1); // // b2 := b2 - V2*w // i__2 = *n - *k - i__ + 1; i__3 = i__ - 1; dgemv_("NO TRANSPOSE", &i__2, &i__3, &c_b4, &a[*k + i__ + a_dim1], lda, &t[*nb * t_dim1 + 1], &c__1, &c_b5, &a[*k + i__ + i__ * a_dim1], &c__1); // // b1 := b1 - V1*w // i__2 = i__ - 1; dtrmv_("Lower", "NO TRANSPOSE", "UNIT", &i__2, &a[*k + 1 + a_dim1] , lda, &t[*nb * t_dim1 + 1], &c__1); i__2 = i__ - 1; daxpy_(&i__2, &c_b4, &t[*nb * t_dim1 + 1], &c__1, &a[*k + 1 + i__ * a_dim1], &c__1); a[*k + i__ - 1 + (i__ - 1) * a_dim1] = ei; } // // Generate the elementary reflector H(I) to annihilate // A(K+I+1:N,I) // i__2 = *n - *k - i__ + 1; // Computing MIN i__3 = *k + i__ + 1; dlarfg_(&i__2, &a[*k + i__ + i__ * a_dim1], &a[min(i__3,*n) + i__ * a_dim1], &c__1, &tau[i__]); ei = a[*k + i__ + i__ * a_dim1]; a[*k + i__ + i__ * a_dim1] = 1.; // // Compute Y(K+1:N,I) // i__2 = *n - *k; i__3 = *n - *k - i__ + 1; dgemv_("NO TRANSPOSE", &i__2, &i__3, &c_b5, &a[*k + 1 + (i__ + 1) * a_dim1], lda, &a[*k + i__ + i__ * a_dim1], &c__1, &c_b38, &y[* k + 1 + i__ * y_dim1], &c__1); i__2 = *n - *k - i__ + 1; i__3 = i__ - 1; dgemv_("Transpose", &i__2, &i__3, &c_b5, &a[*k + i__ + a_dim1], lda, & a[*k + i__ + i__ * a_dim1], &c__1, &c_b38, &t[i__ * t_dim1 + 1], &c__1); i__2 = *n - *k; i__3 = i__ - 1; dgemv_("NO TRANSPOSE", &i__2, &i__3, &c_b4, &y[*k + 1 + y_dim1], ldy, &t[i__ * t_dim1 + 1], &c__1, &c_b5, &y[*k + 1 + i__ * y_dim1], &c__1); i__2 = *n - *k; dscal_(&i__2, &tau[i__], &y[*k + 1 + i__ * y_dim1], &c__1); // // Compute T(1:I,I) // i__2 = i__ - 1; d__1 = -tau[i__]; dscal_(&i__2, &d__1, &t[i__ * t_dim1 + 1], &c__1); i__2 = i__ - 1; dtrmv_("Upper", "No Transpose", "NON-UNIT", &i__2, &t[t_offset], ldt, &t[i__ * t_dim1 + 1], &c__1); t[i__ + i__ * t_dim1] = tau[i__]; // L10: } a[*k + *nb + *nb * a_dim1] = ei; // // Compute Y(1:K,1:NB) // dlacpy_("ALL", k, nb, &a[(a_dim1 << 1) + 1], lda, &y[y_offset], ldy); dtrmm_("RIGHT", "Lower", "NO TRANSPOSE", "UNIT", k, nb, &c_b5, &a[*k + 1 + a_dim1], lda, &y[y_offset], ldy); if (*n > *k + *nb) { i__1 = *n - *k - *nb; dgemm_("NO TRANSPOSE", "NO TRANSPOSE", k, nb, &i__1, &c_b5, &a[(*nb + 2) * a_dim1 + 1], lda, &a[*k + 1 + *nb + a_dim1], lda, &c_b5, &y[y_offset], ldy); } dtrmm_("RIGHT", "Upper", "NO TRANSPOSE", "NON-UNIT", k, nb, &c_b5, &t[ t_offset], ldt, &y[y_offset], ldy); return 0; // // End of DLAHR2 // } // dlahr2_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DLALN2 solves a 1-by-1 or 2-by-2 linear system of equations of the specified form. // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DLALN2 + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DLALN2( LTRANS, NA, NW, SMIN, CA, A, LDA, D1, D2, B, // LDB, WR, WI, X, LDX, SCALE, XNORM, INFO ) // // .. Scalar Arguments .. // LOGICAL LTRANS // INTEGER INFO, LDA, LDB, LDX, NA, NW // DOUBLE PRECISION CA, D1, D2, SCALE, SMIN, WI, WR, XNORM // .. // .. Array Arguments .. // DOUBLE PRECISION A( LDA, * ), B( LDB, * ), X( LDX, * ) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> DLALN2 solves a system of the form (ca A - w D ) X = s B //> or (ca A**T - w D) X = s B with possible scaling ("s") and //> perturbation of A. (A**T means A-transpose.) //> //> A is an NA x NA real matrix, ca is a real scalar, D is an NA x NA //> real diagonal matrix, w is a real or complex value, and X and B are //> NA x 1 matrices -- real if w is real, complex if w is complex. NA //> may be 1 or 2. //> //> If w is complex, X and B are represented as NA x 2 matrices, //> the first column of each being the real part and the second //> being the imaginary part. //> //> "s" is a scaling factor (<= 1), computed by DLALN2, which is //> so chosen that X can be computed without overflow. X is further //> scaled if necessary to assure that norm(ca A - w D)*norm(X) is less //> than overflow. //> //> If both singular values of (ca A - w D) are less than SMIN, //> SMIN*identity will be used instead of (ca A - w D). If only one //> singular value is less than SMIN, one element of (ca A - w D) will be //> perturbed enough to make the smallest singular value roughly SMIN. //> If both singular values are at least SMIN, (ca A - w D) will not be //> perturbed. In any case, the perturbation will be at most some small //> multiple of max( SMIN, ulp*norm(ca A - w D) ). The singular values //> are computed by infinity-norm approximations, and thus will only be //> correct to a factor of 2 or so. //> //> Note: all input quantities are assumed to be smaller than overflow //> by a reasonable factor. (See BIGNUM.) //> \endverbatim // // Arguments: // ========== // //> \param[in] LTRANS //> \verbatim //> LTRANS is LOGICAL //> =.TRUE.: A-transpose will be used. //> =.FALSE.: A will be used (not transposed.) //> \endverbatim //> //> \param[in] NA //> \verbatim //> NA is INTEGER //> The size of the matrix A. It may (only) be 1 or 2. //> \endverbatim //> //> \param[in] NW //> \verbatim //> NW is INTEGER //> 1 if "w" is real, 2 if "w" is complex. It may only be 1 //> or 2. //> \endverbatim //> //> \param[in] SMIN //> \verbatim //> SMIN is DOUBLE PRECISION //> The desired lower bound on the singular values of A. This //> should be a safe distance away from underflow or overflow, //> say, between (underflow/machine precision) and (machine //> precision * overflow ). (See BIGNUM and ULP.) //> \endverbatim //> //> \param[in] CA //> \verbatim //> CA is DOUBLE PRECISION //> The coefficient c, which A is multiplied by. //> \endverbatim //> //> \param[in] A //> \verbatim //> A is DOUBLE PRECISION array, dimension (LDA,NA) //> The NA x NA matrix A. //> \endverbatim //> //> \param[in] LDA //> \verbatim //> LDA is INTEGER //> The leading dimension of A. It must be at least NA. //> \endverbatim //> //> \param[in] D1 //> \verbatim //> D1 is DOUBLE PRECISION //> The 1,1 element in the diagonal matrix D. //> \endverbatim //> //> \param[in] D2 //> \verbatim //> D2 is DOUBLE PRECISION //> The 2,2 element in the diagonal matrix D. Not used if NA=1. //> \endverbatim //> //> \param[in] B //> \verbatim //> B is DOUBLE PRECISION array, dimension (LDB,NW) //> The NA x NW matrix B (right-hand side). If NW=2 ("w" is //> complex), column 1 contains the real part of B and column 2 //> contains the imaginary part. //> \endverbatim //> //> \param[in] LDB //> \verbatim //> LDB is INTEGER //> The leading dimension of B. It must be at least NA. //> \endverbatim //> //> \param[in] WR //> \verbatim //> WR is DOUBLE PRECISION //> The real part of the scalar "w". //> \endverbatim //> //> \param[in] WI //> \verbatim //> WI is DOUBLE PRECISION //> The imaginary part of the scalar "w". Not used if NW=1. //> \endverbatim //> //> \param[out] X //> \verbatim //> X is DOUBLE PRECISION array, dimension (LDX,NW) //> The NA x NW matrix X (unknowns), as computed by DLALN2. //> If NW=2 ("w" is complex), on exit, column 1 will contain //> the real part of X and column 2 will contain the imaginary //> part. //> \endverbatim //> //> \param[in] LDX //> \verbatim //> LDX is INTEGER //> The leading dimension of X. It must be at least NA. //> \endverbatim //> //> \param[out] SCALE //> \verbatim //> SCALE is DOUBLE PRECISION //> The scale factor that B must be multiplied by to insure //> that overflow does not occur when computing X. Thus, //> (ca A - w D) X will be SCALE*B, not B (ignoring //> perturbations of A.) It will be at most 1. //> \endverbatim //> //> \param[out] XNORM //> \verbatim //> XNORM is DOUBLE PRECISION //> The infinity-norm of X, when X is regarded as an NA x NW //> real matrix. //> \endverbatim //> //> \param[out] INFO //> \verbatim //> INFO is INTEGER //> An error flag. It will be set to zero if no error occurs, //> a negative number if an argument is in error, or a positive //> number if ca A - w D had to be perturbed. //> The possible values are: //> = 0: No error occurred, and (ca A - w D) did not have to be //> perturbed. //> = 1: (ca A - w D) had to be perturbed to make its smallest //> (or only) singular value greater than SMIN. //> NOTE: In the interests of speed, this routine does not //> check the inputs for errors. //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date December 2016 // //> \ingroup doubleOTHERauxiliary // // ===================================================================== /* Subroutine */ int dlaln2_(int *ltrans, int *na, int *nw, double *smin, double *ca, double *a, int *lda, double *d1, double *d2, double *b, int *ldb, double *wr, double *wi, double *x, int *ldx, double *scale, double *xnorm, int *info) { /* Initialized data */ static int zswap[4] = { FALSE_,FALSE_,TRUE_,TRUE_ }; static int rswap[4] = { FALSE_,TRUE_,FALSE_,TRUE_ }; static int ipivot[16] /* was [4][4] */ = { 1,2,3,4,2,1,4,3,3,4,1,2, 4,3,2,1 }; // System generated locals int a_dim1, a_offset, b_dim1, b_offset, x_dim1, x_offset; double d__1, d__2, d__3, d__4, d__5, d__6; static double equiv_0[4], equiv_1[4]; // Local variables int j; #define ci (equiv_0) #define cr (equiv_1) double bi1, bi2, br1, br2, xi1, xi2, xr1, xr2, ci21, ci22, cr21, cr22, li21, csi, ui11, lr21, ui12, ui22; #define civ (equiv_0) double csr, ur11, ur12, ur22; #define crv (equiv_1) double bbnd, cmax, ui11r, ui12s, temp, ur11r, ur12s, u22abs; int icmax; double bnorm, cnorm, smini; extern double dlamch_(char *); extern /* Subroutine */ int dladiv_(double *, double *, double *, double * , double *, double *); double bignum, smlnum; // // -- LAPACK auxiliary routine (version 3.7.0) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // December 2016 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // //===================================================================== // // .. Parameters .. // .. // .. Local Scalars .. // .. // .. Local Arrays .. // .. // .. External Functions .. // .. // .. External Subroutines .. // .. // .. Intrinsic Functions .. // .. // .. Equivalences .. // .. // .. Data statements .. // Parameter adjustments a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; b_dim1 = *ldb; b_offset = 1 + b_dim1; b -= b_offset; x_dim1 = *ldx; x_offset = 1 + x_dim1; x -= x_offset; // Function Body // .. // .. Executable Statements .. // // Compute BIGNUM // smlnum = 2. * dlamch_("Safe minimum"); bignum = 1. / smlnum; smini = max(*smin,smlnum); // // Don't check for input errors // *info = 0; // // Standard Initializations // *scale = 1.; if (*na == 1) { // // 1 x 1 (i.e., scalar) system C X = B // if (*nw == 1) { // // Real 1x1 system. // // C = ca A - w D // csr = *ca * a[a_dim1 + 1] - *wr * *d1; cnorm = abs(csr); // // If | C | < SMINI, use C = SMINI // if (cnorm < smini) { csr = smini; cnorm = smini; *info = 1; } // // Check scaling for X = B / C // bnorm = (d__1 = b[b_dim1 + 1], abs(d__1)); if (cnorm < 1. && bnorm > 1.) { if (bnorm > bignum * cnorm) { *scale = 1. / bnorm; } } // // Compute X // x[x_dim1 + 1] = b[b_dim1 + 1] * *scale / csr; *xnorm = (d__1 = x[x_dim1 + 1], abs(d__1)); } else { // // Complex 1x1 system (w is complex) // // C = ca A - w D // csr = *ca * a[a_dim1 + 1] - *wr * *d1; csi = -(*wi) * *d1; cnorm = abs(csr) + abs(csi); // // If | C | < SMINI, use C = SMINI // if (cnorm < smini) { csr = smini; csi = 0.; cnorm = smini; *info = 1; } // // Check scaling for X = B / C // bnorm = (d__1 = b[b_dim1 + 1], abs(d__1)) + (d__2 = b[(b_dim1 << 1) + 1], abs(d__2)); if (cnorm < 1. && bnorm > 1.) { if (bnorm > bignum * cnorm) { *scale = 1. / bnorm; } } // // Compute X // d__1 = *scale * b[b_dim1 + 1]; d__2 = *scale * b[(b_dim1 << 1) + 1]; dladiv_(&d__1, &d__2, &csr, &csi, &x[x_dim1 + 1], &x[(x_dim1 << 1) + 1]); *xnorm = (d__1 = x[x_dim1 + 1], abs(d__1)) + (d__2 = x[(x_dim1 << 1) + 1], abs(d__2)); } } else { // // 2x2 System // // Compute the real part of C = ca A - w D (or ca A**T - w D ) // cr[0] = *ca * a[a_dim1 + 1] - *wr * *d1; cr[3] = *ca * a[(a_dim1 << 1) + 2] - *wr * *d2; if (*ltrans) { cr[2] = *ca * a[a_dim1 + 2]; cr[1] = *ca * a[(a_dim1 << 1) + 1]; } else { cr[1] = *ca * a[a_dim1 + 2]; cr[2] = *ca * a[(a_dim1 << 1) + 1]; } if (*nw == 1) { // // Real 2x2 system (w is real) // // Find the largest element in C // cmax = 0.; icmax = 0; for (j = 1; j <= 4; ++j) { if ((d__1 = crv[j - 1], abs(d__1)) > cmax) { cmax = (d__1 = crv[j - 1], abs(d__1)); icmax = j; } // L10: } // // If norm(C) < SMINI, use SMINI*identity. // if (cmax < smini) { // Computing MAX d__3 = (d__1 = b[b_dim1 + 1], abs(d__1)), d__4 = (d__2 = b[ b_dim1 + 2], abs(d__2)); bnorm = max(d__3,d__4); if (smini < 1. && bnorm > 1.) { if (bnorm > bignum * smini) { *scale = 1. / bnorm; } } temp = *scale / smini; x[x_dim1 + 1] = temp * b[b_dim1 + 1]; x[x_dim1 + 2] = temp * b[b_dim1 + 2]; *xnorm = temp * bnorm; *info = 1; return 0; } // // Gaussian elimination with complete pivoting. // ur11 = crv[icmax - 1]; cr21 = crv[ipivot[(icmax << 2) - 3] - 1]; ur12 = crv[ipivot[(icmax << 2) - 2] - 1]; cr22 = crv[ipivot[(icmax << 2) - 1] - 1]; ur11r = 1. / ur11; lr21 = ur11r * cr21; ur22 = cr22 - ur12 * lr21; // // If smaller pivot < SMINI, use SMINI // if (abs(ur22) < smini) { ur22 = smini; *info = 1; } if (rswap[icmax - 1]) { br1 = b[b_dim1 + 2]; br2 = b[b_dim1 + 1]; } else { br1 = b[b_dim1 + 1]; br2 = b[b_dim1 + 2]; } br2 -= lr21 * br1; // Computing MAX d__2 = (d__1 = br1 * (ur22 * ur11r), abs(d__1)), d__3 = abs(br2); bbnd = max(d__2,d__3); if (bbnd > 1. && abs(ur22) < 1.) { if (bbnd >= bignum * abs(ur22)) { *scale = 1. / bbnd; } } xr2 = br2 * *scale / ur22; xr1 = *scale * br1 * ur11r - xr2 * (ur11r * ur12); if (zswap[icmax - 1]) { x[x_dim1 + 1] = xr2; x[x_dim1 + 2] = xr1; } else { x[x_dim1 + 1] = xr1; x[x_dim1 + 2] = xr2; } // Computing MAX d__1 = abs(xr1), d__2 = abs(xr2); *xnorm = max(d__1,d__2); // // Further scaling if norm(A) norm(X) > overflow // if (*xnorm > 1. && cmax > 1.) { if (*xnorm > bignum / cmax) { temp = cmax / bignum; x[x_dim1 + 1] = temp * x[x_dim1 + 1]; x[x_dim1 + 2] = temp * x[x_dim1 + 2]; *xnorm = temp * *xnorm; *scale = temp * *scale; } } } else { // // Complex 2x2 system (w is complex) // // Find the largest element in C // ci[0] = -(*wi) * *d1; ci[1] = 0.; ci[2] = 0.; ci[3] = -(*wi) * *d2; cmax = 0.; icmax = 0; for (j = 1; j <= 4; ++j) { if ((d__1 = crv[j - 1], abs(d__1)) + (d__2 = civ[j - 1], abs( d__2)) > cmax) { cmax = (d__1 = crv[j - 1], abs(d__1)) + (d__2 = civ[j - 1] , abs(d__2)); icmax = j; } // L20: } // // If norm(C) < SMINI, use SMINI*identity. // if (cmax < smini) { // Computing MAX d__5 = (d__1 = b[b_dim1 + 1], abs(d__1)) + (d__2 = b[(b_dim1 << 1) + 1], abs(d__2)), d__6 = (d__3 = b[b_dim1 + 2], abs(d__3)) + (d__4 = b[(b_dim1 << 1) + 2], abs(d__4)); bnorm = max(d__5,d__6); if (smini < 1. && bnorm > 1.) { if (bnorm > bignum * smini) { *scale = 1. / bnorm; } } temp = *scale / smini; x[x_dim1 + 1] = temp * b[b_dim1 + 1]; x[x_dim1 + 2] = temp * b[b_dim1 + 2]; x[(x_dim1 << 1) + 1] = temp * b[(b_dim1 << 1) + 1]; x[(x_dim1 << 1) + 2] = temp * b[(b_dim1 << 1) + 2]; *xnorm = temp * bnorm; *info = 1; return 0; } // // Gaussian elimination with complete pivoting. // ur11 = crv[icmax - 1]; ui11 = civ[icmax - 1]; cr21 = crv[ipivot[(icmax << 2) - 3] - 1]; ci21 = civ[ipivot[(icmax << 2) - 3] - 1]; ur12 = crv[ipivot[(icmax << 2) - 2] - 1]; ui12 = civ[ipivot[(icmax << 2) - 2] - 1]; cr22 = crv[ipivot[(icmax << 2) - 1] - 1]; ci22 = civ[ipivot[(icmax << 2) - 1] - 1]; if (icmax == 1 || icmax == 4) { // // Code when off-diagonals of pivoted C are real // if (abs(ur11) > abs(ui11)) { temp = ui11 / ur11; // Computing 2nd power d__1 = temp; ur11r = 1. / (ur11 * (d__1 * d__1 + 1.)); ui11r = -temp * ur11r; } else { temp = ur11 / ui11; // Computing 2nd power d__1 = temp; ui11r = -1. / (ui11 * (d__1 * d__1 + 1.)); ur11r = -temp * ui11r; } lr21 = cr21 * ur11r; li21 = cr21 * ui11r; ur12s = ur12 * ur11r; ui12s = ur12 * ui11r; ur22 = cr22 - ur12 * lr21; ui22 = ci22 - ur12 * li21; } else { // // Code when diagonals of pivoted C are real // ur11r = 1. / ur11; ui11r = 0.; lr21 = cr21 * ur11r; li21 = ci21 * ur11r; ur12s = ur12 * ur11r; ui12s = ui12 * ur11r; ur22 = cr22 - ur12 * lr21 + ui12 * li21; ui22 = -ur12 * li21 - ui12 * lr21; } u22abs = abs(ur22) + abs(ui22); // // If smaller pivot < SMINI, use SMINI // if (u22abs < smini) { ur22 = smini; ui22 = 0.; *info = 1; } if (rswap[icmax - 1]) { br2 = b[b_dim1 + 1]; br1 = b[b_dim1 + 2]; bi2 = b[(b_dim1 << 1) + 1]; bi1 = b[(b_dim1 << 1) + 2]; } else { br1 = b[b_dim1 + 1]; br2 = b[b_dim1 + 2]; bi1 = b[(b_dim1 << 1) + 1]; bi2 = b[(b_dim1 << 1) + 2]; } br2 = br2 - lr21 * br1 + li21 * bi1; bi2 = bi2 - li21 * br1 - lr21 * bi1; // Computing MAX d__1 = (abs(br1) + abs(bi1)) * (u22abs * (abs(ur11r) + abs(ui11r)) ), d__2 = abs(br2) + abs(bi2); bbnd = max(d__1,d__2); if (bbnd > 1. && u22abs < 1.) { if (bbnd >= bignum * u22abs) { *scale = 1. / bbnd; br1 = *scale * br1; bi1 = *scale * bi1; br2 = *scale * br2; bi2 = *scale * bi2; } } dladiv_(&br2, &bi2, &ur22, &ui22, &xr2, &xi2); xr1 = ur11r * br1 - ui11r * bi1 - ur12s * xr2 + ui12s * xi2; xi1 = ui11r * br1 + ur11r * bi1 - ui12s * xr2 - ur12s * xi2; if (zswap[icmax - 1]) { x[x_dim1 + 1] = xr2; x[x_dim1 + 2] = xr1; x[(x_dim1 << 1) + 1] = xi2; x[(x_dim1 << 1) + 2] = xi1; } else { x[x_dim1 + 1] = xr1; x[x_dim1 + 2] = xr2; x[(x_dim1 << 1) + 1] = xi1; x[(x_dim1 << 1) + 2] = xi2; } // Computing MAX d__1 = abs(xr1) + abs(xi1), d__2 = abs(xr2) + abs(xi2); *xnorm = max(d__1,d__2); // // Further scaling if norm(A) norm(X) > overflow // if (*xnorm > 1. && cmax > 1.) { if (*xnorm > bignum / cmax) { temp = cmax / bignum; x[x_dim1 + 1] = temp * x[x_dim1 + 1]; x[x_dim1 + 2] = temp * x[x_dim1 + 2]; x[(x_dim1 << 1) + 1] = temp * x[(x_dim1 << 1) + 1]; x[(x_dim1 << 1) + 2] = temp * x[(x_dim1 << 1) + 2]; *xnorm = temp * *xnorm; *scale = temp * *scale; } } } } return 0; // // End of DLALN2 // } // dlaln2_ #undef crv #undef civ #undef cr #undef ci /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DLANV2 computes the Schur factorization of a real 2-by-2 nonsymmetric matrix in standard form. // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DLANV2 + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DLANV2( A, B, C, D, RT1R, RT1I, RT2R, RT2I, CS, SN ) // // .. Scalar Arguments .. // DOUBLE PRECISION A, B, C, CS, D, RT1I, RT1R, RT2I, RT2R, SN // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> DLANV2 computes the Schur factorization of a real 2-by-2 nonsymmetric //> matrix in standard form: //> //> [ A B ] = [ CS -SN ] [ AA BB ] [ CS SN ] //> [ C D ] [ SN CS ] [ CC DD ] [-SN CS ] //> //> where either //> 1) CC = 0 so that AA and DD are real eigenvalues of the matrix, or //> 2) AA = DD and BB*CC < 0, so that AA + or - sqrt(BB*CC) are complex //> conjugate eigenvalues. //> \endverbatim // // Arguments: // ========== // //> \param[in,out] A //> \verbatim //> A is DOUBLE PRECISION //> \endverbatim //> //> \param[in,out] B //> \verbatim //> B is DOUBLE PRECISION //> \endverbatim //> //> \param[in,out] C //> \verbatim //> C is DOUBLE PRECISION //> \endverbatim //> //> \param[in,out] D //> \verbatim //> D is DOUBLE PRECISION //> On entry, the elements of the input matrix. //> On exit, they are overwritten by the elements of the //> standardised Schur form. //> \endverbatim //> //> \param[out] RT1R //> \verbatim //> RT1R is DOUBLE PRECISION //> \endverbatim //> //> \param[out] RT1I //> \verbatim //> RT1I is DOUBLE PRECISION //> \endverbatim //> //> \param[out] RT2R //> \verbatim //> RT2R is DOUBLE PRECISION //> \endverbatim //> //> \param[out] RT2I //> \verbatim //> RT2I is DOUBLE PRECISION //> The real and imaginary parts of the eigenvalues. If the //> eigenvalues are a complex conjugate pair, RT1I > 0. //> \endverbatim //> //> \param[out] CS //> \verbatim //> CS is DOUBLE PRECISION //> \endverbatim //> //> \param[out] SN //> \verbatim //> SN is DOUBLE PRECISION //> Parameters of the rotation matrix. //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date December 2016 // //> \ingroup doubleOTHERauxiliary // //> \par Further Details: // ===================== //> //> \verbatim //> //> Modified by V. Sima, Research Institute for Informatics, Bucharest, //> Romania, to reduce the risk of cancellation errors, //> when computing real eigenvalues, and to ensure, if possible, that //> abs(RT1R) >= abs(RT2R). //> \endverbatim //> // ===================================================================== /* Subroutine */ int dlanv2_(double *a, double *b, double *c__, double *d__, double *rt1r, double *rt1i, double *rt2r, double *rt2i, double *cs, double *sn) { // Table of constant values double c_b3 = 1.; // System generated locals double d__1, d__2; // Local variables double p, z__, aa, bb, cc, dd, cs1, sn1, sab, sac, eps, tau, temp, scale, bcmax, bcmis, sigma; extern double dlapy2_(double *, double *), dlamch_(char *); // // -- LAPACK auxiliary routine (version 3.7.0) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // December 2016 // // .. Scalar Arguments .. // .. // // ===================================================================== // // .. Parameters .. // .. // .. Local Scalars .. // .. // .. External Functions .. // .. // .. Intrinsic Functions .. // .. // .. Executable Statements .. // eps = dlamch_("P"); if (*c__ == 0.) { *cs = 1.; *sn = 0.; } else if (*b == 0.) { // // Swap rows and columns // *cs = 0.; *sn = 1.; temp = *d__; *d__ = *a; *a = temp; *b = -(*c__); *c__ = 0.; } else if (*a - *d__ == 0. && d_sign(&c_b3, b) != d_sign(&c_b3, c__)) { *cs = 1.; *sn = 0.; } else { temp = *a - *d__; p = temp * .5; // Computing MAX d__1 = abs(*b), d__2 = abs(*c__); bcmax = max(d__1,d__2); // Computing MIN d__1 = abs(*b), d__2 = abs(*c__); bcmis = min(d__1,d__2) * d_sign(&c_b3, b) * d_sign(&c_b3, c__); // Computing MAX d__1 = abs(p); scale = max(d__1,bcmax); z__ = p / scale * p + bcmax / scale * bcmis; // // If Z is of the order of the machine accuracy, postpone the // decision on the nature of eigenvalues // if (z__ >= eps * 4.) { // // Real eigenvalues. Compute A and D. // d__1 = sqrt(scale) * sqrt(z__); z__ = p + d_sign(&d__1, &p); *a = *d__ + z__; *d__ -= bcmax / z__ * bcmis; // // Compute B and the rotation matrix // tau = dlapy2_(c__, &z__); *cs = z__ / tau; *sn = *c__ / tau; *b -= *c__; *c__ = 0.; } else { // // Complex eigenvalues, or real (almost) equal eigenvalues. // Make diagonal elements equal. // sigma = *b + *c__; tau = dlapy2_(&sigma, &temp); *cs = sqrt((abs(sigma) / tau + 1.) * .5); *sn = -(p / (tau * *cs)) * d_sign(&c_b3, &sigma); // // Compute [ AA BB ] = [ A B ] [ CS -SN ] // [ CC DD ] [ C D ] [ SN CS ] // aa = *a * *cs + *b * *sn; bb = -(*a) * *sn + *b * *cs; cc = *c__ * *cs + *d__ * *sn; dd = -(*c__) * *sn + *d__ * *cs; // // Compute [ A B ] = [ CS SN ] [ AA BB ] // [ C D ] [-SN CS ] [ CC DD ] // *a = aa * *cs + cc * *sn; *b = bb * *cs + dd * *sn; *c__ = -aa * *sn + cc * *cs; *d__ = -bb * *sn + dd * *cs; temp = (*a + *d__) * .5; *a = temp; *d__ = temp; if (*c__ != 0.) { if (*b != 0.) { if (d_sign(&c_b3, b) == d_sign(&c_b3, c__)) { // // Real eigenvalues: reduce to upper triangular form // sab = sqrt((abs(*b))); sac = sqrt((abs(*c__))); d__1 = sab * sac; p = d_sign(&d__1, c__); tau = 1. / sqrt((d__1 = *b + *c__, abs(d__1))); *a = temp + p; *d__ = temp - p; *b -= *c__; *c__ = 0.; cs1 = sab * tau; sn1 = sac * tau; temp = *cs * cs1 - *sn * sn1; *sn = *cs * sn1 + *sn * cs1; *cs = temp; } } else { *b = -(*c__); *c__ = 0.; temp = *cs; *cs = -(*sn); *sn = temp; } } } } // // Store eigenvalues in (RT1R,RT1I) and (RT2R,RT2I). // *rt1r = *a; *rt2r = *d__; if (*c__ == 0.) { *rt1i = 0.; *rt2i = 0.; } else { *rt1i = sqrt((abs(*b))) * sqrt((abs(*c__))); *rt2i = -(*rt1i); } return 0; // // End of DLANV2 // } // dlanv2_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DLAQR0 computes the eigenvalues of a Hessenberg matrix, and optionally the matrices from the Schur decomposition. // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DLAQR0 + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DLAQR0( WANTT, WANTZ, N, ILO, IHI, H, LDH, WR, WI, // ILOZ, IHIZ, Z, LDZ, WORK, LWORK, INFO ) // // .. Scalar Arguments .. // INTEGER IHI, IHIZ, ILO, ILOZ, INFO, LDH, LDZ, LWORK, N // LOGICAL WANTT, WANTZ // .. // .. Array Arguments .. // DOUBLE PRECISION H( LDH, * ), WI( * ), WORK( * ), WR( * ), // $ Z( LDZ, * ) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> DLAQR0 computes the eigenvalues of a Hessenberg matrix H //> and, optionally, the matrices T and Z from the Schur decomposition //> H = Z T Z**T, where T is an upper quasi-triangular matrix (the //> Schur form), and Z is the orthogonal matrix of Schur vectors. //> //> Optionally Z may be postmultiplied into an input orthogonal //> matrix Q so that this routine can give the Schur factorization //> of a matrix A which has been reduced to the Hessenberg form H //> by the orthogonal matrix Q: A = Q*H*Q**T = (QZ)*T*(QZ)**T. //> \endverbatim // // Arguments: // ========== // //> \param[in] WANTT //> \verbatim //> WANTT is LOGICAL //> = .TRUE. : the full Schur form T is required; //> = .FALSE.: only eigenvalues are required. //> \endverbatim //> //> \param[in] WANTZ //> \verbatim //> WANTZ is LOGICAL //> = .TRUE. : the matrix of Schur vectors Z is required; //> = .FALSE.: Schur vectors are not required. //> \endverbatim //> //> \param[in] N //> \verbatim //> N is INTEGER //> The order of the matrix H. N >= 0. //> \endverbatim //> //> \param[in] ILO //> \verbatim //> ILO is INTEGER //> \endverbatim //> //> \param[in] IHI //> \verbatim //> IHI is INTEGER //> It is assumed that H is already upper triangular in rows //> and columns 1:ILO-1 and IHI+1:N and, if ILO > 1, //> H(ILO,ILO-1) is zero. ILO and IHI are normally set by a //> previous call to DGEBAL, and then passed to DGEHRD when the //> matrix output by DGEBAL is reduced to Hessenberg form. //> Otherwise, ILO and IHI should be set to 1 and N, //> respectively. If N > 0, then 1 <= ILO <= IHI <= N. //> If N = 0, then ILO = 1 and IHI = 0. //> \endverbatim //> //> \param[in,out] H //> \verbatim //> H is DOUBLE PRECISION array, dimension (LDH,N) //> On entry, the upper Hessenberg matrix H. //> On exit, if INFO = 0 and WANTT is .TRUE., then H contains //> the upper quasi-triangular matrix T from the Schur //> decomposition (the Schur form); 2-by-2 diagonal blocks //> (corresponding to complex conjugate pairs of eigenvalues) //> are returned in standard form, with H(i,i) = H(i+1,i+1) //> and H(i+1,i)*H(i,i+1) < 0. If INFO = 0 and WANTT is //> .FALSE., then the contents of H are unspecified on exit. //> (The output value of H when INFO > 0 is given under the //> description of INFO below.) //> //> This subroutine may explicitly set H(i,j) = 0 for i > j and //> j = 1, 2, ... ILO-1 or j = IHI+1, IHI+2, ... N. //> \endverbatim //> //> \param[in] LDH //> \verbatim //> LDH is INTEGER //> The leading dimension of the array H. LDH >= max(1,N). //> \endverbatim //> //> \param[out] WR //> \verbatim //> WR is DOUBLE PRECISION array, dimension (IHI) //> \endverbatim //> //> \param[out] WI //> \verbatim //> WI is DOUBLE PRECISION array, dimension (IHI) //> The real and imaginary parts, respectively, of the computed //> eigenvalues of H(ILO:IHI,ILO:IHI) are stored in WR(ILO:IHI) //> and WI(ILO:IHI). If two eigenvalues are computed as a //> complex conjugate pair, they are stored in consecutive //> elements of WR and WI, say the i-th and (i+1)th, with //> WI(i) > 0 and WI(i+1) < 0. If WANTT is .TRUE., then //> the eigenvalues are stored in the same order as on the //> diagonal of the Schur form returned in H, with //> WR(i) = H(i,i) and, if H(i:i+1,i:i+1) is a 2-by-2 diagonal //> block, WI(i) = sqrt(-H(i+1,i)*H(i,i+1)) and //> WI(i+1) = -WI(i). //> \endverbatim //> //> \param[in] ILOZ //> \verbatim //> ILOZ is INTEGER //> \endverbatim //> //> \param[in] IHIZ //> \verbatim //> IHIZ is INTEGER //> Specify the rows of Z to which transformations must be //> applied if WANTZ is .TRUE.. //> 1 <= ILOZ <= ILO; IHI <= IHIZ <= N. //> \endverbatim //> //> \param[in,out] Z //> \verbatim //> Z is DOUBLE PRECISION array, dimension (LDZ,IHI) //> If WANTZ is .FALSE., then Z is not referenced. //> If WANTZ is .TRUE., then Z(ILO:IHI,ILOZ:IHIZ) is //> replaced by Z(ILO:IHI,ILOZ:IHIZ)*U where U is the //> orthogonal Schur factor of H(ILO:IHI,ILO:IHI). //> (The output value of Z when INFO > 0 is given under //> the description of INFO below.) //> \endverbatim //> //> \param[in] LDZ //> \verbatim //> LDZ is INTEGER //> The leading dimension of the array Z. if WANTZ is .TRUE. //> then LDZ >= MAX(1,IHIZ). Otherwise, LDZ >= 1. //> \endverbatim //> //> \param[out] WORK //> \verbatim //> WORK is DOUBLE PRECISION array, dimension LWORK //> On exit, if LWORK = -1, WORK(1) returns an estimate of //> the optimal value for LWORK. //> \endverbatim //> //> \param[in] LWORK //> \verbatim //> LWORK is INTEGER //> The dimension of the array WORK. LWORK >= max(1,N) //> is sufficient, but LWORK typically as large as 6*N may //> be required for optimal performance. A workspace query //> to determine the optimal workspace size is recommended. //> //> If LWORK = -1, then DLAQR0 does a workspace query. //> In this case, DLAQR0 checks the input parameters and //> estimates the optimal workspace size for the given //> values of N, ILO and IHI. The estimate is returned //> in WORK(1). No error message related to LWORK is //> issued by XERBLA. Neither H nor Z are accessed. //> \endverbatim //> //> \param[out] INFO //> \verbatim //> INFO is INTEGER //> = 0: successful exit //> > 0: if INFO = i, DLAQR0 failed to compute all of //> the eigenvalues. Elements 1:ilo-1 and i+1:n of WR //> and WI contain those eigenvalues which have been //> successfully computed. (Failures are rare.) //> //> If INFO > 0 and WANT is .FALSE., then on exit, //> the remaining unconverged eigenvalues are the eigen- //> values of the upper Hessenberg matrix rows and //> columns ILO through INFO of the final, output //> value of H. //> //> If INFO > 0 and WANTT is .TRUE., then on exit //> //> (*) (initial value of H)*U = U*(final value of H) //> //> where U is an orthogonal matrix. The final //> value of H is upper Hessenberg and quasi-triangular //> in rows and columns INFO+1 through IHI. //> //> If INFO > 0 and WANTZ is .TRUE., then on exit //> //> (final value of Z(ILO:IHI,ILOZ:IHIZ) //> = (initial value of Z(ILO:IHI,ILOZ:IHIZ)*U //> //> where U is the orthogonal matrix in (*) (regard- //> less of the value of WANTT.) //> //> If INFO > 0 and WANTZ is .FALSE., then Z is not //> accessed. //> \endverbatim // //> \par Contributors: // ================== //> //> Karen Braman and Ralph Byers, Department of Mathematics, //> University of Kansas, USA // //> \par References: // ================ //> //> K. Braman, R. Byers and R. Mathias, The Multi-Shift QR //> Algorithm Part I: Maintaining Well Focused Shifts, and Level 3 //> Performance, SIAM Journal of Matrix Analysis, volume 23, pages //> 929--947, 2002. //> \n //> K. Braman, R. Byers and R. Mathias, The Multi-Shift QR //> Algorithm Part II: Aggressive Early Deflation, SIAM Journal //> of Matrix Analysis, volume 23, pages 948--973, 2002. // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date December 2016 // //> \ingroup doubleOTHERauxiliary // // ===================================================================== /* Subroutine */ int dlaqr0_(int *wantt, int *wantz, int *n, int *ilo, int * ihi, double *h__, int *ldh, double *wr, double *wi, int *iloz, int * ihiz, double *z__, int *ldz, double *work, int *lwork, int *info) { // Table of constant values int c__13 = 13; int c__15 = 15; int c_n1 = -1; int c__12 = 12; int c__14 = 14; int c__16 = 16; int c_false = FALSE_; int c__1 = 1; int c__3 = 3; // System generated locals int h_dim1, h_offset, z_dim1, z_offset, i__1, i__2, i__3, i__4, i__5; double d__1, d__2, d__3, d__4; // Local variables int i__, k; double aa, bb, cc, dd; int ld; double cs; int nh, it, ks, kt; double sn; int ku, kv, ls, ns; double ss; int nw, inf, kdu, nho, nve, kwh, nsr, nwr, kwv, ndec, ndfl, kbot, nmin; double swap; int ktop; double zdum[1] /* was [1][1] */; int kacc22, itmax, nsmax, nwmax, kwtop; extern /* Subroutine */ int dlanv2_(double *, double *, double *, double * , double *, double *, double *, double *, double *, double *), dlaqr3_(int *, int *, int *, int *, int *, int *, double *, int *, int *, int *, double *, int *, int *, int *, double *, double *, double *, int *, int *, double *, int *, int *, double *, int *, double *, int *), dlaqr4_(int *, int *, int *, int *, int *, double *, int *, double *, double *, int *, int *, double *, int * , double *, int *, int *), dlaqr5_(int *, int *, int *, int *, int *, int *, int *, double *, double *, double *, int *, int *, int *, double *, int *, double *, int *, double *, int *, int *, double *, int *, int *, double *, int *); int nibble; extern /* Subroutine */ int dlahqr_(int *, int *, int *, int *, int *, double *, int *, double *, double *, int *, int *, double *, int * , int *), dlacpy_(char *, int *, int *, double *, int *, double *, int *); extern int ilaenv_(int *, char *, char *, int *, int *, int *, int *); char jbcmpz[2+1]={'\0'}; int nwupbd; int sorted; int lwkopt; // // -- LAPACK auxiliary routine (version 3.7.0) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // December 2016 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // // ================================================================ // // .. Parameters .. // // ==== Matrices of order NTINY or smaller must be processed by // . DLAHQR because of insufficient subdiagonal scratch space. // . (This is a hard limit.) ==== // // ==== Exceptional deflation windows: try to cure rare // . slow convergence by varying the size of the // . deflation window after KEXNW iterations. ==== // // ==== Exceptional shifts: try to cure rare slow convergence // . with ad-hoc exceptional shifts every KEXSH iterations. // . ==== // // ==== The constants WILK1 and WILK2 are used to form the // . exceptional shifts. ==== // .. // .. Local Scalars .. // .. // .. External Functions .. // .. // .. Local Arrays .. // .. // .. External Subroutines .. // .. // .. Intrinsic Functions .. // .. // .. Executable Statements .. // Parameter adjustments h_dim1 = *ldh; h_offset = 1 + h_dim1; h__ -= h_offset; --wr; --wi; z_dim1 = *ldz; z_offset = 1 + z_dim1; z__ -= z_offset; --work; // Function Body *info = 0; // // ==== Quick return for N = 0: nothing to do. ==== // if (*n == 0) { work[1] = 1.; return 0; } if (*n <= 11) { // // ==== Tiny matrices must use DLAHQR. ==== // lwkopt = 1; if (*lwork != -1) { dlahqr_(wantt, wantz, n, ilo, ihi, &h__[h_offset], ldh, &wr[1], & wi[1], iloz, ihiz, &z__[z_offset], ldz, info); } } else { // // ==== Use small bulge multi-shift QR with aggressive early // . deflation on larger-than-tiny matrices. ==== // // ==== Hope for the best. ==== // *info = 0; // // ==== Set up job flags for ILAENV. ==== // if (*wantt) { *(unsigned char *)jbcmpz = 'S'; } else { *(unsigned char *)jbcmpz = 'E'; } if (*wantz) { *(unsigned char *)&jbcmpz[1] = 'V'; } else { *(unsigned char *)&jbcmpz[1] = 'N'; } // // ==== NWR = recommended deflation window size. At this // . point, N .GT. NTINY = 11, so there is enough // . subdiagonal workspace for NWR.GE.2 as required. // . (In fact, there is enough subdiagonal space for // . NWR.GE.3.) ==== // nwr = ilaenv_(&c__13, "DLAQR0", jbcmpz, n, ilo, ihi, lwork); nwr = max(2,nwr); // Computing MIN i__1 = *ihi - *ilo + 1, i__2 = (*n - 1) / 3, i__1 = min(i__1,i__2); nwr = min(i__1,nwr); // // ==== NSR = recommended number of simultaneous shifts. // . At this point N .GT. NTINY = 11, so there is at // . enough subdiagonal workspace for NSR to be even // . and greater than or equal to two as required. ==== // nsr = ilaenv_(&c__15, "DLAQR0", jbcmpz, n, ilo, ihi, lwork); // Computing MIN i__1 = nsr, i__2 = (*n + 6) / 9, i__1 = min(i__1,i__2), i__2 = *ihi - *ilo; nsr = min(i__1,i__2); // Computing MAX i__1 = 2, i__2 = nsr - nsr % 2; nsr = max(i__1,i__2); // // ==== Estimate optimal workspace ==== // // ==== Workspace query call to DLAQR3 ==== // i__1 = nwr + 1; dlaqr3_(wantt, wantz, n, ilo, ihi, &i__1, &h__[h_offset], ldh, iloz, ihiz, &z__[z_offset], ldz, &ls, &ld, &wr[1], &wi[1], &h__[ h_offset], ldh, n, &h__[h_offset], ldh, n, &h__[h_offset], ldh, &work[1], &c_n1); // // ==== Optimal workspace = MAX(DLAQR5, DLAQR3) ==== // // Computing MAX i__1 = nsr * 3 / 2, i__2 = (int) work[1]; lwkopt = max(i__1,i__2); // // ==== Quick return in case of workspace query. ==== // if (*lwork == -1) { work[1] = (double) lwkopt; return 0; } // // ==== DLAHQR/DLAQR0 crossover point ==== // nmin = ilaenv_(&c__12, "DLAQR0", jbcmpz, n, ilo, ihi, lwork); nmin = max(11,nmin); // // ==== Nibble crossover point ==== // nibble = ilaenv_(&c__14, "DLAQR0", jbcmpz, n, ilo, ihi, lwork); nibble = max(0,nibble); // // ==== Accumulate reflections during ttswp? Use block // . 2-by-2 structure during matrix-matrix multiply? ==== // kacc22 = ilaenv_(&c__16, "DLAQR0", jbcmpz, n, ilo, ihi, lwork); kacc22 = max(0,kacc22); kacc22 = min(2,kacc22); // // ==== NWMAX = the largest possible deflation window for // . which there is sufficient workspace. ==== // // Computing MIN i__1 = (*n - 1) / 3, i__2 = *lwork / 2; nwmax = min(i__1,i__2); nw = nwmax; // // ==== NSMAX = the Largest number of simultaneous shifts // . for which there is sufficient workspace. ==== // // Computing MIN i__1 = (*n + 6) / 9, i__2 = (*lwork << 1) / 3; nsmax = min(i__1,i__2); nsmax -= nsmax % 2; // // ==== NDFL: an iteration count restarted at deflation. ==== // ndfl = 1; // // ==== ITMAX = iteration limit ==== // // Computing MAX i__1 = 10, i__2 = *ihi - *ilo + 1; itmax = max(i__1,i__2) * 30; // // ==== Last row and column in the active block ==== // kbot = *ihi; // // ==== Main Loop ==== // i__1 = itmax; for (it = 1; it <= i__1; ++it) { // // ==== Done when KBOT falls below ILO ==== // if (kbot < *ilo) { goto L90; } // // ==== Locate active block ==== // i__2 = *ilo + 1; for (k = kbot; k >= i__2; --k) { if (h__[k + (k - 1) * h_dim1] == 0.) { goto L20; } // L10: } k = *ilo; L20: ktop = k; // // ==== Select deflation window size: // . Typical Case: // . If possible and advisable, nibble the entire // . active block. If not, use size MIN(NWR,NWMAX) // . or MIN(NWR+1,NWMAX) depending upon which has // . the smaller corresponding subdiagonal entry // . (a heuristic). // . // . Exceptional Case: // . If there have been no deflations in KEXNW or // . more iterations, then vary the deflation window // . size. At first, because, larger windows are, // . in general, more powerful than smaller ones, // . rapidly increase the window to the maximum possible. // . Then, gradually reduce the window size. ==== // nh = kbot - ktop + 1; nwupbd = min(nh,nwmax); if (ndfl < 5) { nw = min(nwupbd,nwr); } else { // Computing MIN i__2 = nwupbd, i__3 = nw << 1; nw = min(i__2,i__3); } if (nw < nwmax) { if (nw >= nh - 1) { nw = nh; } else { kwtop = kbot - nw + 1; if ((d__1 = h__[kwtop + (kwtop - 1) * h_dim1], abs(d__1)) > (d__2 = h__[kwtop - 1 + (kwtop - 2) * h_dim1], abs(d__2))) { ++nw; } } } if (ndfl < 5) { ndec = -1; } else if (ndec >= 0 || nw >= nwupbd) { ++ndec; if (nw - ndec < 2) { ndec = 0; } nw -= ndec; } // // ==== Aggressive early deflation: // . split workspace under the subdiagonal into // . - an nw-by-nw work array V in the lower // . left-hand-corner, // . - an NW-by-at-least-NW-but-more-is-better // . (NW-by-NHO) horizontal work array along // . the bottom edge, // . - an at-least-NW-but-more-is-better (NHV-by-NW) // . vertical work array along the left-hand-edge. // . ==== // kv = *n - nw + 1; kt = nw + 1; nho = *n - nw - 1 - kt + 1; kwv = nw + 2; nve = *n - nw - kwv + 1; // // ==== Aggressive early deflation ==== // dlaqr3_(wantt, wantz, n, &ktop, &kbot, &nw, &h__[h_offset], ldh, iloz, ihiz, &z__[z_offset], ldz, &ls, &ld, &wr[1], &wi[1], &h__[kv + h_dim1], ldh, &nho, &h__[kv + kt * h_dim1], ldh, &nve, &h__[kwv + h_dim1], ldh, &work[1], lwork); // // ==== Adjust KBOT accounting for new deflations. ==== // kbot -= ld; // // ==== KS points to the shifts. ==== // ks = kbot - ls + 1; // // ==== Skip an expensive QR sweep if there is a (partly // . heuristic) reason to expect that many eigenvalues // . will deflate without it. Here, the QR sweep is // . skipped if many eigenvalues have just been deflated // . or if the remaining active block is small. // if (ld == 0 || ld * 100 <= nw * nibble && kbot - ktop + 1 > min( nmin,nwmax)) { // // ==== NS = nominal number of simultaneous shifts. // . This may be lowered (slightly) if DLAQR3 // . did not provide that many shifts. ==== // // Computing MIN // Computing MAX i__4 = 2, i__5 = kbot - ktop; i__2 = min(nsmax,nsr), i__3 = max(i__4,i__5); ns = min(i__2,i__3); ns -= ns % 2; // // ==== If there have been no deflations // . in a multiple of KEXSH iterations, // . then try exceptional shifts. // . Otherwise use shifts provided by // . DLAQR3 above or from the eigenvalues // . of a trailing principal submatrix. ==== // if (ndfl % 6 == 0) { ks = kbot - ns + 1; // Computing MAX i__3 = ks + 1, i__4 = ktop + 2; i__2 = max(i__3,i__4); for (i__ = kbot; i__ >= i__2; i__ += -2) { ss = (d__1 = h__[i__ + (i__ - 1) * h_dim1], abs(d__1)) + (d__2 = h__[i__ - 1 + (i__ - 2) * h_dim1], abs(d__2)); aa = ss * .75 + h__[i__ + i__ * h_dim1]; bb = ss; cc = ss * -.4375; dd = aa; dlanv2_(&aa, &bb, &cc, &dd, &wr[i__ - 1], &wi[i__ - 1] , &wr[i__], &wi[i__], &cs, &sn); // L30: } if (ks == ktop) { wr[ks + 1] = h__[ks + 1 + (ks + 1) * h_dim1]; wi[ks + 1] = 0.; wr[ks] = wr[ks + 1]; wi[ks] = wi[ks + 1]; } } else { // // ==== Got NS/2 or fewer shifts? Use DLAQR4 or // . DLAHQR on a trailing principal submatrix to // . get more. (Since NS.LE.NSMAX.LE.(N+6)/9, // . there is enough space below the subdiagonal // . to fit an NS-by-NS scratch array.) ==== // if (kbot - ks + 1 <= ns / 2) { ks = kbot - ns + 1; kt = *n - ns + 1; dlacpy_("A", &ns, &ns, &h__[ks + ks * h_dim1], ldh, & h__[kt + h_dim1], ldh); if (ns > nmin) { dlaqr4_(&c_false, &c_false, &ns, &c__1, &ns, &h__[ kt + h_dim1], ldh, &wr[ks], &wi[ks], & c__1, &c__1, zdum, &c__1, &work[1], lwork, &inf); } else { dlahqr_(&c_false, &c_false, &ns, &c__1, &ns, &h__[ kt + h_dim1], ldh, &wr[ks], &wi[ks], & c__1, &c__1, zdum, &c__1, &inf); } ks += inf; // // ==== In case of a rare QR failure use // . eigenvalues of the trailing 2-by-2 // . principal submatrix. ==== // if (ks >= kbot) { aa = h__[kbot - 1 + (kbot - 1) * h_dim1]; cc = h__[kbot + (kbot - 1) * h_dim1]; bb = h__[kbot - 1 + kbot * h_dim1]; dd = h__[kbot + kbot * h_dim1]; dlanv2_(&aa, &bb, &cc, &dd, &wr[kbot - 1], &wi[ kbot - 1], &wr[kbot], &wi[kbot], &cs, &sn) ; ks = kbot - 1; } } if (kbot - ks + 1 > ns) { // // ==== Sort the shifts (Helps a little) // . Bubble sort keeps complex conjugate // . pairs together. ==== // sorted = FALSE_; i__2 = ks + 1; for (k = kbot; k >= i__2; --k) { if (sorted) { goto L60; } sorted = TRUE_; i__3 = k - 1; for (i__ = ks; i__ <= i__3; ++i__) { if ((d__1 = wr[i__], abs(d__1)) + (d__2 = wi[ i__], abs(d__2)) < (d__3 = wr[i__ + 1] , abs(d__3)) + (d__4 = wi[i__ + 1], abs(d__4))) { sorted = FALSE_; swap = wr[i__]; wr[i__] = wr[i__ + 1]; wr[i__ + 1] = swap; swap = wi[i__]; wi[i__] = wi[i__ + 1]; wi[i__ + 1] = swap; } // L40: } // L50: } L60: ; } // // ==== Shuffle shifts into pairs of real shifts // . and pairs of complex conjugate shifts // . assuming complex conjugate shifts are // . already adjacent to one another. (Yes, // . they are.) ==== // i__2 = ks + 2; for (i__ = kbot; i__ >= i__2; i__ += -2) { if (wi[i__] != -wi[i__ - 1]) { swap = wr[i__]; wr[i__] = wr[i__ - 1]; wr[i__ - 1] = wr[i__ - 2]; wr[i__ - 2] = swap; swap = wi[i__]; wi[i__] = wi[i__ - 1]; wi[i__ - 1] = wi[i__ - 2]; wi[i__ - 2] = swap; } // L70: } } // // ==== If there are only two shifts and both are // . real, then use only one. ==== // if (kbot - ks + 1 == 2) { if (wi[kbot] == 0.) { if ((d__1 = wr[kbot] - h__[kbot + kbot * h_dim1], abs( d__1)) < (d__2 = wr[kbot - 1] - h__[kbot + kbot * h_dim1], abs(d__2))) { wr[kbot - 1] = wr[kbot]; } else { wr[kbot] = wr[kbot - 1]; } } } // // ==== Use up to NS of the the smallest magnitude // . shifts. If there aren't NS shifts available, // . then use them all, possibly dropping one to // . make the number of shifts even. ==== // // Computing MIN i__2 = ns, i__3 = kbot - ks + 1; ns = min(i__2,i__3); ns -= ns % 2; ks = kbot - ns + 1; // // ==== Small-bulge multi-shift QR sweep: // . split workspace under the subdiagonal into // . - a KDU-by-KDU work array U in the lower // . left-hand-corner, // . - a KDU-by-at-least-KDU-but-more-is-better // . (KDU-by-NHo) horizontal work array WH along // . the bottom edge, // . - and an at-least-KDU-but-more-is-better-by-KDU // . (NVE-by-KDU) vertical work WV arrow along // . the left-hand-edge. ==== // kdu = ns * 3 - 3; ku = *n - kdu + 1; kwh = kdu + 1; nho = *n - kdu - 3 - (kdu + 1) + 1; kwv = kdu + 4; nve = *n - kdu - kwv + 1; // // ==== Small-bulge multi-shift QR sweep ==== // dlaqr5_(wantt, wantz, &kacc22, n, &ktop, &kbot, &ns, &wr[ks], &wi[ks], &h__[h_offset], ldh, iloz, ihiz, &z__[ z_offset], ldz, &work[1], &c__3, &h__[ku + h_dim1], ldh, &nve, &h__[kwv + h_dim1], ldh, &nho, &h__[ku + kwh * h_dim1], ldh); } // // ==== Note progress (or the lack of it). ==== // if (ld > 0) { ndfl = 1; } else { ++ndfl; } // // ==== End of main loop ==== // L80: } // // ==== Iteration limit exceeded. Set INFO to show where // . the problem occurred and exit. ==== // *info = kbot; L90: ; } // // ==== Return the optimal value of LWORK. ==== // work[1] = (double) lwkopt; // // ==== End of DLAQR0 ==== // return 0; } // dlaqr0_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DLAQR1 sets a scalar multiple of the first column of the product of 2-by-2 or 3-by-3 matrix H and specified shifts. // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DLAQR1 + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DLAQR1( N, H, LDH, SR1, SI1, SR2, SI2, V ) // // .. Scalar Arguments .. // DOUBLE PRECISION SI1, SI2, SR1, SR2 // INTEGER LDH, N // .. // .. Array Arguments .. // DOUBLE PRECISION H( LDH, * ), V( * ) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> Given a 2-by-2 or 3-by-3 matrix H, DLAQR1 sets v to a //> scalar multiple of the first column of the product //> //> (*) K = (H - (sr1 + i*si1)*I)*(H - (sr2 + i*si2)*I) //> //> scaling to avoid overflows and most underflows. It //> is assumed that either //> //> 1) sr1 = sr2 and si1 = -si2 //> or //> 2) si1 = si2 = 0. //> //> This is useful for starting double implicit shift bulges //> in the QR algorithm. //> \endverbatim // // Arguments: // ========== // //> \param[in] N //> \verbatim //> N is INTEGER //> Order of the matrix H. N must be either 2 or 3. //> \endverbatim //> //> \param[in] H //> \verbatim //> H is DOUBLE PRECISION array, dimension (LDH,N) //> The 2-by-2 or 3-by-3 matrix H in (*). //> \endverbatim //> //> \param[in] LDH //> \verbatim //> LDH is INTEGER //> The leading dimension of H as declared in //> the calling procedure. LDH >= N //> \endverbatim //> //> \param[in] SR1 //> \verbatim //> SR1 is DOUBLE PRECISION //> \endverbatim //> //> \param[in] SI1 //> \verbatim //> SI1 is DOUBLE PRECISION //> \endverbatim //> //> \param[in] SR2 //> \verbatim //> SR2 is DOUBLE PRECISION //> \endverbatim //> //> \param[in] SI2 //> \verbatim //> SI2 is DOUBLE PRECISION //> The shifts in (*). //> \endverbatim //> //> \param[out] V //> \verbatim //> V is DOUBLE PRECISION array, dimension (N) //> A scalar multiple of the first column of the //> matrix K in (*). //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date June 2017 // //> \ingroup doubleOTHERauxiliary // //> \par Contributors: // ================== //> //> Karen Braman and Ralph Byers, Department of Mathematics, //> University of Kansas, USA //> // ===================================================================== /* Subroutine */ int dlaqr1_(int *n, double *h__, int *ldh, double *sr1, double *si1, double *sr2, double *si2, double *v) { // System generated locals int h_dim1, h_offset; double d__1, d__2, d__3; // Local variables double s, h21s, h31s; // // -- LAPACK auxiliary routine (version 3.7.1) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // June 2017 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // // ================================================================ // // .. Parameters .. // .. // .. Local Scalars .. // .. // .. Intrinsic Functions .. // .. // .. Executable Statements .. // // Quick return if possible // // Parameter adjustments h_dim1 = *ldh; h_offset = 1 + h_dim1; h__ -= h_offset; --v; // Function Body if (*n != 2 && *n != 3) { return 0; } if (*n == 2) { s = (d__1 = h__[h_dim1 + 1] - *sr2, abs(d__1)) + abs(*si2) + (d__2 = h__[h_dim1 + 2], abs(d__2)); if (s == 0.) { v[1] = 0.; v[2] = 0.; } else { h21s = h__[h_dim1 + 2] / s; v[1] = h21s * h__[(h_dim1 << 1) + 1] + (h__[h_dim1 + 1] - *sr1) * ((h__[h_dim1 + 1] - *sr2) / s) - *si1 * (*si2 / s); v[2] = h21s * (h__[h_dim1 + 1] + h__[(h_dim1 << 1) + 2] - *sr1 - * sr2); } } else { s = (d__1 = h__[h_dim1 + 1] - *sr2, abs(d__1)) + abs(*si2) + (d__2 = h__[h_dim1 + 2], abs(d__2)) + (d__3 = h__[h_dim1 + 3], abs( d__3)); if (s == 0.) { v[1] = 0.; v[2] = 0.; v[3] = 0.; } else { h21s = h__[h_dim1 + 2] / s; h31s = h__[h_dim1 + 3] / s; v[1] = (h__[h_dim1 + 1] - *sr1) * ((h__[h_dim1 + 1] - *sr2) / s) - *si1 * (*si2 / s) + h__[(h_dim1 << 1) + 1] * h21s + h__[ h_dim1 * 3 + 1] * h31s; v[2] = h21s * (h__[h_dim1 + 1] + h__[(h_dim1 << 1) + 2] - *sr1 - * sr2) + h__[h_dim1 * 3 + 2] * h31s; v[3] = h31s * (h__[h_dim1 + 1] + h__[h_dim1 * 3 + 3] - *sr1 - * sr2) + h21s * h__[(h_dim1 << 1) + 3]; } } return 0; } // dlaqr1_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DLAQR2 performs the orthogonal similarity transformation of a Hessenberg matrix to detect and deflate fully converged eigenvalues from a trailing principal submatrix (aggressive early deflation). // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DLAQR2 + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DLAQR2( WANTT, WANTZ, N, KTOP, KBOT, NW, H, LDH, ILOZ, // IHIZ, Z, LDZ, NS, ND, SR, SI, V, LDV, NH, T, // LDT, NV, WV, LDWV, WORK, LWORK ) // // .. Scalar Arguments .. // INTEGER IHIZ, ILOZ, KBOT, KTOP, LDH, LDT, LDV, LDWV, // $ LDZ, LWORK, N, ND, NH, NS, NV, NW // LOGICAL WANTT, WANTZ // .. // .. Array Arguments .. // DOUBLE PRECISION H( LDH, * ), SI( * ), SR( * ), T( LDT, * ), // $ V( LDV, * ), WORK( * ), WV( LDWV, * ), // $ Z( LDZ, * ) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> DLAQR2 is identical to DLAQR3 except that it avoids //> recursion by calling DLAHQR instead of DLAQR4. //> //> Aggressive early deflation: //> //> This subroutine accepts as input an upper Hessenberg matrix //> H and performs an orthogonal similarity transformation //> designed to detect and deflate fully converged eigenvalues from //> a trailing principal submatrix. On output H has been over- //> written by a new Hessenberg matrix that is a perturbation of //> an orthogonal similarity transformation of H. It is to be //> hoped that the final version of H has many zero subdiagonal //> entries. //> \endverbatim // // Arguments: // ========== // //> \param[in] WANTT //> \verbatim //> WANTT is LOGICAL //> If .TRUE., then the Hessenberg matrix H is fully updated //> so that the quasi-triangular Schur factor may be //> computed (in cooperation with the calling subroutine). //> If .FALSE., then only enough of H is updated to preserve //> the eigenvalues. //> \endverbatim //> //> \param[in] WANTZ //> \verbatim //> WANTZ is LOGICAL //> If .TRUE., then the orthogonal matrix Z is updated so //> so that the orthogonal Schur factor may be computed //> (in cooperation with the calling subroutine). //> If .FALSE., then Z is not referenced. //> \endverbatim //> //> \param[in] N //> \verbatim //> N is INTEGER //> The order of the matrix H and (if WANTZ is .TRUE.) the //> order of the orthogonal matrix Z. //> \endverbatim //> //> \param[in] KTOP //> \verbatim //> KTOP is INTEGER //> It is assumed that either KTOP = 1 or H(KTOP,KTOP-1)=0. //> KBOT and KTOP together determine an isolated block //> along the diagonal of the Hessenberg matrix. //> \endverbatim //> //> \param[in] KBOT //> \verbatim //> KBOT is INTEGER //> It is assumed without a check that either //> KBOT = N or H(KBOT+1,KBOT)=0. KBOT and KTOP together //> determine an isolated block along the diagonal of the //> Hessenberg matrix. //> \endverbatim //> //> \param[in] NW //> \verbatim //> NW is INTEGER //> Deflation window size. 1 <= NW <= (KBOT-KTOP+1). //> \endverbatim //> //> \param[in,out] H //> \verbatim //> H is DOUBLE PRECISION array, dimension (LDH,N) //> On input the initial N-by-N section of H stores the //> Hessenberg matrix undergoing aggressive early deflation. //> On output H has been transformed by an orthogonal //> similarity transformation, perturbed, and the returned //> to Hessenberg form that (it is to be hoped) has some //> zero subdiagonal entries. //> \endverbatim //> //> \param[in] LDH //> \verbatim //> LDH is INTEGER //> Leading dimension of H just as declared in the calling //> subroutine. N <= LDH //> \endverbatim //> //> \param[in] ILOZ //> \verbatim //> ILOZ is INTEGER //> \endverbatim //> //> \param[in] IHIZ //> \verbatim //> IHIZ is INTEGER //> Specify the rows of Z to which transformations must be //> applied if WANTZ is .TRUE.. 1 <= ILOZ <= IHIZ <= N. //> \endverbatim //> //> \param[in,out] Z //> \verbatim //> Z is DOUBLE PRECISION array, dimension (LDZ,N) //> IF WANTZ is .TRUE., then on output, the orthogonal //> similarity transformation mentioned above has been //> accumulated into Z(ILOZ:IHIZ,ILOZ:IHIZ) from the right. //> If WANTZ is .FALSE., then Z is unreferenced. //> \endverbatim //> //> \param[in] LDZ //> \verbatim //> LDZ is INTEGER //> The leading dimension of Z just as declared in the //> calling subroutine. 1 <= LDZ. //> \endverbatim //> //> \param[out] NS //> \verbatim //> NS is INTEGER //> The number of unconverged (ie approximate) eigenvalues //> returned in SR and SI that may be used as shifts by the //> calling subroutine. //> \endverbatim //> //> \param[out] ND //> \verbatim //> ND is INTEGER //> The number of converged eigenvalues uncovered by this //> subroutine. //> \endverbatim //> //> \param[out] SR //> \verbatim //> SR is DOUBLE PRECISION array, dimension (KBOT) //> \endverbatim //> //> \param[out] SI //> \verbatim //> SI is DOUBLE PRECISION array, dimension (KBOT) //> On output, the real and imaginary parts of approximate //> eigenvalues that may be used for shifts are stored in //> SR(KBOT-ND-NS+1) through SR(KBOT-ND) and //> SI(KBOT-ND-NS+1) through SI(KBOT-ND), respectively. //> The real and imaginary parts of converged eigenvalues //> are stored in SR(KBOT-ND+1) through SR(KBOT) and //> SI(KBOT-ND+1) through SI(KBOT), respectively. //> \endverbatim //> //> \param[out] V //> \verbatim //> V is DOUBLE PRECISION array, dimension (LDV,NW) //> An NW-by-NW work array. //> \endverbatim //> //> \param[in] LDV //> \verbatim //> LDV is INTEGER //> The leading dimension of V just as declared in the //> calling subroutine. NW <= LDV //> \endverbatim //> //> \param[in] NH //> \verbatim //> NH is INTEGER //> The number of columns of T. NH >= NW. //> \endverbatim //> //> \param[out] T //> \verbatim //> T is DOUBLE PRECISION array, dimension (LDT,NW) //> \endverbatim //> //> \param[in] LDT //> \verbatim //> LDT is INTEGER //> The leading dimension of T just as declared in the //> calling subroutine. NW <= LDT //> \endverbatim //> //> \param[in] NV //> \verbatim //> NV is INTEGER //> The number of rows of work array WV available for //> workspace. NV >= NW. //> \endverbatim //> //> \param[out] WV //> \verbatim //> WV is DOUBLE PRECISION array, dimension (LDWV,NW) //> \endverbatim //> //> \param[in] LDWV //> \verbatim //> LDWV is INTEGER //> The leading dimension of W just as declared in the //> calling subroutine. NW <= LDV //> \endverbatim //> //> \param[out] WORK //> \verbatim //> WORK is DOUBLE PRECISION array, dimension (LWORK) //> On exit, WORK(1) is set to an estimate of the optimal value //> of LWORK for the given values of N, NW, KTOP and KBOT. //> \endverbatim //> //> \param[in] LWORK //> \verbatim //> LWORK is INTEGER //> The dimension of the work array WORK. LWORK = 2*NW //> suffices, but greater efficiency may result from larger //> values of LWORK. //> //> If LWORK = -1, then a workspace query is assumed; DLAQR2 //> only estimates the optimal workspace size for the given //> values of N, NW, KTOP and KBOT. The estimate is returned //> in WORK(1). No error message related to LWORK is issued //> by XERBLA. Neither H nor Z are accessed. //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date June 2017 // //> \ingroup doubleOTHERauxiliary // //> \par Contributors: // ================== //> //> Karen Braman and Ralph Byers, Department of Mathematics, //> University of Kansas, USA //> // ===================================================================== /* Subroutine */ int dlaqr2_(int *wantt, int *wantz, int *n, int *ktop, int * kbot, int *nw, double *h__, int *ldh, int *iloz, int *ihiz, double * z__, int *ldz, int *ns, int *nd, double *sr, double *si, double *v, int *ldv, int *nh, double *t, int *ldt, int *nv, double *wv, int * ldwv, double *work, int *lwork) { // Table of constant values int c__1 = 1; int c_n1 = -1; double c_b12 = 0.; double c_b13 = 1.; int c_true = TRUE_; // System generated locals int h_dim1, h_offset, t_dim1, t_offset, v_dim1, v_offset, wv_dim1, wv_offset, z_dim1, z_offset, i__1, i__2, i__3, i__4; double d__1, d__2, d__3, d__4, d__5, d__6; // Local variables int i__, j, k; double s, aa, bb, cc, dd, cs, sn; int jw; double evi, evk, foo; int kln; double tau, ulp; int lwk1, lwk2; double beta; int kend, kcol, info, ifst, ilst, ltop, krow; extern /* Subroutine */ int dlarf_(char *, int *, int *, double *, int *, double *, double *, int *, double *), dgemm_(char *, char *, int * , int *, int *, double *, double *, int *, double *, int *, double *, double *, int *); int bulge; extern /* Subroutine */ int dcopy_(int *, double *, int *, double *, int * ); int infqr, kwtop; extern /* Subroutine */ int dlanv2_(double *, double *, double *, double * , double *, double *, double *, double *, double *, double *), dlabad_(double *, double *); extern double dlamch_(char *); extern /* Subroutine */ int dgehrd_(int *, int *, int *, double *, int *, double *, double *, int *, int *), dlarfg_(int *, double *, double *, int *, double *), dlahqr_(int *, int *, int *, int *, int *, double *, int *, double *, double *, int *, int *, double * , int *, int *), dlacpy_(char *, int *, int *, double *, int *, double *, int *); double safmin; extern /* Subroutine */ int dlaset_(char *, int *, int *, double *, double *, double *, int *); double safmax; extern /* Subroutine */ int dtrexc_(char *, int *, double *, int *, double *, int *, int *, int *, double *, int *), dormhr_(char *, char *, int *, int *, int *, int *, double *, int *, double *, double *, int *, double *, int *, int *); int sorted; double smlnum; int lwkopt; // // -- LAPACK auxiliary routine (version 3.7.1) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // June 2017 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // // ================================================================ // .. Parameters .. // .. // .. Local Scalars .. // .. // .. External Functions .. // .. // .. External Subroutines .. // .. // .. Intrinsic Functions .. // .. // .. Executable Statements .. // // ==== Estimate optimal workspace. ==== // // Parameter adjustments h_dim1 = *ldh; h_offset = 1 + h_dim1; h__ -= h_offset; z_dim1 = *ldz; z_offset = 1 + z_dim1; z__ -= z_offset; --sr; --si; v_dim1 = *ldv; v_offset = 1 + v_dim1; v -= v_offset; t_dim1 = *ldt; t_offset = 1 + t_dim1; t -= t_offset; wv_dim1 = *ldwv; wv_offset = 1 + wv_dim1; wv -= wv_offset; --work; // Function Body // Computing MIN i__1 = *nw, i__2 = *kbot - *ktop + 1; jw = min(i__1,i__2); if (jw <= 2) { lwkopt = 1; } else { // // ==== Workspace query call to DGEHRD ==== // i__1 = jw - 1; dgehrd_(&jw, &c__1, &i__1, &t[t_offset], ldt, &work[1], &work[1], & c_n1, &info); lwk1 = (int) work[1]; // // ==== Workspace query call to DORMHR ==== // i__1 = jw - 1; dormhr_("R", "N", &jw, &jw, &c__1, &i__1, &t[t_offset], ldt, &work[1], &v[v_offset], ldv, &work[1], &c_n1, &info); lwk2 = (int) work[1]; // // ==== Optimal workspace ==== // lwkopt = jw + max(lwk1,lwk2); } // // ==== Quick return in case of workspace query. ==== // if (*lwork == -1) { work[1] = (double) lwkopt; return 0; } // // ==== Nothing to do ... // ... for an empty active block ... ==== *ns = 0; *nd = 0; work[1] = 1.; if (*ktop > *kbot) { return 0; } // ... nor for an empty deflation window. ==== if (*nw < 1) { return 0; } // // ==== Machine constants ==== // safmin = dlamch_("SAFE MINIMUM"); safmax = 1. / safmin; dlabad_(&safmin, &safmax); ulp = dlamch_("PRECISION"); smlnum = safmin * ((double) (*n) / ulp); // // ==== Setup deflation window ==== // // Computing MIN i__1 = *nw, i__2 = *kbot - *ktop + 1; jw = min(i__1,i__2); kwtop = *kbot - jw + 1; if (kwtop == *ktop) { s = 0.; } else { s = h__[kwtop + (kwtop - 1) * h_dim1]; } if (*kbot == kwtop) { // // ==== 1-by-1 deflation window: not much to do ==== // sr[kwtop] = h__[kwtop + kwtop * h_dim1]; si[kwtop] = 0.; *ns = 1; *nd = 0; // Computing MAX d__2 = smlnum, d__3 = ulp * (d__1 = h__[kwtop + kwtop * h_dim1], abs( d__1)); if (abs(s) <= max(d__2,d__3)) { *ns = 0; *nd = 1; if (kwtop > *ktop) { h__[kwtop + (kwtop - 1) * h_dim1] = 0.; } } work[1] = 1.; return 0; } // // ==== Convert to spike-triangular form. (In case of a // . rare QR failure, this routine continues to do // . aggressive early deflation using that part of // . the deflation window that converged using INFQR // . here and there to keep track.) ==== // dlacpy_("U", &jw, &jw, &h__[kwtop + kwtop * h_dim1], ldh, &t[t_offset], ldt); i__1 = jw - 1; i__2 = *ldh + 1; i__3 = *ldt + 1; dcopy_(&i__1, &h__[kwtop + 1 + kwtop * h_dim1], &i__2, &t[t_dim1 + 2], & i__3); dlaset_("A", &jw, &jw, &c_b12, &c_b13, &v[v_offset], ldv); dlahqr_(&c_true, &c_true, &jw, &c__1, &jw, &t[t_offset], ldt, &sr[kwtop], &si[kwtop], &c__1, &jw, &v[v_offset], ldv, &infqr); // // ==== DTREXC needs a clean margin near the diagonal ==== // i__1 = jw - 3; for (j = 1; j <= i__1; ++j) { t[j + 2 + j * t_dim1] = 0.; t[j + 3 + j * t_dim1] = 0.; // L10: } if (jw > 2) { t[jw + (jw - 2) * t_dim1] = 0.; } // // ==== Deflation detection loop ==== // *ns = jw; ilst = infqr + 1; L20: if (ilst <= *ns) { if (*ns == 1) { bulge = FALSE_; } else { bulge = t[*ns + (*ns - 1) * t_dim1] != 0.; } // // ==== Small spike tip test for deflation ==== // if (! bulge) { // // ==== Real eigenvalue ==== // foo = (d__1 = t[*ns + *ns * t_dim1], abs(d__1)); if (foo == 0.) { foo = abs(s); } // Computing MAX d__2 = smlnum, d__3 = ulp * foo; if ((d__1 = s * v[*ns * v_dim1 + 1], abs(d__1)) <= max(d__2,d__3)) { // // ==== Deflatable ==== // --(*ns); } else { // // ==== Undeflatable. Move it up out of the way. // . (DTREXC can not fail in this case.) ==== // ifst = *ns; dtrexc_("V", &jw, &t[t_offset], ldt, &v[v_offset], ldv, &ifst, &ilst, &work[1], &info); ++ilst; } } else { // // ==== Complex conjugate pair ==== // foo = (d__3 = t[*ns + *ns * t_dim1], abs(d__3)) + sqrt((d__1 = t[* ns + (*ns - 1) * t_dim1], abs(d__1))) * sqrt((d__2 = t[* ns - 1 + *ns * t_dim1], abs(d__2))); if (foo == 0.) { foo = abs(s); } // Computing MAX d__3 = (d__1 = s * v[*ns * v_dim1 + 1], abs(d__1)), d__4 = (d__2 = s * v[(*ns - 1) * v_dim1 + 1], abs(d__2)); // Computing MAX d__5 = smlnum, d__6 = ulp * foo; if (max(d__3,d__4) <= max(d__5,d__6)) { // // ==== Deflatable ==== // *ns += -2; } else { // // ==== Undeflatable. Move them up out of the way. // . Fortunately, DTREXC does the right thing with // . ILST in case of a rare exchange failure. ==== // ifst = *ns; dtrexc_("V", &jw, &t[t_offset], ldt, &v[v_offset], ldv, &ifst, &ilst, &work[1], &info); ilst += 2; } } // // ==== End deflation detection loop ==== // goto L20; } // // ==== Return to Hessenberg form ==== // if (*ns == 0) { s = 0.; } if (*ns < jw) { // // ==== sorting diagonal blocks of T improves accuracy for // . graded matrices. Bubble sort deals well with // . exchange failures. ==== // sorted = FALSE_; i__ = *ns + 1; L30: if (sorted) { goto L50; } sorted = TRUE_; kend = i__ - 1; i__ = infqr + 1; if (i__ == *ns) { k = i__ + 1; } else if (t[i__ + 1 + i__ * t_dim1] == 0.) { k = i__ + 1; } else { k = i__ + 2; } L40: if (k <= kend) { if (k == i__ + 1) { evi = (d__1 = t[i__ + i__ * t_dim1], abs(d__1)); } else { evi = (d__3 = t[i__ + i__ * t_dim1], abs(d__3)) + sqrt((d__1 = t[i__ + 1 + i__ * t_dim1], abs(d__1))) * sqrt((d__2 = t[i__ + (i__ + 1) * t_dim1], abs(d__2))); } if (k == kend) { evk = (d__1 = t[k + k * t_dim1], abs(d__1)); } else if (t[k + 1 + k * t_dim1] == 0.) { evk = (d__1 = t[k + k * t_dim1], abs(d__1)); } else { evk = (d__3 = t[k + k * t_dim1], abs(d__3)) + sqrt((d__1 = t[ k + 1 + k * t_dim1], abs(d__1))) * sqrt((d__2 = t[k + (k + 1) * t_dim1], abs(d__2))); } if (evi >= evk) { i__ = k; } else { sorted = FALSE_; ifst = i__; ilst = k; dtrexc_("V", &jw, &t[t_offset], ldt, &v[v_offset], ldv, &ifst, &ilst, &work[1], &info); if (info == 0) { i__ = ilst; } else { i__ = k; } } if (i__ == kend) { k = i__ + 1; } else if (t[i__ + 1 + i__ * t_dim1] == 0.) { k = i__ + 1; } else { k = i__ + 2; } goto L40; } goto L30; L50: ; } // // ==== Restore shift/eigenvalue array from T ==== // i__ = jw; L60: if (i__ >= infqr + 1) { if (i__ == infqr + 1) { sr[kwtop + i__ - 1] = t[i__ + i__ * t_dim1]; si[kwtop + i__ - 1] = 0.; --i__; } else if (t[i__ + (i__ - 1) * t_dim1] == 0.) { sr[kwtop + i__ - 1] = t[i__ + i__ * t_dim1]; si[kwtop + i__ - 1] = 0.; --i__; } else { aa = t[i__ - 1 + (i__ - 1) * t_dim1]; cc = t[i__ + (i__ - 1) * t_dim1]; bb = t[i__ - 1 + i__ * t_dim1]; dd = t[i__ + i__ * t_dim1]; dlanv2_(&aa, &bb, &cc, &dd, &sr[kwtop + i__ - 2], &si[kwtop + i__ - 2], &sr[kwtop + i__ - 1], &si[kwtop + i__ - 1], &cs, & sn); i__ += -2; } goto L60; } if (*ns < jw || s == 0.) { if (*ns > 1 && s != 0.) { // // ==== Reflect spike back into lower triangle ==== // dcopy_(ns, &v[v_offset], ldv, &work[1], &c__1); beta = work[1]; dlarfg_(ns, &beta, &work[2], &c__1, &tau); work[1] = 1.; i__1 = jw - 2; i__2 = jw - 2; dlaset_("L", &i__1, &i__2, &c_b12, &c_b12, &t[t_dim1 + 3], ldt); dlarf_("L", ns, &jw, &work[1], &c__1, &tau, &t[t_offset], ldt, & work[jw + 1]); dlarf_("R", ns, ns, &work[1], &c__1, &tau, &t[t_offset], ldt, & work[jw + 1]); dlarf_("R", &jw, ns, &work[1], &c__1, &tau, &v[v_offset], ldv, & work[jw + 1]); i__1 = *lwork - jw; dgehrd_(&jw, &c__1, ns, &t[t_offset], ldt, &work[1], &work[jw + 1] , &i__1, &info); } // // ==== Copy updated reduced window into place ==== // if (kwtop > 1) { h__[kwtop + (kwtop - 1) * h_dim1] = s * v[v_dim1 + 1]; } dlacpy_("U", &jw, &jw, &t[t_offset], ldt, &h__[kwtop + kwtop * h_dim1] , ldh); i__1 = jw - 1; i__2 = *ldt + 1; i__3 = *ldh + 1; dcopy_(&i__1, &t[t_dim1 + 2], &i__2, &h__[kwtop + 1 + kwtop * h_dim1], &i__3); // // ==== Accumulate orthogonal matrix in order update // . H and Z, if requested. ==== // if (*ns > 1 && s != 0.) { i__1 = *lwork - jw; dormhr_("R", "N", &jw, ns, &c__1, ns, &t[t_offset], ldt, &work[1], &v[v_offset], ldv, &work[jw + 1], &i__1, &info); } // // ==== Update vertical slab in H ==== // if (*wantt) { ltop = 1; } else { ltop = *ktop; } i__1 = kwtop - 1; i__2 = *nv; for (krow = ltop; i__2 < 0 ? krow >= i__1 : krow <= i__1; krow += i__2) { // Computing MIN i__3 = *nv, i__4 = kwtop - krow; kln = min(i__3,i__4); dgemm_("N", "N", &kln, &jw, &jw, &c_b13, &h__[krow + kwtop * h_dim1], ldh, &v[v_offset], ldv, &c_b12, &wv[wv_offset], ldwv); dlacpy_("A", &kln, &jw, &wv[wv_offset], ldwv, &h__[krow + kwtop * h_dim1], ldh); // L70: } // // ==== Update horizontal slab in H ==== // if (*wantt) { i__2 = *n; i__1 = *nh; for (kcol = *kbot + 1; i__1 < 0 ? kcol >= i__2 : kcol <= i__2; kcol += i__1) { // Computing MIN i__3 = *nh, i__4 = *n - kcol + 1; kln = min(i__3,i__4); dgemm_("C", "N", &jw, &kln, &jw, &c_b13, &v[v_offset], ldv, & h__[kwtop + kcol * h_dim1], ldh, &c_b12, &t[t_offset], ldt); dlacpy_("A", &jw, &kln, &t[t_offset], ldt, &h__[kwtop + kcol * h_dim1], ldh); // L80: } } // // ==== Update vertical slab in Z ==== // if (*wantz) { i__1 = *ihiz; i__2 = *nv; for (krow = *iloz; i__2 < 0 ? krow >= i__1 : krow <= i__1; krow += i__2) { // Computing MIN i__3 = *nv, i__4 = *ihiz - krow + 1; kln = min(i__3,i__4); dgemm_("N", "N", &kln, &jw, &jw, &c_b13, &z__[krow + kwtop * z_dim1], ldz, &v[v_offset], ldv, &c_b12, &wv[ wv_offset], ldwv); dlacpy_("A", &kln, &jw, &wv[wv_offset], ldwv, &z__[krow + kwtop * z_dim1], ldz); // L90: } } } // // ==== Return the number of deflations ... ==== // *nd = jw - *ns; // // ==== ... and the number of shifts. (Subtracting // . INFQR from the spike length takes care // . of the case of a rare QR failure while // . calculating eigenvalues of the deflation // . window.) ==== // *ns -= infqr; // // ==== Return optimal workspace. ==== // work[1] = (double) lwkopt; // // ==== End of DLAQR2 ==== // return 0; } // dlaqr2_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DLAQR3 performs the orthogonal similarity transformation of a Hessenberg matrix to detect and deflate fully converged eigenvalues from a trailing principal submatrix (aggressive early deflation). // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DLAQR3 + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DLAQR3( WANTT, WANTZ, N, KTOP, KBOT, NW, H, LDH, ILOZ, // IHIZ, Z, LDZ, NS, ND, SR, SI, V, LDV, NH, T, // LDT, NV, WV, LDWV, WORK, LWORK ) // // .. Scalar Arguments .. // INTEGER IHIZ, ILOZ, KBOT, KTOP, LDH, LDT, LDV, LDWV, // $ LDZ, LWORK, N, ND, NH, NS, NV, NW // LOGICAL WANTT, WANTZ // .. // .. Array Arguments .. // DOUBLE PRECISION H( LDH, * ), SI( * ), SR( * ), T( LDT, * ), // $ V( LDV, * ), WORK( * ), WV( LDWV, * ), // $ Z( LDZ, * ) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> Aggressive early deflation: //> //> DLAQR3 accepts as input an upper Hessenberg matrix //> H and performs an orthogonal similarity transformation //> designed to detect and deflate fully converged eigenvalues from //> a trailing principal submatrix. On output H has been over- //> written by a new Hessenberg matrix that is a perturbation of //> an orthogonal similarity transformation of H. It is to be //> hoped that the final version of H has many zero subdiagonal //> entries. //> \endverbatim // // Arguments: // ========== // //> \param[in] WANTT //> \verbatim //> WANTT is LOGICAL //> If .TRUE., then the Hessenberg matrix H is fully updated //> so that the quasi-triangular Schur factor may be //> computed (in cooperation with the calling subroutine). //> If .FALSE., then only enough of H is updated to preserve //> the eigenvalues. //> \endverbatim //> //> \param[in] WANTZ //> \verbatim //> WANTZ is LOGICAL //> If .TRUE., then the orthogonal matrix Z is updated so //> so that the orthogonal Schur factor may be computed //> (in cooperation with the calling subroutine). //> If .FALSE., then Z is not referenced. //> \endverbatim //> //> \param[in] N //> \verbatim //> N is INTEGER //> The order of the matrix H and (if WANTZ is .TRUE.) the //> order of the orthogonal matrix Z. //> \endverbatim //> //> \param[in] KTOP //> \verbatim //> KTOP is INTEGER //> It is assumed that either KTOP = 1 or H(KTOP,KTOP-1)=0. //> KBOT and KTOP together determine an isolated block //> along the diagonal of the Hessenberg matrix. //> \endverbatim //> //> \param[in] KBOT //> \verbatim //> KBOT is INTEGER //> It is assumed without a check that either //> KBOT = N or H(KBOT+1,KBOT)=0. KBOT and KTOP together //> determine an isolated block along the diagonal of the //> Hessenberg matrix. //> \endverbatim //> //> \param[in] NW //> \verbatim //> NW is INTEGER //> Deflation window size. 1 <= NW <= (KBOT-KTOP+1). //> \endverbatim //> //> \param[in,out] H //> \verbatim //> H is DOUBLE PRECISION array, dimension (LDH,N) //> On input the initial N-by-N section of H stores the //> Hessenberg matrix undergoing aggressive early deflation. //> On output H has been transformed by an orthogonal //> similarity transformation, perturbed, and the returned //> to Hessenberg form that (it is to be hoped) has some //> zero subdiagonal entries. //> \endverbatim //> //> \param[in] LDH //> \verbatim //> LDH is INTEGER //> Leading dimension of H just as declared in the calling //> subroutine. N <= LDH //> \endverbatim //> //> \param[in] ILOZ //> \verbatim //> ILOZ is INTEGER //> \endverbatim //> //> \param[in] IHIZ //> \verbatim //> IHIZ is INTEGER //> Specify the rows of Z to which transformations must be //> applied if WANTZ is .TRUE.. 1 <= ILOZ <= IHIZ <= N. //> \endverbatim //> //> \param[in,out] Z //> \verbatim //> Z is DOUBLE PRECISION array, dimension (LDZ,N) //> IF WANTZ is .TRUE., then on output, the orthogonal //> similarity transformation mentioned above has been //> accumulated into Z(ILOZ:IHIZ,ILOZ:IHIZ) from the right. //> If WANTZ is .FALSE., then Z is unreferenced. //> \endverbatim //> //> \param[in] LDZ //> \verbatim //> LDZ is INTEGER //> The leading dimension of Z just as declared in the //> calling subroutine. 1 <= LDZ. //> \endverbatim //> //> \param[out] NS //> \verbatim //> NS is INTEGER //> The number of unconverged (ie approximate) eigenvalues //> returned in SR and SI that may be used as shifts by the //> calling subroutine. //> \endverbatim //> //> \param[out] ND //> \verbatim //> ND is INTEGER //> The number of converged eigenvalues uncovered by this //> subroutine. //> \endverbatim //> //> \param[out] SR //> \verbatim //> SR is DOUBLE PRECISION array, dimension (KBOT) //> \endverbatim //> //> \param[out] SI //> \verbatim //> SI is DOUBLE PRECISION array, dimension (KBOT) //> On output, the real and imaginary parts of approximate //> eigenvalues that may be used for shifts are stored in //> SR(KBOT-ND-NS+1) through SR(KBOT-ND) and //> SI(KBOT-ND-NS+1) through SI(KBOT-ND), respectively. //> The real and imaginary parts of converged eigenvalues //> are stored in SR(KBOT-ND+1) through SR(KBOT) and //> SI(KBOT-ND+1) through SI(KBOT), respectively. //> \endverbatim //> //> \param[out] V //> \verbatim //> V is DOUBLE PRECISION array, dimension (LDV,NW) //> An NW-by-NW work array. //> \endverbatim //> //> \param[in] LDV //> \verbatim //> LDV is INTEGER //> The leading dimension of V just as declared in the //> calling subroutine. NW <= LDV //> \endverbatim //> //> \param[in] NH //> \verbatim //> NH is INTEGER //> The number of columns of T. NH >= NW. //> \endverbatim //> //> \param[out] T //> \verbatim //> T is DOUBLE PRECISION array, dimension (LDT,NW) //> \endverbatim //> //> \param[in] LDT //> \verbatim //> LDT is INTEGER //> The leading dimension of T just as declared in the //> calling subroutine. NW <= LDT //> \endverbatim //> //> \param[in] NV //> \verbatim //> NV is INTEGER //> The number of rows of work array WV available for //> workspace. NV >= NW. //> \endverbatim //> //> \param[out] WV //> \verbatim //> WV is DOUBLE PRECISION array, dimension (LDWV,NW) //> \endverbatim //> //> \param[in] LDWV //> \verbatim //> LDWV is INTEGER //> The leading dimension of W just as declared in the //> calling subroutine. NW <= LDV //> \endverbatim //> //> \param[out] WORK //> \verbatim //> WORK is DOUBLE PRECISION array, dimension (LWORK) //> On exit, WORK(1) is set to an estimate of the optimal value //> of LWORK for the given values of N, NW, KTOP and KBOT. //> \endverbatim //> //> \param[in] LWORK //> \verbatim //> LWORK is INTEGER //> The dimension of the work array WORK. LWORK = 2*NW //> suffices, but greater efficiency may result from larger //> values of LWORK. //> //> If LWORK = -1, then a workspace query is assumed; DLAQR3 //> only estimates the optimal workspace size for the given //> values of N, NW, KTOP and KBOT. The estimate is returned //> in WORK(1). No error message related to LWORK is issued //> by XERBLA. Neither H nor Z are accessed. //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date June 2016 // //> \ingroup doubleOTHERauxiliary // //> \par Contributors: // ================== //> //> Karen Braman and Ralph Byers, Department of Mathematics, //> University of Kansas, USA //> // ===================================================================== /* Subroutine */ int dlaqr3_(int *wantt, int *wantz, int *n, int *ktop, int * kbot, int *nw, double *h__, int *ldh, int *iloz, int *ihiz, double * z__, int *ldz, int *ns, int *nd, double *sr, double *si, double *v, int *ldv, int *nh, double *t, int *ldt, int *nv, double *wv, int * ldwv, double *work, int *lwork) { // Table of constant values int c__1 = 1; int c_n1 = -1; int c_true = TRUE_; double c_b17 = 0.; double c_b18 = 1.; int c__12 = 12; // System generated locals int h_dim1, h_offset, t_dim1, t_offset, v_dim1, v_offset, wv_dim1, wv_offset, z_dim1, z_offset, i__1, i__2, i__3, i__4; double d__1, d__2, d__3, d__4, d__5, d__6; // Local variables int i__, j, k; double s, aa, bb, cc, dd, cs, sn; int jw; double evi, evk, foo; int kln; double tau, ulp; int lwk1, lwk2, lwk3; double beta; int kend, kcol, info, nmin, ifst, ilst, ltop, krow; extern /* Subroutine */ int dlarf_(char *, int *, int *, double *, int *, double *, double *, int *, double *), dgemm_(char *, char *, int * , int *, int *, double *, double *, int *, double *, int *, double *, double *, int *); int bulge; extern /* Subroutine */ int dcopy_(int *, double *, int *, double *, int * ); int infqr, kwtop; extern /* Subroutine */ int dlanv2_(double *, double *, double *, double * , double *, double *, double *, double *, double *, double *), dlaqr4_(int *, int *, int *, int *, int *, double *, int *, double *, double *, int *, int *, double *, int *, double *, int * , int *), dlabad_(double *, double *); extern double dlamch_(char *); extern /* Subroutine */ int dgehrd_(int *, int *, int *, double *, int *, double *, double *, int *, int *), dlarfg_(int *, double *, double *, int *, double *), dlahqr_(int *, int *, int *, int *, int *, double *, int *, double *, double *, int *, int *, double * , int *, int *), dlacpy_(char *, int *, int *, double *, int *, double *, int *); double safmin; extern int ilaenv_(int *, char *, char *, int *, int *, int *, int *); double safmax; extern /* Subroutine */ int dlaset_(char *, int *, int *, double *, double *, double *, int *), dtrexc_(char *, int *, double *, int * , double *, int *, int *, int *, double *, int *), dormhr_(char *, char *, int *, int *, int *, int *, double *, int *, double *, double *, int *, double *, int *, int *); int sorted; double smlnum; int lwkopt; // // -- LAPACK auxiliary routine (version 3.7.1) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // June 2016 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // // ================================================================ // .. Parameters .. // .. // .. Local Scalars .. // .. // .. External Functions .. // .. // .. External Subroutines .. // .. // .. Intrinsic Functions .. // .. // .. Executable Statements .. // // ==== Estimate optimal workspace. ==== // // Parameter adjustments h_dim1 = *ldh; h_offset = 1 + h_dim1; h__ -= h_offset; z_dim1 = *ldz; z_offset = 1 + z_dim1; z__ -= z_offset; --sr; --si; v_dim1 = *ldv; v_offset = 1 + v_dim1; v -= v_offset; t_dim1 = *ldt; t_offset = 1 + t_dim1; t -= t_offset; wv_dim1 = *ldwv; wv_offset = 1 + wv_dim1; wv -= wv_offset; --work; // Function Body // Computing MIN i__1 = *nw, i__2 = *kbot - *ktop + 1; jw = min(i__1,i__2); if (jw <= 2) { lwkopt = 1; } else { // // ==== Workspace query call to DGEHRD ==== // i__1 = jw - 1; dgehrd_(&jw, &c__1, &i__1, &t[t_offset], ldt, &work[1], &work[1], & c_n1, &info); lwk1 = (int) work[1]; // // ==== Workspace query call to DORMHR ==== // i__1 = jw - 1; dormhr_("R", "N", &jw, &jw, &c__1, &i__1, &t[t_offset], ldt, &work[1], &v[v_offset], ldv, &work[1], &c_n1, &info); lwk2 = (int) work[1]; // // ==== Workspace query call to DLAQR4 ==== // dlaqr4_(&c_true, &c_true, &jw, &c__1, &jw, &t[t_offset], ldt, &sr[1], &si[1], &c__1, &jw, &v[v_offset], ldv, &work[1], &c_n1, & infqr); lwk3 = (int) work[1]; // // ==== Optimal workspace ==== // // Computing MAX i__1 = jw + max(lwk1,lwk2); lwkopt = max(i__1,lwk3); } // // ==== Quick return in case of workspace query. ==== // if (*lwork == -1) { work[1] = (double) lwkopt; return 0; } // // ==== Nothing to do ... // ... for an empty active block ... ==== *ns = 0; *nd = 0; work[1] = 1.; if (*ktop > *kbot) { return 0; } // ... nor for an empty deflation window. ==== if (*nw < 1) { return 0; } // // ==== Machine constants ==== // safmin = dlamch_("SAFE MINIMUM"); safmax = 1. / safmin; dlabad_(&safmin, &safmax); ulp = dlamch_("PRECISION"); smlnum = safmin * ((double) (*n) / ulp); // // ==== Setup deflation window ==== // // Computing MIN i__1 = *nw, i__2 = *kbot - *ktop + 1; jw = min(i__1,i__2); kwtop = *kbot - jw + 1; if (kwtop == *ktop) { s = 0.; } else { s = h__[kwtop + (kwtop - 1) * h_dim1]; } if (*kbot == kwtop) { // // ==== 1-by-1 deflation window: not much to do ==== // sr[kwtop] = h__[kwtop + kwtop * h_dim1]; si[kwtop] = 0.; *ns = 1; *nd = 0; // Computing MAX d__2 = smlnum, d__3 = ulp * (d__1 = h__[kwtop + kwtop * h_dim1], abs( d__1)); if (abs(s) <= max(d__2,d__3)) { *ns = 0; *nd = 1; if (kwtop > *ktop) { h__[kwtop + (kwtop - 1) * h_dim1] = 0.; } } work[1] = 1.; return 0; } // // ==== Convert to spike-triangular form. (In case of a // . rare QR failure, this routine continues to do // . aggressive early deflation using that part of // . the deflation window that converged using INFQR // . here and there to keep track.) ==== // dlacpy_("U", &jw, &jw, &h__[kwtop + kwtop * h_dim1], ldh, &t[t_offset], ldt); i__1 = jw - 1; i__2 = *ldh + 1; i__3 = *ldt + 1; dcopy_(&i__1, &h__[kwtop + 1 + kwtop * h_dim1], &i__2, &t[t_dim1 + 2], & i__3); dlaset_("A", &jw, &jw, &c_b17, &c_b18, &v[v_offset], ldv); nmin = ilaenv_(&c__12, "DLAQR3", "SV", &jw, &c__1, &jw, lwork); if (jw > nmin) { dlaqr4_(&c_true, &c_true, &jw, &c__1, &jw, &t[t_offset], ldt, &sr[ kwtop], &si[kwtop], &c__1, &jw, &v[v_offset], ldv, &work[1], lwork, &infqr); } else { dlahqr_(&c_true, &c_true, &jw, &c__1, &jw, &t[t_offset], ldt, &sr[ kwtop], &si[kwtop], &c__1, &jw, &v[v_offset], ldv, &infqr); } // // ==== DTREXC needs a clean margin near the diagonal ==== // i__1 = jw - 3; for (j = 1; j <= i__1; ++j) { t[j + 2 + j * t_dim1] = 0.; t[j + 3 + j * t_dim1] = 0.; // L10: } if (jw > 2) { t[jw + (jw - 2) * t_dim1] = 0.; } // // ==== Deflation detection loop ==== // *ns = jw; ilst = infqr + 1; L20: if (ilst <= *ns) { if (*ns == 1) { bulge = FALSE_; } else { bulge = t[*ns + (*ns - 1) * t_dim1] != 0.; } // // ==== Small spike tip test for deflation ==== // if (! bulge) { // // ==== Real eigenvalue ==== // foo = (d__1 = t[*ns + *ns * t_dim1], abs(d__1)); if (foo == 0.) { foo = abs(s); } // Computing MAX d__2 = smlnum, d__3 = ulp * foo; if ((d__1 = s * v[*ns * v_dim1 + 1], abs(d__1)) <= max(d__2,d__3)) { // // ==== Deflatable ==== // --(*ns); } else { // // ==== Undeflatable. Move it up out of the way. // . (DTREXC can not fail in this case.) ==== // ifst = *ns; dtrexc_("V", &jw, &t[t_offset], ldt, &v[v_offset], ldv, &ifst, &ilst, &work[1], &info); ++ilst; } } else { // // ==== Complex conjugate pair ==== // foo = (d__3 = t[*ns + *ns * t_dim1], abs(d__3)) + sqrt((d__1 = t[* ns + (*ns - 1) * t_dim1], abs(d__1))) * sqrt((d__2 = t[* ns - 1 + *ns * t_dim1], abs(d__2))); if (foo == 0.) { foo = abs(s); } // Computing MAX d__3 = (d__1 = s * v[*ns * v_dim1 + 1], abs(d__1)), d__4 = (d__2 = s * v[(*ns - 1) * v_dim1 + 1], abs(d__2)); // Computing MAX d__5 = smlnum, d__6 = ulp * foo; if (max(d__3,d__4) <= max(d__5,d__6)) { // // ==== Deflatable ==== // *ns += -2; } else { // // ==== Undeflatable. Move them up out of the way. // . Fortunately, DTREXC does the right thing with // . ILST in case of a rare exchange failure. ==== // ifst = *ns; dtrexc_("V", &jw, &t[t_offset], ldt, &v[v_offset], ldv, &ifst, &ilst, &work[1], &info); ilst += 2; } } // // ==== End deflation detection loop ==== // goto L20; } // // ==== Return to Hessenberg form ==== // if (*ns == 0) { s = 0.; } if (*ns < jw) { // // ==== sorting diagonal blocks of T improves accuracy for // . graded matrices. Bubble sort deals well with // . exchange failures. ==== // sorted = FALSE_; i__ = *ns + 1; L30: if (sorted) { goto L50; } sorted = TRUE_; kend = i__ - 1; i__ = infqr + 1; if (i__ == *ns) { k = i__ + 1; } else if (t[i__ + 1 + i__ * t_dim1] == 0.) { k = i__ + 1; } else { k = i__ + 2; } L40: if (k <= kend) { if (k == i__ + 1) { evi = (d__1 = t[i__ + i__ * t_dim1], abs(d__1)); } else { evi = (d__3 = t[i__ + i__ * t_dim1], abs(d__3)) + sqrt((d__1 = t[i__ + 1 + i__ * t_dim1], abs(d__1))) * sqrt((d__2 = t[i__ + (i__ + 1) * t_dim1], abs(d__2))); } if (k == kend) { evk = (d__1 = t[k + k * t_dim1], abs(d__1)); } else if (t[k + 1 + k * t_dim1] == 0.) { evk = (d__1 = t[k + k * t_dim1], abs(d__1)); } else { evk = (d__3 = t[k + k * t_dim1], abs(d__3)) + sqrt((d__1 = t[ k + 1 + k * t_dim1], abs(d__1))) * sqrt((d__2 = t[k + (k + 1) * t_dim1], abs(d__2))); } if (evi >= evk) { i__ = k; } else { sorted = FALSE_; ifst = i__; ilst = k; dtrexc_("V", &jw, &t[t_offset], ldt, &v[v_offset], ldv, &ifst, &ilst, &work[1], &info); if (info == 0) { i__ = ilst; } else { i__ = k; } } if (i__ == kend) { k = i__ + 1; } else if (t[i__ + 1 + i__ * t_dim1] == 0.) { k = i__ + 1; } else { k = i__ + 2; } goto L40; } goto L30; L50: ; } // // ==== Restore shift/eigenvalue array from T ==== // i__ = jw; L60: if (i__ >= infqr + 1) { if (i__ == infqr + 1) { sr[kwtop + i__ - 1] = t[i__ + i__ * t_dim1]; si[kwtop + i__ - 1] = 0.; --i__; } else if (t[i__ + (i__ - 1) * t_dim1] == 0.) { sr[kwtop + i__ - 1] = t[i__ + i__ * t_dim1]; si[kwtop + i__ - 1] = 0.; --i__; } else { aa = t[i__ - 1 + (i__ - 1) * t_dim1]; cc = t[i__ + (i__ - 1) * t_dim1]; bb = t[i__ - 1 + i__ * t_dim1]; dd = t[i__ + i__ * t_dim1]; dlanv2_(&aa, &bb, &cc, &dd, &sr[kwtop + i__ - 2], &si[kwtop + i__ - 2], &sr[kwtop + i__ - 1], &si[kwtop + i__ - 1], &cs, & sn); i__ += -2; } goto L60; } if (*ns < jw || s == 0.) { if (*ns > 1 && s != 0.) { // // ==== Reflect spike back into lower triangle ==== // dcopy_(ns, &v[v_offset], ldv, &work[1], &c__1); beta = work[1]; dlarfg_(ns, &beta, &work[2], &c__1, &tau); work[1] = 1.; i__1 = jw - 2; i__2 = jw - 2; dlaset_("L", &i__1, &i__2, &c_b17, &c_b17, &t[t_dim1 + 3], ldt); dlarf_("L", ns, &jw, &work[1], &c__1, &tau, &t[t_offset], ldt, & work[jw + 1]); dlarf_("R", ns, ns, &work[1], &c__1, &tau, &t[t_offset], ldt, & work[jw + 1]); dlarf_("R", &jw, ns, &work[1], &c__1, &tau, &v[v_offset], ldv, & work[jw + 1]); i__1 = *lwork - jw; dgehrd_(&jw, &c__1, ns, &t[t_offset], ldt, &work[1], &work[jw + 1] , &i__1, &info); } // // ==== Copy updated reduced window into place ==== // if (kwtop > 1) { h__[kwtop + (kwtop - 1) * h_dim1] = s * v[v_dim1 + 1]; } dlacpy_("U", &jw, &jw, &t[t_offset], ldt, &h__[kwtop + kwtop * h_dim1] , ldh); i__1 = jw - 1; i__2 = *ldt + 1; i__3 = *ldh + 1; dcopy_(&i__1, &t[t_dim1 + 2], &i__2, &h__[kwtop + 1 + kwtop * h_dim1], &i__3); // // ==== Accumulate orthogonal matrix in order update // . H and Z, if requested. ==== // if (*ns > 1 && s != 0.) { i__1 = *lwork - jw; dormhr_("R", "N", &jw, ns, &c__1, ns, &t[t_offset], ldt, &work[1], &v[v_offset], ldv, &work[jw + 1], &i__1, &info); } // // ==== Update vertical slab in H ==== // if (*wantt) { ltop = 1; } else { ltop = *ktop; } i__1 = kwtop - 1; i__2 = *nv; for (krow = ltop; i__2 < 0 ? krow >= i__1 : krow <= i__1; krow += i__2) { // Computing MIN i__3 = *nv, i__4 = kwtop - krow; kln = min(i__3,i__4); dgemm_("N", "N", &kln, &jw, &jw, &c_b18, &h__[krow + kwtop * h_dim1], ldh, &v[v_offset], ldv, &c_b17, &wv[wv_offset], ldwv); dlacpy_("A", &kln, &jw, &wv[wv_offset], ldwv, &h__[krow + kwtop * h_dim1], ldh); // L70: } // // ==== Update horizontal slab in H ==== // if (*wantt) { i__2 = *n; i__1 = *nh; for (kcol = *kbot + 1; i__1 < 0 ? kcol >= i__2 : kcol <= i__2; kcol += i__1) { // Computing MIN i__3 = *nh, i__4 = *n - kcol + 1; kln = min(i__3,i__4); dgemm_("C", "N", &jw, &kln, &jw, &c_b18, &v[v_offset], ldv, & h__[kwtop + kcol * h_dim1], ldh, &c_b17, &t[t_offset], ldt); dlacpy_("A", &jw, &kln, &t[t_offset], ldt, &h__[kwtop + kcol * h_dim1], ldh); // L80: } } // // ==== Update vertical slab in Z ==== // if (*wantz) { i__1 = *ihiz; i__2 = *nv; for (krow = *iloz; i__2 < 0 ? krow >= i__1 : krow <= i__1; krow += i__2) { // Computing MIN i__3 = *nv, i__4 = *ihiz - krow + 1; kln = min(i__3,i__4); dgemm_("N", "N", &kln, &jw, &jw, &c_b18, &z__[krow + kwtop * z_dim1], ldz, &v[v_offset], ldv, &c_b17, &wv[ wv_offset], ldwv); dlacpy_("A", &kln, &jw, &wv[wv_offset], ldwv, &z__[krow + kwtop * z_dim1], ldz); // L90: } } } // // ==== Return the number of deflations ... ==== // *nd = jw - *ns; // // ==== ... and the number of shifts. (Subtracting // . INFQR from the spike length takes care // . of the case of a rare QR failure while // . calculating eigenvalues of the deflation // . window.) ==== // *ns -= infqr; // // ==== Return optimal workspace. ==== // work[1] = (double) lwkopt; // // ==== End of DLAQR3 ==== // return 0; } // dlaqr3_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DLAQR4 computes the eigenvalues of a Hessenberg matrix, and optionally the matrices from the Schur decomposition. // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DLAQR4 + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DLAQR4( WANTT, WANTZ, N, ILO, IHI, H, LDH, WR, WI, // ILOZ, IHIZ, Z, LDZ, WORK, LWORK, INFO ) // // .. Scalar Arguments .. // INTEGER IHI, IHIZ, ILO, ILOZ, INFO, LDH, LDZ, LWORK, N // LOGICAL WANTT, WANTZ // .. // .. Array Arguments .. // DOUBLE PRECISION H( LDH, * ), WI( * ), WORK( * ), WR( * ), // $ Z( LDZ, * ) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> DLAQR4 implements one level of recursion for DLAQR0. //> It is a complete implementation of the small bulge multi-shift //> QR algorithm. It may be called by DLAQR0 and, for large enough //> deflation window size, it may be called by DLAQR3. This //> subroutine is identical to DLAQR0 except that it calls DLAQR2 //> instead of DLAQR3. //> //> DLAQR4 computes the eigenvalues of a Hessenberg matrix H //> and, optionally, the matrices T and Z from the Schur decomposition //> H = Z T Z**T, where T is an upper quasi-triangular matrix (the //> Schur form), and Z is the orthogonal matrix of Schur vectors. //> //> Optionally Z may be postmultiplied into an input orthogonal //> matrix Q so that this routine can give the Schur factorization //> of a matrix A which has been reduced to the Hessenberg form H //> by the orthogonal matrix Q: A = Q*H*Q**T = (QZ)*T*(QZ)**T. //> \endverbatim // // Arguments: // ========== // //> \param[in] WANTT //> \verbatim //> WANTT is LOGICAL //> = .TRUE. : the full Schur form T is required; //> = .FALSE.: only eigenvalues are required. //> \endverbatim //> //> \param[in] WANTZ //> \verbatim //> WANTZ is LOGICAL //> = .TRUE. : the matrix of Schur vectors Z is required; //> = .FALSE.: Schur vectors are not required. //> \endverbatim //> //> \param[in] N //> \verbatim //> N is INTEGER //> The order of the matrix H. N >= 0. //> \endverbatim //> //> \param[in] ILO //> \verbatim //> ILO is INTEGER //> \endverbatim //> //> \param[in] IHI //> \verbatim //> IHI is INTEGER //> It is assumed that H is already upper triangular in rows //> and columns 1:ILO-1 and IHI+1:N and, if ILO > 1, //> H(ILO,ILO-1) is zero. ILO and IHI are normally set by a //> previous call to DGEBAL, and then passed to DGEHRD when the //> matrix output by DGEBAL is reduced to Hessenberg form. //> Otherwise, ILO and IHI should be set to 1 and N, //> respectively. If N > 0, then 1 <= ILO <= IHI <= N. //> If N = 0, then ILO = 1 and IHI = 0. //> \endverbatim //> //> \param[in,out] H //> \verbatim //> H is DOUBLE PRECISION array, dimension (LDH,N) //> On entry, the upper Hessenberg matrix H. //> On exit, if INFO = 0 and WANTT is .TRUE., then H contains //> the upper quasi-triangular matrix T from the Schur //> decomposition (the Schur form); 2-by-2 diagonal blocks //> (corresponding to complex conjugate pairs of eigenvalues) //> are returned in standard form, with H(i,i) = H(i+1,i+1) //> and H(i+1,i)*H(i,i+1) < 0. If INFO = 0 and WANTT is //> .FALSE., then the contents of H are unspecified on exit. //> (The output value of H when INFO > 0 is given under the //> description of INFO below.) //> //> This subroutine may explicitly set H(i,j) = 0 for i > j and //> j = 1, 2, ... ILO-1 or j = IHI+1, IHI+2, ... N. //> \endverbatim //> //> \param[in] LDH //> \verbatim //> LDH is INTEGER //> The leading dimension of the array H. LDH >= max(1,N). //> \endverbatim //> //> \param[out] WR //> \verbatim //> WR is DOUBLE PRECISION array, dimension (IHI) //> \endverbatim //> //> \param[out] WI //> \verbatim //> WI is DOUBLE PRECISION array, dimension (IHI) //> The real and imaginary parts, respectively, of the computed //> eigenvalues of H(ILO:IHI,ILO:IHI) are stored in WR(ILO:IHI) //> and WI(ILO:IHI). If two eigenvalues are computed as a //> complex conjugate pair, they are stored in consecutive //> elements of WR and WI, say the i-th and (i+1)th, with //> WI(i) > 0 and WI(i+1) < 0. If WANTT is .TRUE., then //> the eigenvalues are stored in the same order as on the //> diagonal of the Schur form returned in H, with //> WR(i) = H(i,i) and, if H(i:i+1,i:i+1) is a 2-by-2 diagonal //> block, WI(i) = sqrt(-H(i+1,i)*H(i,i+1)) and //> WI(i+1) = -WI(i). //> \endverbatim //> //> \param[in] ILOZ //> \verbatim //> ILOZ is INTEGER //> \endverbatim //> //> \param[in] IHIZ //> \verbatim //> IHIZ is INTEGER //> Specify the rows of Z to which transformations must be //> applied if WANTZ is .TRUE.. //> 1 <= ILOZ <= ILO; IHI <= IHIZ <= N. //> \endverbatim //> //> \param[in,out] Z //> \verbatim //> Z is DOUBLE PRECISION array, dimension (LDZ,IHI) //> If WANTZ is .FALSE., then Z is not referenced. //> If WANTZ is .TRUE., then Z(ILO:IHI,ILOZ:IHIZ) is //> replaced by Z(ILO:IHI,ILOZ:IHIZ)*U where U is the //> orthogonal Schur factor of H(ILO:IHI,ILO:IHI). //> (The output value of Z when INFO > 0 is given under //> the description of INFO below.) //> \endverbatim //> //> \param[in] LDZ //> \verbatim //> LDZ is INTEGER //> The leading dimension of the array Z. if WANTZ is .TRUE. //> then LDZ >= MAX(1,IHIZ). Otherwise, LDZ >= 1. //> \endverbatim //> //> \param[out] WORK //> \verbatim //> WORK is DOUBLE PRECISION array, dimension LWORK //> On exit, if LWORK = -1, WORK(1) returns an estimate of //> the optimal value for LWORK. //> \endverbatim //> //> \param[in] LWORK //> \verbatim //> LWORK is INTEGER //> The dimension of the array WORK. LWORK >= max(1,N) //> is sufficient, but LWORK typically as large as 6*N may //> be required for optimal performance. A workspace query //> to determine the optimal workspace size is recommended. //> //> If LWORK = -1, then DLAQR4 does a workspace query. //> In this case, DLAQR4 checks the input parameters and //> estimates the optimal workspace size for the given //> values of N, ILO and IHI. The estimate is returned //> in WORK(1). No error message related to LWORK is //> issued by XERBLA. Neither H nor Z are accessed. //> \endverbatim //> //> \param[out] INFO //> \verbatim //> INFO is INTEGER //> = 0: successful exit //> > 0: if INFO = i, DLAQR4 failed to compute all of //> the eigenvalues. Elements 1:ilo-1 and i+1:n of WR //> and WI contain those eigenvalues which have been //> successfully computed. (Failures are rare.) //> //> If INFO > 0 and WANT is .FALSE., then on exit, //> the remaining unconverged eigenvalues are the eigen- //> values of the upper Hessenberg matrix rows and //> columns ILO through INFO of the final, output //> value of H. //> //> If INFO > 0 and WANTT is .TRUE., then on exit //> //> (*) (initial value of H)*U = U*(final value of H) //> //> where U is a orthogonal matrix. The final //> value of H is upper Hessenberg and triangular in //> rows and columns INFO+1 through IHI. //> //> If INFO > 0 and WANTZ is .TRUE., then on exit //> //> (final value of Z(ILO:IHI,ILOZ:IHIZ) //> = (initial value of Z(ILO:IHI,ILOZ:IHIZ)*U //> //> where U is the orthogonal matrix in (*) (regard- //> less of the value of WANTT.) //> //> If INFO > 0 and WANTZ is .FALSE., then Z is not //> accessed. //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date December 2016 // //> \ingroup doubleOTHERauxiliary // //> \par Contributors: // ================== //> //> Karen Braman and Ralph Byers, Department of Mathematics, //> University of Kansas, USA // //> \par References: // ================ //> //> K. Braman, R. Byers and R. Mathias, The Multi-Shift QR //> Algorithm Part I: Maintaining Well Focused Shifts, and Level 3 //> Performance, SIAM Journal of Matrix Analysis, volume 23, pages //> 929--947, 2002. //> \n //> K. Braman, R. Byers and R. Mathias, The Multi-Shift QR //> Algorithm Part II: Aggressive Early Deflation, SIAM Journal //> of Matrix Analysis, volume 23, pages 948--973, 2002. //> // ===================================================================== /* Subroutine */ int dlaqr4_(int *wantt, int *wantz, int *n, int *ilo, int * ihi, double *h__, int *ldh, double *wr, double *wi, int *iloz, int * ihiz, double *z__, int *ldz, double *work, int *lwork, int *info) { // Table of constant values int c__13 = 13; int c__15 = 15; int c_n1 = -1; int c__12 = 12; int c__14 = 14; int c__16 = 16; int c_false = FALSE_; int c__1 = 1; int c__3 = 3; // System generated locals int h_dim1, h_offset, z_dim1, z_offset, i__1, i__2, i__3, i__4, i__5; double d__1, d__2, d__3, d__4; // Local variables int i__, k; double aa, bb, cc, dd; int ld; double cs; int nh, it, ks, kt; double sn; int ku, kv, ls, ns; double ss; int nw, inf, kdu, nho, nve, kwh, nsr, nwr, kwv, ndec, ndfl, kbot, nmin; double swap; int ktop; double zdum[1] /* was [1][1] */; int kacc22, itmax, nsmax, nwmax, kwtop; extern /* Subroutine */ int dlaqr2_(int *, int *, int *, int *, int *, int *, double *, int *, int *, int *, double *, int *, int *, int *, double *, double *, double *, int *, int *, double *, int *, int *, double *, int *, double *, int *), dlanv2_(double *, double *, double *, double *, double *, double *, double *, double *, double *, double *), dlaqr5_(int *, int *, int *, int *, int *, int *, int *, double *, double *, double *, int *, int *, int *, double *, int *, double *, int *, double *, int *, int *, double *, int *, int *, double *, int *); int nibble; extern /* Subroutine */ int dlahqr_(int *, int *, int *, int *, int *, double *, int *, double *, double *, int *, int *, double *, int * , int *), dlacpy_(char *, int *, int *, double *, int *, double *, int *); extern int ilaenv_(int *, char *, char *, int *, int *, int *, int *); char jbcmpz[2+1]={'\0'}; int nwupbd; int sorted; int lwkopt; // // -- LAPACK auxiliary routine (version 3.7.0) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // December 2016 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // // ================================================================ // .. Parameters .. // // ==== Matrices of order NTINY or smaller must be processed by // . DLAHQR because of insufficient subdiagonal scratch space. // . (This is a hard limit.) ==== // // ==== Exceptional deflation windows: try to cure rare // . slow convergence by varying the size of the // . deflation window after KEXNW iterations. ==== // // ==== Exceptional shifts: try to cure rare slow convergence // . with ad-hoc exceptional shifts every KEXSH iterations. // . ==== // // ==== The constants WILK1 and WILK2 are used to form the // . exceptional shifts. ==== // .. // .. Local Scalars .. // .. // .. External Functions .. // .. // .. Local Arrays .. // .. // .. External Subroutines .. // .. // .. Intrinsic Functions .. // .. // .. Executable Statements .. // Parameter adjustments h_dim1 = *ldh; h_offset = 1 + h_dim1; h__ -= h_offset; --wr; --wi; z_dim1 = *ldz; z_offset = 1 + z_dim1; z__ -= z_offset; --work; // Function Body *info = 0; // // ==== Quick return for N = 0: nothing to do. ==== // if (*n == 0) { work[1] = 1.; return 0; } if (*n <= 11) { // // ==== Tiny matrices must use DLAHQR. ==== // lwkopt = 1; if (*lwork != -1) { dlahqr_(wantt, wantz, n, ilo, ihi, &h__[h_offset], ldh, &wr[1], & wi[1], iloz, ihiz, &z__[z_offset], ldz, info); } } else { // // ==== Use small bulge multi-shift QR with aggressive early // . deflation on larger-than-tiny matrices. ==== // // ==== Hope for the best. ==== // *info = 0; // // ==== Set up job flags for ILAENV. ==== // if (*wantt) { *(unsigned char *)jbcmpz = 'S'; } else { *(unsigned char *)jbcmpz = 'E'; } if (*wantz) { *(unsigned char *)&jbcmpz[1] = 'V'; } else { *(unsigned char *)&jbcmpz[1] = 'N'; } // // ==== NWR = recommended deflation window size. At this // . point, N .GT. NTINY = 11, so there is enough // . subdiagonal workspace for NWR.GE.2 as required. // . (In fact, there is enough subdiagonal space for // . NWR.GE.3.) ==== // nwr = ilaenv_(&c__13, "DLAQR4", jbcmpz, n, ilo, ihi, lwork); nwr = max(2,nwr); // Computing MIN i__1 = *ihi - *ilo + 1, i__2 = (*n - 1) / 3, i__1 = min(i__1,i__2); nwr = min(i__1,nwr); // // ==== NSR = recommended number of simultaneous shifts. // . At this point N .GT. NTINY = 11, so there is at // . enough subdiagonal workspace for NSR to be even // . and greater than or equal to two as required. ==== // nsr = ilaenv_(&c__15, "DLAQR4", jbcmpz, n, ilo, ihi, lwork); // Computing MIN i__1 = nsr, i__2 = (*n + 6) / 9, i__1 = min(i__1,i__2), i__2 = *ihi - *ilo; nsr = min(i__1,i__2); // Computing MAX i__1 = 2, i__2 = nsr - nsr % 2; nsr = max(i__1,i__2); // // ==== Estimate optimal workspace ==== // // ==== Workspace query call to DLAQR2 ==== // i__1 = nwr + 1; dlaqr2_(wantt, wantz, n, ilo, ihi, &i__1, &h__[h_offset], ldh, iloz, ihiz, &z__[z_offset], ldz, &ls, &ld, &wr[1], &wi[1], &h__[ h_offset], ldh, n, &h__[h_offset], ldh, n, &h__[h_offset], ldh, &work[1], &c_n1); // // ==== Optimal workspace = MAX(DLAQR5, DLAQR2) ==== // // Computing MAX i__1 = nsr * 3 / 2, i__2 = (int) work[1]; lwkopt = max(i__1,i__2); // // ==== Quick return in case of workspace query. ==== // if (*lwork == -1) { work[1] = (double) lwkopt; return 0; } // // ==== DLAHQR/DLAQR0 crossover point ==== // nmin = ilaenv_(&c__12, "DLAQR4", jbcmpz, n, ilo, ihi, lwork); nmin = max(11,nmin); // // ==== Nibble crossover point ==== // nibble = ilaenv_(&c__14, "DLAQR4", jbcmpz, n, ilo, ihi, lwork); nibble = max(0,nibble); // // ==== Accumulate reflections during ttswp? Use block // . 2-by-2 structure during matrix-matrix multiply? ==== // kacc22 = ilaenv_(&c__16, "DLAQR4", jbcmpz, n, ilo, ihi, lwork); kacc22 = max(0,kacc22); kacc22 = min(2,kacc22); // // ==== NWMAX = the largest possible deflation window for // . which there is sufficient workspace. ==== // // Computing MIN i__1 = (*n - 1) / 3, i__2 = *lwork / 2; nwmax = min(i__1,i__2); nw = nwmax; // // ==== NSMAX = the Largest number of simultaneous shifts // . for which there is sufficient workspace. ==== // // Computing MIN i__1 = (*n + 6) / 9, i__2 = (*lwork << 1) / 3; nsmax = min(i__1,i__2); nsmax -= nsmax % 2; // // ==== NDFL: an iteration count restarted at deflation. ==== // ndfl = 1; // // ==== ITMAX = iteration limit ==== // // Computing MAX i__1 = 10, i__2 = *ihi - *ilo + 1; itmax = max(i__1,i__2) * 30; // // ==== Last row and column in the active block ==== // kbot = *ihi; // // ==== Main Loop ==== // i__1 = itmax; for (it = 1; it <= i__1; ++it) { // // ==== Done when KBOT falls below ILO ==== // if (kbot < *ilo) { goto L90; } // // ==== Locate active block ==== // i__2 = *ilo + 1; for (k = kbot; k >= i__2; --k) { if (h__[k + (k - 1) * h_dim1] == 0.) { goto L20; } // L10: } k = *ilo; L20: ktop = k; // // ==== Select deflation window size: // . Typical Case: // . If possible and advisable, nibble the entire // . active block. If not, use size MIN(NWR,NWMAX) // . or MIN(NWR+1,NWMAX) depending upon which has // . the smaller corresponding subdiagonal entry // . (a heuristic). // . // . Exceptional Case: // . If there have been no deflations in KEXNW or // . more iterations, then vary the deflation window // . size. At first, because, larger windows are, // . in general, more powerful than smaller ones, // . rapidly increase the window to the maximum possible. // . Then, gradually reduce the window size. ==== // nh = kbot - ktop + 1; nwupbd = min(nh,nwmax); if (ndfl < 5) { nw = min(nwupbd,nwr); } else { // Computing MIN i__2 = nwupbd, i__3 = nw << 1; nw = min(i__2,i__3); } if (nw < nwmax) { if (nw >= nh - 1) { nw = nh; } else { kwtop = kbot - nw + 1; if ((d__1 = h__[kwtop + (kwtop - 1) * h_dim1], abs(d__1)) > (d__2 = h__[kwtop - 1 + (kwtop - 2) * h_dim1], abs(d__2))) { ++nw; } } } if (ndfl < 5) { ndec = -1; } else if (ndec >= 0 || nw >= nwupbd) { ++ndec; if (nw - ndec < 2) { ndec = 0; } nw -= ndec; } // // ==== Aggressive early deflation: // . split workspace under the subdiagonal into // . - an nw-by-nw work array V in the lower // . left-hand-corner, // . - an NW-by-at-least-NW-but-more-is-better // . (NW-by-NHO) horizontal work array along // . the bottom edge, // . - an at-least-NW-but-more-is-better (NHV-by-NW) // . vertical work array along the left-hand-edge. // . ==== // kv = *n - nw + 1; kt = nw + 1; nho = *n - nw - 1 - kt + 1; kwv = nw + 2; nve = *n - nw - kwv + 1; // // ==== Aggressive early deflation ==== // dlaqr2_(wantt, wantz, n, &ktop, &kbot, &nw, &h__[h_offset], ldh, iloz, ihiz, &z__[z_offset], ldz, &ls, &ld, &wr[1], &wi[1], &h__[kv + h_dim1], ldh, &nho, &h__[kv + kt * h_dim1], ldh, &nve, &h__[kwv + h_dim1], ldh, &work[1], lwork); // // ==== Adjust KBOT accounting for new deflations. ==== // kbot -= ld; // // ==== KS points to the shifts. ==== // ks = kbot - ls + 1; // // ==== Skip an expensive QR sweep if there is a (partly // . heuristic) reason to expect that many eigenvalues // . will deflate without it. Here, the QR sweep is // . skipped if many eigenvalues have just been deflated // . or if the remaining active block is small. // if (ld == 0 || ld * 100 <= nw * nibble && kbot - ktop + 1 > min( nmin,nwmax)) { // // ==== NS = nominal number of simultaneous shifts. // . This may be lowered (slightly) if DLAQR2 // . did not provide that many shifts. ==== // // Computing MIN // Computing MAX i__4 = 2, i__5 = kbot - ktop; i__2 = min(nsmax,nsr), i__3 = max(i__4,i__5); ns = min(i__2,i__3); ns -= ns % 2; // // ==== If there have been no deflations // . in a multiple of KEXSH iterations, // . then try exceptional shifts. // . Otherwise use shifts provided by // . DLAQR2 above or from the eigenvalues // . of a trailing principal submatrix. ==== // if (ndfl % 6 == 0) { ks = kbot - ns + 1; // Computing MAX i__3 = ks + 1, i__4 = ktop + 2; i__2 = max(i__3,i__4); for (i__ = kbot; i__ >= i__2; i__ += -2) { ss = (d__1 = h__[i__ + (i__ - 1) * h_dim1], abs(d__1)) + (d__2 = h__[i__ - 1 + (i__ - 2) * h_dim1], abs(d__2)); aa = ss * .75 + h__[i__ + i__ * h_dim1]; bb = ss; cc = ss * -.4375; dd = aa; dlanv2_(&aa, &bb, &cc, &dd, &wr[i__ - 1], &wi[i__ - 1] , &wr[i__], &wi[i__], &cs, &sn); // L30: } if (ks == ktop) { wr[ks + 1] = h__[ks + 1 + (ks + 1) * h_dim1]; wi[ks + 1] = 0.; wr[ks] = wr[ks + 1]; wi[ks] = wi[ks + 1]; } } else { // // ==== Got NS/2 or fewer shifts? Use DLAHQR // . on a trailing principal submatrix to // . get more. (Since NS.LE.NSMAX.LE.(N+6)/9, // . there is enough space below the subdiagonal // . to fit an NS-by-NS scratch array.) ==== // if (kbot - ks + 1 <= ns / 2) { ks = kbot - ns + 1; kt = *n - ns + 1; dlacpy_("A", &ns, &ns, &h__[ks + ks * h_dim1], ldh, & h__[kt + h_dim1], ldh); dlahqr_(&c_false, &c_false, &ns, &c__1, &ns, &h__[kt + h_dim1], ldh, &wr[ks], &wi[ks], &c__1, & c__1, zdum, &c__1, &inf); ks += inf; // // ==== In case of a rare QR failure use // . eigenvalues of the trailing 2-by-2 // . principal submatrix. ==== // if (ks >= kbot) { aa = h__[kbot - 1 + (kbot - 1) * h_dim1]; cc = h__[kbot + (kbot - 1) * h_dim1]; bb = h__[kbot - 1 + kbot * h_dim1]; dd = h__[kbot + kbot * h_dim1]; dlanv2_(&aa, &bb, &cc, &dd, &wr[kbot - 1], &wi[ kbot - 1], &wr[kbot], &wi[kbot], &cs, &sn) ; ks = kbot - 1; } } if (kbot - ks + 1 > ns) { // // ==== Sort the shifts (Helps a little) // . Bubble sort keeps complex conjugate // . pairs together. ==== // sorted = FALSE_; i__2 = ks + 1; for (k = kbot; k >= i__2; --k) { if (sorted) { goto L60; } sorted = TRUE_; i__3 = k - 1; for (i__ = ks; i__ <= i__3; ++i__) { if ((d__1 = wr[i__], abs(d__1)) + (d__2 = wi[ i__], abs(d__2)) < (d__3 = wr[i__ + 1] , abs(d__3)) + (d__4 = wi[i__ + 1], abs(d__4))) { sorted = FALSE_; swap = wr[i__]; wr[i__] = wr[i__ + 1]; wr[i__ + 1] = swap; swap = wi[i__]; wi[i__] = wi[i__ + 1]; wi[i__ + 1] = swap; } // L40: } // L50: } L60: ; } // // ==== Shuffle shifts into pairs of real shifts // . and pairs of complex conjugate shifts // . assuming complex conjugate shifts are // . already adjacent to one another. (Yes, // . they are.) ==== // i__2 = ks + 2; for (i__ = kbot; i__ >= i__2; i__ += -2) { if (wi[i__] != -wi[i__ - 1]) { swap = wr[i__]; wr[i__] = wr[i__ - 1]; wr[i__ - 1] = wr[i__ - 2]; wr[i__ - 2] = swap; swap = wi[i__]; wi[i__] = wi[i__ - 1]; wi[i__ - 1] = wi[i__ - 2]; wi[i__ - 2] = swap; } // L70: } } // // ==== If there are only two shifts and both are // . real, then use only one. ==== // if (kbot - ks + 1 == 2) { if (wi[kbot] == 0.) { if ((d__1 = wr[kbot] - h__[kbot + kbot * h_dim1], abs( d__1)) < (d__2 = wr[kbot - 1] - h__[kbot + kbot * h_dim1], abs(d__2))) { wr[kbot - 1] = wr[kbot]; } else { wr[kbot] = wr[kbot - 1]; } } } // // ==== Use up to NS of the the smallest magnitude // . shifts. If there aren't NS shifts available, // . then use them all, possibly dropping one to // . make the number of shifts even. ==== // // Computing MIN i__2 = ns, i__3 = kbot - ks + 1; ns = min(i__2,i__3); ns -= ns % 2; ks = kbot - ns + 1; // // ==== Small-bulge multi-shift QR sweep: // . split workspace under the subdiagonal into // . - a KDU-by-KDU work array U in the lower // . left-hand-corner, // . - a KDU-by-at-least-KDU-but-more-is-better // . (KDU-by-NHo) horizontal work array WH along // . the bottom edge, // . - and an at-least-KDU-but-more-is-better-by-KDU // . (NVE-by-KDU) vertical work WV arrow along // . the left-hand-edge. ==== // kdu = ns * 3 - 3; ku = *n - kdu + 1; kwh = kdu + 1; nho = *n - kdu - 3 - (kdu + 1) + 1; kwv = kdu + 4; nve = *n - kdu - kwv + 1; // // ==== Small-bulge multi-shift QR sweep ==== // dlaqr5_(wantt, wantz, &kacc22, n, &ktop, &kbot, &ns, &wr[ks], &wi[ks], &h__[h_offset], ldh, iloz, ihiz, &z__[ z_offset], ldz, &work[1], &c__3, &h__[ku + h_dim1], ldh, &nve, &h__[kwv + h_dim1], ldh, &nho, &h__[ku + kwh * h_dim1], ldh); } // // ==== Note progress (or the lack of it). ==== // if (ld > 0) { ndfl = 1; } else { ++ndfl; } // // ==== End of main loop ==== // L80: } // // ==== Iteration limit exceeded. Set INFO to show where // . the problem occurred and exit. ==== // *info = kbot; L90: ; } // // ==== Return the optimal value of LWORK. ==== // work[1] = (double) lwkopt; // // ==== End of DLAQR4 ==== // return 0; } // dlaqr4_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DLAQR5 performs a single small-bulge multi-shift QR sweep. // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DLAQR5 + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DLAQR5( WANTT, WANTZ, KACC22, N, KTOP, KBOT, NSHFTS, // SR, SI, H, LDH, ILOZ, IHIZ, Z, LDZ, V, LDV, U, // LDU, NV, WV, LDWV, NH, WH, LDWH ) // // .. Scalar Arguments .. // INTEGER IHIZ, ILOZ, KACC22, KBOT, KTOP, LDH, LDU, LDV, // $ LDWH, LDWV, LDZ, N, NH, NSHFTS, NV // LOGICAL WANTT, WANTZ // .. // .. Array Arguments .. // DOUBLE PRECISION H( LDH, * ), SI( * ), SR( * ), U( LDU, * ), // $ V( LDV, * ), WH( LDWH, * ), WV( LDWV, * ), // $ Z( LDZ, * ) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> DLAQR5, called by DLAQR0, performs a //> single small-bulge multi-shift QR sweep. //> \endverbatim // // Arguments: // ========== // //> \param[in] WANTT //> \verbatim //> WANTT is LOGICAL //> WANTT = .true. if the quasi-triangular Schur factor //> is being computed. WANTT is set to .false. otherwise. //> \endverbatim //> //> \param[in] WANTZ //> \verbatim //> WANTZ is LOGICAL //> WANTZ = .true. if the orthogonal Schur factor is being //> computed. WANTZ is set to .false. otherwise. //> \endverbatim //> //> \param[in] KACC22 //> \verbatim //> KACC22 is INTEGER with value 0, 1, or 2. //> Specifies the computation mode of far-from-diagonal //> orthogonal updates. //> = 0: DLAQR5 does not accumulate reflections and does not //> use matrix-matrix multiply to update far-from-diagonal //> matrix entries. //> = 1: DLAQR5 accumulates reflections and uses matrix-matrix //> multiply to update the far-from-diagonal matrix entries. //> = 2: DLAQR5 accumulates reflections, uses matrix-matrix //> multiply to update the far-from-diagonal matrix entries, //> and takes advantage of 2-by-2 block structure during //> matrix multiplies. //> \endverbatim //> //> \param[in] N //> \verbatim //> N is INTEGER //> N is the order of the Hessenberg matrix H upon which this //> subroutine operates. //> \endverbatim //> //> \param[in] KTOP //> \verbatim //> KTOP is INTEGER //> \endverbatim //> //> \param[in] KBOT //> \verbatim //> KBOT is INTEGER //> These are the first and last rows and columns of an //> isolated diagonal block upon which the QR sweep is to be //> applied. It is assumed without a check that //> either KTOP = 1 or H(KTOP,KTOP-1) = 0 //> and //> either KBOT = N or H(KBOT+1,KBOT) = 0. //> \endverbatim //> //> \param[in] NSHFTS //> \verbatim //> NSHFTS is INTEGER //> NSHFTS gives the number of simultaneous shifts. NSHFTS //> must be positive and even. //> \endverbatim //> //> \param[in,out] SR //> \verbatim //> SR is DOUBLE PRECISION array, dimension (NSHFTS) //> \endverbatim //> //> \param[in,out] SI //> \verbatim //> SI is DOUBLE PRECISION array, dimension (NSHFTS) //> SR contains the real parts and SI contains the imaginary //> parts of the NSHFTS shifts of origin that define the //> multi-shift QR sweep. On output SR and SI may be //> reordered. //> \endverbatim //> //> \param[in,out] H //> \verbatim //> H is DOUBLE PRECISION array, dimension (LDH,N) //> On input H contains a Hessenberg matrix. On output a //> multi-shift QR sweep with shifts SR(J)+i*SI(J) is applied //> to the isolated diagonal block in rows and columns KTOP //> through KBOT. //> \endverbatim //> //> \param[in] LDH //> \verbatim //> LDH is INTEGER //> LDH is the leading dimension of H just as declared in the //> calling procedure. LDH >= MAX(1,N). //> \endverbatim //> //> \param[in] ILOZ //> \verbatim //> ILOZ is INTEGER //> \endverbatim //> //> \param[in] IHIZ //> \verbatim //> IHIZ is INTEGER //> Specify the rows of Z to which transformations must be //> applied if WANTZ is .TRUE.. 1 <= ILOZ <= IHIZ <= N //> \endverbatim //> //> \param[in,out] Z //> \verbatim //> Z is DOUBLE PRECISION array, dimension (LDZ,IHIZ) //> If WANTZ = .TRUE., then the QR Sweep orthogonal //> similarity transformation is accumulated into //> Z(ILOZ:IHIZ,ILOZ:IHIZ) from the right. //> If WANTZ = .FALSE., then Z is unreferenced. //> \endverbatim //> //> \param[in] LDZ //> \verbatim //> LDZ is INTEGER //> LDA is the leading dimension of Z just as declared in //> the calling procedure. LDZ >= N. //> \endverbatim //> //> \param[out] V //> \verbatim //> V is DOUBLE PRECISION array, dimension (LDV,NSHFTS/2) //> \endverbatim //> //> \param[in] LDV //> \verbatim //> LDV is INTEGER //> LDV is the leading dimension of V as declared in the //> calling procedure. LDV >= 3. //> \endverbatim //> //> \param[out] U //> \verbatim //> U is DOUBLE PRECISION array, dimension (LDU,3*NSHFTS-3) //> \endverbatim //> //> \param[in] LDU //> \verbatim //> LDU is INTEGER //> LDU is the leading dimension of U just as declared in the //> in the calling subroutine. LDU >= 3*NSHFTS-3. //> \endverbatim //> //> \param[in] NV //> \verbatim //> NV is INTEGER //> NV is the number of rows in WV agailable for workspace. //> NV >= 1. //> \endverbatim //> //> \param[out] WV //> \verbatim //> WV is DOUBLE PRECISION array, dimension (LDWV,3*NSHFTS-3) //> \endverbatim //> //> \param[in] LDWV //> \verbatim //> LDWV is INTEGER //> LDWV is the leading dimension of WV as declared in the //> in the calling subroutine. LDWV >= NV. //> \endverbatim // //> \param[in] NH //> \verbatim //> NH is INTEGER //> NH is the number of columns in array WH available for //> workspace. NH >= 1. //> \endverbatim //> //> \param[out] WH //> \verbatim //> WH is DOUBLE PRECISION array, dimension (LDWH,NH) //> \endverbatim //> //> \param[in] LDWH //> \verbatim //> LDWH is INTEGER //> Leading dimension of WH just as declared in the //> calling procedure. LDWH >= 3*NSHFTS-3. //> \endverbatim //> // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date June 2016 // //> \ingroup doubleOTHERauxiliary // //> \par Contributors: // ================== //> //> Karen Braman and Ralph Byers, Department of Mathematics, //> University of Kansas, USA // //> \par References: // ================ //> //> K. Braman, R. Byers and R. Mathias, The Multi-Shift QR //> Algorithm Part I: Maintaining Well Focused Shifts, and Level 3 //> Performance, SIAM Journal of Matrix Analysis, volume 23, pages //> 929--947, 2002. //> // ===================================================================== /* Subroutine */ int dlaqr5_(int *wantt, int *wantz, int *kacc22, int *n, int *ktop, int *kbot, int *nshfts, double *sr, double *si, double *h__, int *ldh, int *iloz, int *ihiz, double *z__, int *ldz, double *v, int *ldv, double *u, int *ldu, int *nv, double *wv, int *ldwv, int *nh, double *wh, int *ldwh) { // Table of constant values double c_b7 = 0.; double c_b8 = 1.; int c__3 = 3; int c__1 = 1; int c__2 = 2; // System generated locals int h_dim1, h_offset, u_dim1, u_offset, v_dim1, v_offset, wh_dim1, wh_offset, wv_dim1, wv_offset, z_dim1, z_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7; double d__1, d__2, d__3, d__4, d__5; // Local variables int i__, j, k, m, i2, j2, i4, j4, k1; double h11, h12, h21, h22; int m22, ns, nu; double vt[3], scl; int kdu, kms; double ulp; int knz, kzs; double tst1, tst2, beta; int blk22, bmp22; int mend, jcol, jlen, jbot, mbot; double swap; int jtop, jrow, mtop; double alpha; int accum; extern /* Subroutine */ int dgemm_(char *, char *, int *, int *, int *, double *, double *, int *, double *, int *, double *, double *, int *); int ndcol, incol, krcol, nbmps; extern /* Subroutine */ int dtrmm_(char *, char *, char *, char *, int *, int *, double *, double *, int *, double *, int *), dlaqr1_(int *, double *, int *, double *, double *, double *, double *, double * ), dlabad_(double *, double *); extern double dlamch_(char *); extern /* Subroutine */ int dlarfg_(int *, double *, double *, int *, double *), dlacpy_(char *, int *, int *, double *, int *, double * , int *); double safmin; extern /* Subroutine */ int dlaset_(char *, int *, int *, double *, double *, double *, int *); double safmax, refsum; int mstart; double smlnum; // // -- LAPACK auxiliary routine (version 3.7.1) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // June 2016 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // // ================================================================ // .. Parameters .. // .. // .. Local Scalars .. // .. // .. External Functions .. // .. // .. Intrinsic Functions .. // // .. // .. Local Arrays .. // .. // .. External Subroutines .. // .. // .. Executable Statements .. // // ==== If there are no shifts, then there is nothing to do. ==== // // Parameter adjustments --sr; --si; h_dim1 = *ldh; h_offset = 1 + h_dim1; h__ -= h_offset; z_dim1 = *ldz; z_offset = 1 + z_dim1; z__ -= z_offset; v_dim1 = *ldv; v_offset = 1 + v_dim1; v -= v_offset; u_dim1 = *ldu; u_offset = 1 + u_dim1; u -= u_offset; wv_dim1 = *ldwv; wv_offset = 1 + wv_dim1; wv -= wv_offset; wh_dim1 = *ldwh; wh_offset = 1 + wh_dim1; wh -= wh_offset; // Function Body if (*nshfts < 2) { return 0; } // // ==== If the active block is empty or 1-by-1, then there // . is nothing to do. ==== // if (*ktop >= *kbot) { return 0; } // // ==== Shuffle shifts into pairs of real shifts and pairs // . of complex conjugate shifts assuming complex // . conjugate shifts are already adjacent to one // . another. ==== // i__1 = *nshfts - 2; for (i__ = 1; i__ <= i__1; i__ += 2) { if (si[i__] != -si[i__ + 1]) { swap = sr[i__]; sr[i__] = sr[i__ + 1]; sr[i__ + 1] = sr[i__ + 2]; sr[i__ + 2] = swap; swap = si[i__]; si[i__] = si[i__ + 1]; si[i__ + 1] = si[i__ + 2]; si[i__ + 2] = swap; } // L10: } // // ==== NSHFTS is supposed to be even, but if it is odd, // . then simply reduce it by one. The shuffle above // . ensures that the dropped shift is real and that // . the remaining shifts are paired. ==== // ns = *nshfts - *nshfts % 2; // // ==== Machine constants for deflation ==== // safmin = dlamch_("SAFE MINIMUM"); safmax = 1. / safmin; dlabad_(&safmin, &safmax); ulp = dlamch_("PRECISION"); smlnum = safmin * ((double) (*n) / ulp); // // ==== Use accumulated reflections to update far-from-diagonal // . entries ? ==== // accum = *kacc22 == 1 || *kacc22 == 2; // // ==== If so, exploit the 2-by-2 block structure? ==== // blk22 = ns > 2 && *kacc22 == 2; // // ==== clear trash ==== // if (*ktop + 2 <= *kbot) { h__[*ktop + 2 + *ktop * h_dim1] = 0.; } // // ==== NBMPS = number of 2-shift bulges in the chain ==== // nbmps = ns / 2; // // ==== KDU = width of slab ==== // kdu = nbmps * 6 - 3; // // ==== Create and chase chains of NBMPS bulges ==== // i__1 = *kbot - 2; i__2 = nbmps * 3 - 2; for (incol = (1 - nbmps) * 3 + *ktop - 1; i__2 < 0 ? incol >= i__1 : incol <= i__1; incol += i__2) { ndcol = incol + kdu; if (accum) { dlaset_("ALL", &kdu, &kdu, &c_b7, &c_b8, &u[u_offset], ldu); } // // ==== Near-the-diagonal bulge chase. The following loop // . performs the near-the-diagonal part of a small bulge // . multi-shift QR sweep. Each 6*NBMPS-2 column diagonal // . chunk extends from column INCOL to column NDCOL // . (including both column INCOL and column NDCOL). The // . following loop chases a 3*NBMPS column long chain of // . NBMPS bulges 3*NBMPS-2 columns to the right. (INCOL // . may be less than KTOP and and NDCOL may be greater than // . KBOT indicating phantom columns from which to chase // . bulges before they are actually introduced or to which // . to chase bulges beyond column KBOT.) ==== // // Computing MIN i__4 = incol + nbmps * 3 - 3, i__5 = *kbot - 2; i__3 = min(i__4,i__5); for (krcol = incol; krcol <= i__3; ++krcol) { // // ==== Bulges number MTOP to MBOT are active double implicit // . shift bulges. There may or may not also be small // . 2-by-2 bulge, if there is room. The inactive bulges // . (if any) must wait until the active bulges have moved // . down the diagonal to make room. The phantom matrix // . paradigm described above helps keep track. ==== // // Computing MAX i__4 = 1, i__5 = (*ktop - 1 - krcol + 2) / 3 + 1; mtop = max(i__4,i__5); // Computing MIN i__4 = nbmps, i__5 = (*kbot - krcol) / 3; mbot = min(i__4,i__5); m22 = mbot + 1; bmp22 = mbot < nbmps && krcol + (m22 - 1) * 3 == *kbot - 2; // // ==== Generate reflections to chase the chain right // . one column. (The minimum value of K is KTOP-1.) ==== // i__4 = mbot; for (m = mtop; m <= i__4; ++m) { k = krcol + (m - 1) * 3; if (k == *ktop - 1) { dlaqr1_(&c__3, &h__[*ktop + *ktop * h_dim1], ldh, &sr[(m << 1) - 1], &si[(m << 1) - 1], &sr[m * 2], &si[m * 2], &v[m * v_dim1 + 1]); alpha = v[m * v_dim1 + 1]; dlarfg_(&c__3, &alpha, &v[m * v_dim1 + 2], &c__1, &v[m * v_dim1 + 1]); } else { beta = h__[k + 1 + k * h_dim1]; v[m * v_dim1 + 2] = h__[k + 2 + k * h_dim1]; v[m * v_dim1 + 3] = h__[k + 3 + k * h_dim1]; dlarfg_(&c__3, &beta, &v[m * v_dim1 + 2], &c__1, &v[m * v_dim1 + 1]); // // ==== A Bulge may collapse because of vigilant // . deflation or destructive underflow. In the // . underflow case, try the two-small-subdiagonals // . trick to try to reinflate the bulge. ==== // if (h__[k + 3 + k * h_dim1] != 0. || h__[k + 3 + (k + 1) * h_dim1] != 0. || h__[k + 3 + (k + 2) * h_dim1] == 0.) { // // ==== Typical case: not collapsed (yet). ==== // h__[k + 1 + k * h_dim1] = beta; h__[k + 2 + k * h_dim1] = 0.; h__[k + 3 + k * h_dim1] = 0.; } else { // // ==== Atypical case: collapsed. Attempt to // . reintroduce ignoring H(K+1,K) and H(K+2,K). // . If the fill resulting from the new // . reflector is too large, then abandon it. // . Otherwise, use the new one. ==== // dlaqr1_(&c__3, &h__[k + 1 + (k + 1) * h_dim1], ldh, & sr[(m << 1) - 1], &si[(m << 1) - 1], &sr[m * 2], &si[m * 2], vt); alpha = vt[0]; dlarfg_(&c__3, &alpha, &vt[1], &c__1, vt); refsum = vt[0] * (h__[k + 1 + k * h_dim1] + vt[1] * h__[k + 2 + k * h_dim1]); if ((d__1 = h__[k + 2 + k * h_dim1] - refsum * vt[1], abs(d__1)) + (d__2 = refsum * vt[2], abs(d__2) ) > ulp * ((d__3 = h__[k + k * h_dim1], abs( d__3)) + (d__4 = h__[k + 1 + (k + 1) * h_dim1] , abs(d__4)) + (d__5 = h__[k + 2 + (k + 2) * h_dim1], abs(d__5)))) { // // ==== Starting a new bulge here would // . create non-negligible fill. Use // . the old one with trepidation. ==== // h__[k + 1 + k * h_dim1] = beta; h__[k + 2 + k * h_dim1] = 0.; h__[k + 3 + k * h_dim1] = 0.; } else { // // ==== Stating a new bulge here would // . create only negligible fill. // . Replace the old reflector with // . the new one. ==== // h__[k + 1 + k * h_dim1] -= refsum; h__[k + 2 + k * h_dim1] = 0.; h__[k + 3 + k * h_dim1] = 0.; v[m * v_dim1 + 1] = vt[0]; v[m * v_dim1 + 2] = vt[1]; v[m * v_dim1 + 3] = vt[2]; } } } // L20: } // // ==== Generate a 2-by-2 reflection, if needed. ==== // k = krcol + (m22 - 1) * 3; if (bmp22) { if (k == *ktop - 1) { dlaqr1_(&c__2, &h__[k + 1 + (k + 1) * h_dim1], ldh, &sr[( m22 << 1) - 1], &si[(m22 << 1) - 1], &sr[m22 * 2], &si[m22 * 2], &v[m22 * v_dim1 + 1]); beta = v[m22 * v_dim1 + 1]; dlarfg_(&c__2, &beta, &v[m22 * v_dim1 + 2], &c__1, &v[m22 * v_dim1 + 1]); } else { beta = h__[k + 1 + k * h_dim1]; v[m22 * v_dim1 + 2] = h__[k + 2 + k * h_dim1]; dlarfg_(&c__2, &beta, &v[m22 * v_dim1 + 2], &c__1, &v[m22 * v_dim1 + 1]); h__[k + 1 + k * h_dim1] = beta; h__[k + 2 + k * h_dim1] = 0.; } } // // ==== Multiply H by reflections from the left ==== // if (accum) { jbot = min(ndcol,*kbot); } else if (*wantt) { jbot = *n; } else { jbot = *kbot; } i__4 = jbot; for (j = max(*ktop,krcol); j <= i__4; ++j) { // Computing MIN i__5 = mbot, i__6 = (j - krcol + 2) / 3; mend = min(i__5,i__6); i__5 = mend; for (m = mtop; m <= i__5; ++m) { k = krcol + (m - 1) * 3; refsum = v[m * v_dim1 + 1] * (h__[k + 1 + j * h_dim1] + v[ m * v_dim1 + 2] * h__[k + 2 + j * h_dim1] + v[m * v_dim1 + 3] * h__[k + 3 + j * h_dim1]); h__[k + 1 + j * h_dim1] -= refsum; h__[k + 2 + j * h_dim1] -= refsum * v[m * v_dim1 + 2]; h__[k + 3 + j * h_dim1] -= refsum * v[m * v_dim1 + 3]; // L30: } // L40: } if (bmp22) { k = krcol + (m22 - 1) * 3; // Computing MAX i__4 = k + 1; i__5 = jbot; for (j = max(i__4,*ktop); j <= i__5; ++j) { refsum = v[m22 * v_dim1 + 1] * (h__[k + 1 + j * h_dim1] + v[m22 * v_dim1 + 2] * h__[k + 2 + j * h_dim1]); h__[k + 1 + j * h_dim1] -= refsum; h__[k + 2 + j * h_dim1] -= refsum * v[m22 * v_dim1 + 2]; // L50: } } // // ==== Multiply H by reflections from the right. // . Delay filling in the last row until the // . vigilant deflation check is complete. ==== // if (accum) { jtop = max(*ktop,incol); } else if (*wantt) { jtop = 1; } else { jtop = *ktop; } i__5 = mbot; for (m = mtop; m <= i__5; ++m) { if (v[m * v_dim1 + 1] != 0.) { k = krcol + (m - 1) * 3; // Computing MIN i__6 = *kbot, i__7 = k + 3; i__4 = min(i__6,i__7); for (j = jtop; j <= i__4; ++j) { refsum = v[m * v_dim1 + 1] * (h__[j + (k + 1) * h_dim1] + v[m * v_dim1 + 2] * h__[j + (k + 2) * h_dim1] + v[m * v_dim1 + 3] * h__[j + (k + 3) * h_dim1]); h__[j + (k + 1) * h_dim1] -= refsum; h__[j + (k + 2) * h_dim1] -= refsum * v[m * v_dim1 + 2]; h__[j + (k + 3) * h_dim1] -= refsum * v[m * v_dim1 + 3]; // L60: } if (accum) { // // ==== Accumulate U. (If necessary, update Z later // . with with an efficient matrix-matrix // . multiply.) ==== // kms = k - incol; // Computing MAX i__4 = 1, i__6 = *ktop - incol; i__7 = kdu; for (j = max(i__4,i__6); j <= i__7; ++j) { refsum = v[m * v_dim1 + 1] * (u[j + (kms + 1) * u_dim1] + v[m * v_dim1 + 2] * u[j + (kms + 2) * u_dim1] + v[m * v_dim1 + 3] * u[j + (kms + 3) * u_dim1]); u[j + (kms + 1) * u_dim1] -= refsum; u[j + (kms + 2) * u_dim1] -= refsum * v[m * v_dim1 + 2]; u[j + (kms + 3) * u_dim1] -= refsum * v[m * v_dim1 + 3]; // L70: } } else if (*wantz) { // // ==== U is not accumulated, so update Z // . now by multiplying by reflections // . from the right. ==== // i__7 = *ihiz; for (j = *iloz; j <= i__7; ++j) { refsum = v[m * v_dim1 + 1] * (z__[j + (k + 1) * z_dim1] + v[m * v_dim1 + 2] * z__[j + (k + 2) * z_dim1] + v[m * v_dim1 + 3] * z__[ j + (k + 3) * z_dim1]); z__[j + (k + 1) * z_dim1] -= refsum; z__[j + (k + 2) * z_dim1] -= refsum * v[m * v_dim1 + 2]; z__[j + (k + 3) * z_dim1] -= refsum * v[m * v_dim1 + 3]; // L80: } } } // L90: } // // ==== Special case: 2-by-2 reflection (if needed) ==== // k = krcol + (m22 - 1) * 3; if (bmp22) { if (v[m22 * v_dim1 + 1] != 0.) { // Computing MIN i__7 = *kbot, i__4 = k + 3; i__5 = min(i__7,i__4); for (j = jtop; j <= i__5; ++j) { refsum = v[m22 * v_dim1 + 1] * (h__[j + (k + 1) * h_dim1] + v[m22 * v_dim1 + 2] * h__[j + (k + 2) * h_dim1]); h__[j + (k + 1) * h_dim1] -= refsum; h__[j + (k + 2) * h_dim1] -= refsum * v[m22 * v_dim1 + 2]; // L100: } if (accum) { kms = k - incol; // Computing MAX i__5 = 1, i__7 = *ktop - incol; i__4 = kdu; for (j = max(i__5,i__7); j <= i__4; ++j) { refsum = v[m22 * v_dim1 + 1] * (u[j + (kms + 1) * u_dim1] + v[m22 * v_dim1 + 2] * u[j + ( kms + 2) * u_dim1]); u[j + (kms + 1) * u_dim1] -= refsum; u[j + (kms + 2) * u_dim1] -= refsum * v[m22 * v_dim1 + 2]; // L110: } } else if (*wantz) { i__4 = *ihiz; for (j = *iloz; j <= i__4; ++j) { refsum = v[m22 * v_dim1 + 1] * (z__[j + (k + 1) * z_dim1] + v[m22 * v_dim1 + 2] * z__[j + ( k + 2) * z_dim1]); z__[j + (k + 1) * z_dim1] -= refsum; z__[j + (k + 2) * z_dim1] -= refsum * v[m22 * v_dim1 + 2]; // L120: } } } } // // ==== Vigilant deflation check ==== // mstart = mtop; if (krcol + (mstart - 1) * 3 < *ktop) { ++mstart; } mend = mbot; if (bmp22) { ++mend; } if (krcol == *kbot - 2) { ++mend; } i__4 = mend; for (m = mstart; m <= i__4; ++m) { // Computing MIN i__5 = *kbot - 1, i__7 = krcol + (m - 1) * 3; k = min(i__5,i__7); // // ==== The following convergence test requires that // . the tradition small-compared-to-nearby-diagonals // . criterion and the Ahues & Tisseur (LAWN 122, 1997) // . criteria both be satisfied. The latter improves // . accuracy in some examples. Falling back on an // . alternate convergence criterion when TST1 or TST2 // . is zero (as done here) is traditional but probably // . unnecessary. ==== // if (h__[k + 1 + k * h_dim1] != 0.) { tst1 = (d__1 = h__[k + k * h_dim1], abs(d__1)) + (d__2 = h__[k + 1 + (k + 1) * h_dim1], abs(d__2)); if (tst1 == 0.) { if (k >= *ktop + 1) { tst1 += (d__1 = h__[k + (k - 1) * h_dim1], abs( d__1)); } if (k >= *ktop + 2) { tst1 += (d__1 = h__[k + (k - 2) * h_dim1], abs( d__1)); } if (k >= *ktop + 3) { tst1 += (d__1 = h__[k + (k - 3) * h_dim1], abs( d__1)); } if (k <= *kbot - 2) { tst1 += (d__1 = h__[k + 2 + (k + 1) * h_dim1], abs(d__1)); } if (k <= *kbot - 3) { tst1 += (d__1 = h__[k + 3 + (k + 1) * h_dim1], abs(d__1)); } if (k <= *kbot - 4) { tst1 += (d__1 = h__[k + 4 + (k + 1) * h_dim1], abs(d__1)); } } // Computing MAX d__2 = smlnum, d__3 = ulp * tst1; if ((d__1 = h__[k + 1 + k * h_dim1], abs(d__1)) <= max( d__2,d__3)) { // Computing MAX d__3 = (d__1 = h__[k + 1 + k * h_dim1], abs(d__1)), d__4 = (d__2 = h__[k + (k + 1) * h_dim1], abs( d__2)); h12 = max(d__3,d__4); // Computing MIN d__3 = (d__1 = h__[k + 1 + k * h_dim1], abs(d__1)), d__4 = (d__2 = h__[k + (k + 1) * h_dim1], abs( d__2)); h21 = min(d__3,d__4); // Computing MAX d__3 = (d__1 = h__[k + 1 + (k + 1) * h_dim1], abs( d__1)), d__4 = (d__2 = h__[k + k * h_dim1] - h__[k + 1 + (k + 1) * h_dim1], abs(d__2)); h11 = max(d__3,d__4); // Computing MIN d__3 = (d__1 = h__[k + 1 + (k + 1) * h_dim1], abs( d__1)), d__4 = (d__2 = h__[k + k * h_dim1] - h__[k + 1 + (k + 1) * h_dim1], abs(d__2)); h22 = min(d__3,d__4); scl = h11 + h12; tst2 = h22 * (h11 / scl); // // Computing MAX d__1 = smlnum, d__2 = ulp * tst2; if (tst2 == 0. || h21 * (h12 / scl) <= max(d__1,d__2)) { h__[k + 1 + k * h_dim1] = 0.; } } } // L130: } // // ==== Fill in the last row of each bulge. ==== // // Computing MIN i__4 = nbmps, i__5 = (*kbot - krcol - 1) / 3; mend = min(i__4,i__5); i__4 = mend; for (m = mtop; m <= i__4; ++m) { k = krcol + (m - 1) * 3; refsum = v[m * v_dim1 + 1] * v[m * v_dim1 + 3] * h__[k + 4 + ( k + 3) * h_dim1]; h__[k + 4 + (k + 1) * h_dim1] = -refsum; h__[k + 4 + (k + 2) * h_dim1] = -refsum * v[m * v_dim1 + 2]; h__[k + 4 + (k + 3) * h_dim1] -= refsum * v[m * v_dim1 + 3]; // L140: } // // ==== End of near-the-diagonal bulge chase. ==== // // L150: } // // ==== Use U (if accumulated) to update far-from-diagonal // . entries in H. If required, use U to update Z as // . well. ==== // if (accum) { if (*wantt) { jtop = 1; jbot = *n; } else { jtop = *ktop; jbot = *kbot; } if (! blk22 || incol < *ktop || ndcol > *kbot || ns <= 2) { // // ==== Updates not exploiting the 2-by-2 block // . structure of U. K1 and NU keep track of // . the location and size of U in the special // . cases of introducing bulges and chasing // . bulges off the bottom. In these special // . cases and in case the number of shifts // . is NS = 2, there is no 2-by-2 block // . structure to exploit. ==== // // Computing MAX i__3 = 1, i__4 = *ktop - incol; k1 = max(i__3,i__4); // Computing MAX i__3 = 0, i__4 = ndcol - *kbot; nu = kdu - max(i__3,i__4) - k1 + 1; // // ==== Horizontal Multiply ==== // i__3 = jbot; i__4 = *nh; for (jcol = min(ndcol,*kbot) + 1; i__4 < 0 ? jcol >= i__3 : jcol <= i__3; jcol += i__4) { // Computing MIN i__5 = *nh, i__7 = jbot - jcol + 1; jlen = min(i__5,i__7); dgemm_("C", "N", &nu, &jlen, &nu, &c_b8, &u[k1 + k1 * u_dim1], ldu, &h__[incol + k1 + jcol * h_dim1], ldh, &c_b7, &wh[wh_offset], ldwh); dlacpy_("ALL", &nu, &jlen, &wh[wh_offset], ldwh, &h__[ incol + k1 + jcol * h_dim1], ldh); // L160: } // // ==== Vertical multiply ==== // i__4 = max(*ktop,incol) - 1; i__3 = *nv; for (jrow = jtop; i__3 < 0 ? jrow >= i__4 : jrow <= i__4; jrow += i__3) { // Computing MIN i__5 = *nv, i__7 = max(*ktop,incol) - jrow; jlen = min(i__5,i__7); dgemm_("N", "N", &jlen, &nu, &nu, &c_b8, &h__[jrow + ( incol + k1) * h_dim1], ldh, &u[k1 + k1 * u_dim1], ldu, &c_b7, &wv[wv_offset], ldwv); dlacpy_("ALL", &jlen, &nu, &wv[wv_offset], ldwv, &h__[ jrow + (incol + k1) * h_dim1], ldh); // L170: } // // ==== Z multiply (also vertical) ==== // if (*wantz) { i__3 = *ihiz; i__4 = *nv; for (jrow = *iloz; i__4 < 0 ? jrow >= i__3 : jrow <= i__3; jrow += i__4) { // Computing MIN i__5 = *nv, i__7 = *ihiz - jrow + 1; jlen = min(i__5,i__7); dgemm_("N", "N", &jlen, &nu, &nu, &c_b8, &z__[jrow + ( incol + k1) * z_dim1], ldz, &u[k1 + k1 * u_dim1], ldu, &c_b7, &wv[wv_offset], ldwv); dlacpy_("ALL", &jlen, &nu, &wv[wv_offset], ldwv, &z__[ jrow + (incol + k1) * z_dim1], ldz); // L180: } } } else { // // ==== Updates exploiting U's 2-by-2 block structure. // . (I2, I4, J2, J4 are the last rows and columns // . of the blocks.) ==== // i2 = (kdu + 1) / 2; i4 = kdu; j2 = i4 - i2; j4 = kdu; // // ==== KZS and KNZ deal with the band of zeros // . along the diagonal of one of the triangular // . blocks. ==== // kzs = j4 - j2 - (ns + 1); knz = ns + 1; // // ==== Horizontal multiply ==== // i__4 = jbot; i__3 = *nh; for (jcol = min(ndcol,*kbot) + 1; i__3 < 0 ? jcol >= i__4 : jcol <= i__4; jcol += i__3) { // Computing MIN i__5 = *nh, i__7 = jbot - jcol + 1; jlen = min(i__5,i__7); // // ==== Copy bottom of H to top+KZS of scratch ==== // (The first KZS rows get multiplied by zero.) ==== // dlacpy_("ALL", &knz, &jlen, &h__[incol + 1 + j2 + jcol * h_dim1], ldh, &wh[kzs + 1 + wh_dim1], ldwh); // // ==== Multiply by U21**T ==== // dlaset_("ALL", &kzs, &jlen, &c_b7, &c_b7, &wh[wh_offset], ldwh); dtrmm_("L", "U", "C", "N", &knz, &jlen, &c_b8, &u[j2 + 1 + (kzs + 1) * u_dim1], ldu, &wh[kzs + 1 + wh_dim1] , ldwh); // // ==== Multiply top of H by U11**T ==== // dgemm_("C", "N", &i2, &jlen, &j2, &c_b8, &u[u_offset], ldu, &h__[incol + 1 + jcol * h_dim1], ldh, &c_b8, &wh[wh_offset], ldwh); // // ==== Copy top of H to bottom of WH ==== // dlacpy_("ALL", &j2, &jlen, &h__[incol + 1 + jcol * h_dim1] , ldh, &wh[i2 + 1 + wh_dim1], ldwh); // // ==== Multiply by U21**T ==== // dtrmm_("L", "L", "C", "N", &j2, &jlen, &c_b8, &u[(i2 + 1) * u_dim1 + 1], ldu, &wh[i2 + 1 + wh_dim1], ldwh); // // ==== Multiply by U22 ==== // i__5 = i4 - i2; i__7 = j4 - j2; dgemm_("C", "N", &i__5, &jlen, &i__7, &c_b8, &u[j2 + 1 + ( i2 + 1) * u_dim1], ldu, &h__[incol + 1 + j2 + jcol * h_dim1], ldh, &c_b8, &wh[i2 + 1 + wh_dim1], ldwh); // // ==== Copy it back ==== // dlacpy_("ALL", &kdu, &jlen, &wh[wh_offset], ldwh, &h__[ incol + 1 + jcol * h_dim1], ldh); // L190: } // // ==== Vertical multiply ==== // i__3 = max(incol,*ktop) - 1; i__4 = *nv; for (jrow = jtop; i__4 < 0 ? jrow >= i__3 : jrow <= i__3; jrow += i__4) { // Computing MIN i__5 = *nv, i__7 = max(incol,*ktop) - jrow; jlen = min(i__5,i__7); // // ==== Copy right of H to scratch (the first KZS // . columns get multiplied by zero) ==== // dlacpy_("ALL", &jlen, &knz, &h__[jrow + (incol + 1 + j2) * h_dim1], ldh, &wv[(kzs + 1) * wv_dim1 + 1], ldwv) ; // // ==== Multiply by U21 ==== // dlaset_("ALL", &jlen, &kzs, &c_b7, &c_b7, &wv[wv_offset], ldwv); dtrmm_("R", "U", "N", "N", &jlen, &knz, &c_b8, &u[j2 + 1 + (kzs + 1) * u_dim1], ldu, &wv[(kzs + 1) * wv_dim1 + 1], ldwv); // // ==== Multiply by U11 ==== // dgemm_("N", "N", &jlen, &i2, &j2, &c_b8, &h__[jrow + ( incol + 1) * h_dim1], ldh, &u[u_offset], ldu, & c_b8, &wv[wv_offset], ldwv); // // ==== Copy left of H to right of scratch ==== // dlacpy_("ALL", &jlen, &j2, &h__[jrow + (incol + 1) * h_dim1], ldh, &wv[(i2 + 1) * wv_dim1 + 1], ldwv); // // ==== Multiply by U21 ==== // i__5 = i4 - i2; dtrmm_("R", "L", "N", "N", &jlen, &i__5, &c_b8, &u[(i2 + 1) * u_dim1 + 1], ldu, &wv[(i2 + 1) * wv_dim1 + 1] , ldwv); // // ==== Multiply by U22 ==== // i__5 = i4 - i2; i__7 = j4 - j2; dgemm_("N", "N", &jlen, &i__5, &i__7, &c_b8, &h__[jrow + ( incol + 1 + j2) * h_dim1], ldh, &u[j2 + 1 + (i2 + 1) * u_dim1], ldu, &c_b8, &wv[(i2 + 1) * wv_dim1 + 1], ldwv); // // ==== Copy it back ==== // dlacpy_("ALL", &jlen, &kdu, &wv[wv_offset], ldwv, &h__[ jrow + (incol + 1) * h_dim1], ldh); // L200: } // // ==== Multiply Z (also vertical) ==== // if (*wantz) { i__4 = *ihiz; i__3 = *nv; for (jrow = *iloz; i__3 < 0 ? jrow >= i__4 : jrow <= i__4; jrow += i__3) { // Computing MIN i__5 = *nv, i__7 = *ihiz - jrow + 1; jlen = min(i__5,i__7); // // ==== Copy right of Z to left of scratch (first // . KZS columns get multiplied by zero) ==== // dlacpy_("ALL", &jlen, &knz, &z__[jrow + (incol + 1 + j2) * z_dim1], ldz, &wv[(kzs + 1) * wv_dim1 + 1], ldwv); // // ==== Multiply by U12 ==== // dlaset_("ALL", &jlen, &kzs, &c_b7, &c_b7, &wv[ wv_offset], ldwv); dtrmm_("R", "U", "N", "N", &jlen, &knz, &c_b8, &u[j2 + 1 + (kzs + 1) * u_dim1], ldu, &wv[(kzs + 1) * wv_dim1 + 1], ldwv); // // ==== Multiply by U11 ==== // dgemm_("N", "N", &jlen, &i2, &j2, &c_b8, &z__[jrow + ( incol + 1) * z_dim1], ldz, &u[u_offset], ldu, &c_b8, &wv[wv_offset], ldwv); // // ==== Copy left of Z to right of scratch ==== // dlacpy_("ALL", &jlen, &j2, &z__[jrow + (incol + 1) * z_dim1], ldz, &wv[(i2 + 1) * wv_dim1 + 1], ldwv); // // ==== Multiply by U21 ==== // i__5 = i4 - i2; dtrmm_("R", "L", "N", "N", &jlen, &i__5, &c_b8, &u[( i2 + 1) * u_dim1 + 1], ldu, &wv[(i2 + 1) * wv_dim1 + 1], ldwv); // // ==== Multiply by U22 ==== // i__5 = i4 - i2; i__7 = j4 - j2; dgemm_("N", "N", &jlen, &i__5, &i__7, &c_b8, &z__[ jrow + (incol + 1 + j2) * z_dim1], ldz, &u[j2 + 1 + (i2 + 1) * u_dim1], ldu, &c_b8, &wv[(i2 + 1) * wv_dim1 + 1], ldwv); // // ==== Copy the result back to Z ==== // dlacpy_("ALL", &jlen, &kdu, &wv[wv_offset], ldwv, & z__[jrow + (incol + 1) * z_dim1], ldz); // L210: } } } } // L220: } // // ==== End of DLAQR5 ==== // return 0; } // dlaqr5_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DLARFX applies an elementary reflector to a general rectangular matrix, with loop unrolling when the reflector has order ≤ 10. // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DLARFX + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DLARFX( SIDE, M, N, V, TAU, C, LDC, WORK ) // // .. Scalar Arguments .. // CHARACTER SIDE // INTEGER LDC, M, N // DOUBLE PRECISION TAU // .. // .. Array Arguments .. // DOUBLE PRECISION C( LDC, * ), V( * ), WORK( * ) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> DLARFX applies a real elementary reflector H to a real m by n //> matrix C, from either the left or the right. H is represented in the //> form //> //> H = I - tau * v * v**T //> //> where tau is a real scalar and v is a real vector. //> //> If tau = 0, then H is taken to be the unit matrix //> //> This version uses inline code if H has order < 11. //> \endverbatim // // Arguments: // ========== // //> \param[in] SIDE //> \verbatim //> SIDE is CHARACTER*1 //> = 'L': form H * C //> = 'R': form C * H //> \endverbatim //> //> \param[in] M //> \verbatim //> M is INTEGER //> The number of rows of the matrix C. //> \endverbatim //> //> \param[in] N //> \verbatim //> N is INTEGER //> The number of columns of the matrix C. //> \endverbatim //> //> \param[in] V //> \verbatim //> V is DOUBLE PRECISION array, dimension (M) if SIDE = 'L' //> or (N) if SIDE = 'R' //> The vector v in the representation of H. //> \endverbatim //> //> \param[in] TAU //> \verbatim //> TAU is DOUBLE PRECISION //> The value tau in the representation of H. //> \endverbatim //> //> \param[in,out] C //> \verbatim //> C is DOUBLE PRECISION array, dimension (LDC,N) //> On entry, the m by n matrix C. //> On exit, C is overwritten by the matrix H * C if SIDE = 'L', //> or C * H if SIDE = 'R'. //> \endverbatim //> //> \param[in] LDC //> \verbatim //> LDC is INTEGER //> The leading dimension of the array C. LDC >= (1,M). //> \endverbatim //> //> \param[out] WORK //> \verbatim //> WORK is DOUBLE PRECISION array, dimension //> (N) if SIDE = 'L' //> or (M) if SIDE = 'R' //> WORK is not referenced if H has order < 11. //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date December 2016 // //> \ingroup doubleOTHERauxiliary // // ===================================================================== /* Subroutine */ int dlarfx_(char *side, int *m, int *n, double *v, double * tau, double *c__, int *ldc, double *work) { // Table of constant values int c__1 = 1; // System generated locals int c_dim1, c_offset, i__1; // Local variables int j; double t1, t2, t3, t4, t5, t6, t7, t8, t9, v1, v2, v3, v4, v5, v6, v7, v8, v9, t10, v10, sum; extern /* Subroutine */ int dlarf_(char *, int *, int *, double *, int *, double *, double *, int *, double *); extern int lsame_(char *, char *); // // -- LAPACK auxiliary routine (version 3.7.0) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // December 2016 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // // ===================================================================== // // .. Parameters .. // .. // .. Local Scalars .. // .. // .. External Functions .. // .. // .. External Subroutines .. // .. // .. Executable Statements .. // // Parameter adjustments --v; c_dim1 = *ldc; c_offset = 1 + c_dim1; c__ -= c_offset; --work; // Function Body if (*tau == 0.) { return 0; } if (lsame_(side, "L")) { // // Form H * C, where H has order m. // switch (*m) { case 1: goto L10; case 2: goto L30; case 3: goto L50; case 4: goto L70; case 5: goto L90; case 6: goto L110; case 7: goto L130; case 8: goto L150; case 9: goto L170; case 10: goto L190; } // // Code for general M // dlarf_(side, m, n, &v[1], &c__1, tau, &c__[c_offset], ldc, &work[1]); goto L410; L10: // // Special code for 1 x 1 Householder // t1 = 1. - *tau * v[1] * v[1]; i__1 = *n; for (j = 1; j <= i__1; ++j) { c__[j * c_dim1 + 1] = t1 * c__[j * c_dim1 + 1]; // L20: } goto L410; L30: // // Special code for 2 x 2 Householder // v1 = v[1]; t1 = *tau * v1; v2 = v[2]; t2 = *tau * v2; i__1 = *n; for (j = 1; j <= i__1; ++j) { sum = v1 * c__[j * c_dim1 + 1] + v2 * c__[j * c_dim1 + 2]; c__[j * c_dim1 + 1] -= sum * t1; c__[j * c_dim1 + 2] -= sum * t2; // L40: } goto L410; L50: // // Special code for 3 x 3 Householder // v1 = v[1]; t1 = *tau * v1; v2 = v[2]; t2 = *tau * v2; v3 = v[3]; t3 = *tau * v3; i__1 = *n; for (j = 1; j <= i__1; ++j) { sum = v1 * c__[j * c_dim1 + 1] + v2 * c__[j * c_dim1 + 2] + v3 * c__[j * c_dim1 + 3]; c__[j * c_dim1 + 1] -= sum * t1; c__[j * c_dim1 + 2] -= sum * t2; c__[j * c_dim1 + 3] -= sum * t3; // L60: } goto L410; L70: // // Special code for 4 x 4 Householder // v1 = v[1]; t1 = *tau * v1; v2 = v[2]; t2 = *tau * v2; v3 = v[3]; t3 = *tau * v3; v4 = v[4]; t4 = *tau * v4; i__1 = *n; for (j = 1; j <= i__1; ++j) { sum = v1 * c__[j * c_dim1 + 1] + v2 * c__[j * c_dim1 + 2] + v3 * c__[j * c_dim1 + 3] + v4 * c__[j * c_dim1 + 4]; c__[j * c_dim1 + 1] -= sum * t1; c__[j * c_dim1 + 2] -= sum * t2; c__[j * c_dim1 + 3] -= sum * t3; c__[j * c_dim1 + 4] -= sum * t4; // L80: } goto L410; L90: // // Special code for 5 x 5 Householder // v1 = v[1]; t1 = *tau * v1; v2 = v[2]; t2 = *tau * v2; v3 = v[3]; t3 = *tau * v3; v4 = v[4]; t4 = *tau * v4; v5 = v[5]; t5 = *tau * v5; i__1 = *n; for (j = 1; j <= i__1; ++j) { sum = v1 * c__[j * c_dim1 + 1] + v2 * c__[j * c_dim1 + 2] + v3 * c__[j * c_dim1 + 3] + v4 * c__[j * c_dim1 + 4] + v5 * c__[ j * c_dim1 + 5]; c__[j * c_dim1 + 1] -= sum * t1; c__[j * c_dim1 + 2] -= sum * t2; c__[j * c_dim1 + 3] -= sum * t3; c__[j * c_dim1 + 4] -= sum * t4; c__[j * c_dim1 + 5] -= sum * t5; // L100: } goto L410; L110: // // Special code for 6 x 6 Householder // v1 = v[1]; t1 = *tau * v1; v2 = v[2]; t2 = *tau * v2; v3 = v[3]; t3 = *tau * v3; v4 = v[4]; t4 = *tau * v4; v5 = v[5]; t5 = *tau * v5; v6 = v[6]; t6 = *tau * v6; i__1 = *n; for (j = 1; j <= i__1; ++j) { sum = v1 * c__[j * c_dim1 + 1] + v2 * c__[j * c_dim1 + 2] + v3 * c__[j * c_dim1 + 3] + v4 * c__[j * c_dim1 + 4] + v5 * c__[ j * c_dim1 + 5] + v6 * c__[j * c_dim1 + 6]; c__[j * c_dim1 + 1] -= sum * t1; c__[j * c_dim1 + 2] -= sum * t2; c__[j * c_dim1 + 3] -= sum * t3; c__[j * c_dim1 + 4] -= sum * t4; c__[j * c_dim1 + 5] -= sum * t5; c__[j * c_dim1 + 6] -= sum * t6; // L120: } goto L410; L130: // // Special code for 7 x 7 Householder // v1 = v[1]; t1 = *tau * v1; v2 = v[2]; t2 = *tau * v2; v3 = v[3]; t3 = *tau * v3; v4 = v[4]; t4 = *tau * v4; v5 = v[5]; t5 = *tau * v5; v6 = v[6]; t6 = *tau * v6; v7 = v[7]; t7 = *tau * v7; i__1 = *n; for (j = 1; j <= i__1; ++j) { sum = v1 * c__[j * c_dim1 + 1] + v2 * c__[j * c_dim1 + 2] + v3 * c__[j * c_dim1 + 3] + v4 * c__[j * c_dim1 + 4] + v5 * c__[ j * c_dim1 + 5] + v6 * c__[j * c_dim1 + 6] + v7 * c__[j * c_dim1 + 7]; c__[j * c_dim1 + 1] -= sum * t1; c__[j * c_dim1 + 2] -= sum * t2; c__[j * c_dim1 + 3] -= sum * t3; c__[j * c_dim1 + 4] -= sum * t4; c__[j * c_dim1 + 5] -= sum * t5; c__[j * c_dim1 + 6] -= sum * t6; c__[j * c_dim1 + 7] -= sum * t7; // L140: } goto L410; L150: // // Special code for 8 x 8 Householder // v1 = v[1]; t1 = *tau * v1; v2 = v[2]; t2 = *tau * v2; v3 = v[3]; t3 = *tau * v3; v4 = v[4]; t4 = *tau * v4; v5 = v[5]; t5 = *tau * v5; v6 = v[6]; t6 = *tau * v6; v7 = v[7]; t7 = *tau * v7; v8 = v[8]; t8 = *tau * v8; i__1 = *n; for (j = 1; j <= i__1; ++j) { sum = v1 * c__[j * c_dim1 + 1] + v2 * c__[j * c_dim1 + 2] + v3 * c__[j * c_dim1 + 3] + v4 * c__[j * c_dim1 + 4] + v5 * c__[ j * c_dim1 + 5] + v6 * c__[j * c_dim1 + 6] + v7 * c__[j * c_dim1 + 7] + v8 * c__[j * c_dim1 + 8]; c__[j * c_dim1 + 1] -= sum * t1; c__[j * c_dim1 + 2] -= sum * t2; c__[j * c_dim1 + 3] -= sum * t3; c__[j * c_dim1 + 4] -= sum * t4; c__[j * c_dim1 + 5] -= sum * t5; c__[j * c_dim1 + 6] -= sum * t6; c__[j * c_dim1 + 7] -= sum * t7; c__[j * c_dim1 + 8] -= sum * t8; // L160: } goto L410; L170: // // Special code for 9 x 9 Householder // v1 = v[1]; t1 = *tau * v1; v2 = v[2]; t2 = *tau * v2; v3 = v[3]; t3 = *tau * v3; v4 = v[4]; t4 = *tau * v4; v5 = v[5]; t5 = *tau * v5; v6 = v[6]; t6 = *tau * v6; v7 = v[7]; t7 = *tau * v7; v8 = v[8]; t8 = *tau * v8; v9 = v[9]; t9 = *tau * v9; i__1 = *n; for (j = 1; j <= i__1; ++j) { sum = v1 * c__[j * c_dim1 + 1] + v2 * c__[j * c_dim1 + 2] + v3 * c__[j * c_dim1 + 3] + v4 * c__[j * c_dim1 + 4] + v5 * c__[ j * c_dim1 + 5] + v6 * c__[j * c_dim1 + 6] + v7 * c__[j * c_dim1 + 7] + v8 * c__[j * c_dim1 + 8] + v9 * c__[j * c_dim1 + 9]; c__[j * c_dim1 + 1] -= sum * t1; c__[j * c_dim1 + 2] -= sum * t2; c__[j * c_dim1 + 3] -= sum * t3; c__[j * c_dim1 + 4] -= sum * t4; c__[j * c_dim1 + 5] -= sum * t5; c__[j * c_dim1 + 6] -= sum * t6; c__[j * c_dim1 + 7] -= sum * t7; c__[j * c_dim1 + 8] -= sum * t8; c__[j * c_dim1 + 9] -= sum * t9; // L180: } goto L410; L190: // // Special code for 10 x 10 Householder // v1 = v[1]; t1 = *tau * v1; v2 = v[2]; t2 = *tau * v2; v3 = v[3]; t3 = *tau * v3; v4 = v[4]; t4 = *tau * v4; v5 = v[5]; t5 = *tau * v5; v6 = v[6]; t6 = *tau * v6; v7 = v[7]; t7 = *tau * v7; v8 = v[8]; t8 = *tau * v8; v9 = v[9]; t9 = *tau * v9; v10 = v[10]; t10 = *tau * v10; i__1 = *n; for (j = 1; j <= i__1; ++j) { sum = v1 * c__[j * c_dim1 + 1] + v2 * c__[j * c_dim1 + 2] + v3 * c__[j * c_dim1 + 3] + v4 * c__[j * c_dim1 + 4] + v5 * c__[ j * c_dim1 + 5] + v6 * c__[j * c_dim1 + 6] + v7 * c__[j * c_dim1 + 7] + v8 * c__[j * c_dim1 + 8] + v9 * c__[j * c_dim1 + 9] + v10 * c__[j * c_dim1 + 10]; c__[j * c_dim1 + 1] -= sum * t1; c__[j * c_dim1 + 2] -= sum * t2; c__[j * c_dim1 + 3] -= sum * t3; c__[j * c_dim1 + 4] -= sum * t4; c__[j * c_dim1 + 5] -= sum * t5; c__[j * c_dim1 + 6] -= sum * t6; c__[j * c_dim1 + 7] -= sum * t7; c__[j * c_dim1 + 8] -= sum * t8; c__[j * c_dim1 + 9] -= sum * t9; c__[j * c_dim1 + 10] -= sum * t10; // L200: } goto L410; } else { // // Form C * H, where H has order n. // switch (*n) { case 1: goto L210; case 2: goto L230; case 3: goto L250; case 4: goto L270; case 5: goto L290; case 6: goto L310; case 7: goto L330; case 8: goto L350; case 9: goto L370; case 10: goto L390; } // // Code for general N // dlarf_(side, m, n, &v[1], &c__1, tau, &c__[c_offset], ldc, &work[1]); goto L410; L210: // // Special code for 1 x 1 Householder // t1 = 1. - *tau * v[1] * v[1]; i__1 = *m; for (j = 1; j <= i__1; ++j) { c__[j + c_dim1] = t1 * c__[j + c_dim1]; // L220: } goto L410; L230: // // Special code for 2 x 2 Householder // v1 = v[1]; t1 = *tau * v1; v2 = v[2]; t2 = *tau * v2; i__1 = *m; for (j = 1; j <= i__1; ++j) { sum = v1 * c__[j + c_dim1] + v2 * c__[j + (c_dim1 << 1)]; c__[j + c_dim1] -= sum * t1; c__[j + (c_dim1 << 1)] -= sum * t2; // L240: } goto L410; L250: // // Special code for 3 x 3 Householder // v1 = v[1]; t1 = *tau * v1; v2 = v[2]; t2 = *tau * v2; v3 = v[3]; t3 = *tau * v3; i__1 = *m; for (j = 1; j <= i__1; ++j) { sum = v1 * c__[j + c_dim1] + v2 * c__[j + (c_dim1 << 1)] + v3 * c__[j + c_dim1 * 3]; c__[j + c_dim1] -= sum * t1; c__[j + (c_dim1 << 1)] -= sum * t2; c__[j + c_dim1 * 3] -= sum * t3; // L260: } goto L410; L270: // // Special code for 4 x 4 Householder // v1 = v[1]; t1 = *tau * v1; v2 = v[2]; t2 = *tau * v2; v3 = v[3]; t3 = *tau * v3; v4 = v[4]; t4 = *tau * v4; i__1 = *m; for (j = 1; j <= i__1; ++j) { sum = v1 * c__[j + c_dim1] + v2 * c__[j + (c_dim1 << 1)] + v3 * c__[j + c_dim1 * 3] + v4 * c__[j + (c_dim1 << 2)]; c__[j + c_dim1] -= sum * t1; c__[j + (c_dim1 << 1)] -= sum * t2; c__[j + c_dim1 * 3] -= sum * t3; c__[j + (c_dim1 << 2)] -= sum * t4; // L280: } goto L410; L290: // // Special code for 5 x 5 Householder // v1 = v[1]; t1 = *tau * v1; v2 = v[2]; t2 = *tau * v2; v3 = v[3]; t3 = *tau * v3; v4 = v[4]; t4 = *tau * v4; v5 = v[5]; t5 = *tau * v5; i__1 = *m; for (j = 1; j <= i__1; ++j) { sum = v1 * c__[j + c_dim1] + v2 * c__[j + (c_dim1 << 1)] + v3 * c__[j + c_dim1 * 3] + v4 * c__[j + (c_dim1 << 2)] + v5 * c__[j + c_dim1 * 5]; c__[j + c_dim1] -= sum * t1; c__[j + (c_dim1 << 1)] -= sum * t2; c__[j + c_dim1 * 3] -= sum * t3; c__[j + (c_dim1 << 2)] -= sum * t4; c__[j + c_dim1 * 5] -= sum * t5; // L300: } goto L410; L310: // // Special code for 6 x 6 Householder // v1 = v[1]; t1 = *tau * v1; v2 = v[2]; t2 = *tau * v2; v3 = v[3]; t3 = *tau * v3; v4 = v[4]; t4 = *tau * v4; v5 = v[5]; t5 = *tau * v5; v6 = v[6]; t6 = *tau * v6; i__1 = *m; for (j = 1; j <= i__1; ++j) { sum = v1 * c__[j + c_dim1] + v2 * c__[j + (c_dim1 << 1)] + v3 * c__[j + c_dim1 * 3] + v4 * c__[j + (c_dim1 << 2)] + v5 * c__[j + c_dim1 * 5] + v6 * c__[j + c_dim1 * 6]; c__[j + c_dim1] -= sum * t1; c__[j + (c_dim1 << 1)] -= sum * t2; c__[j + c_dim1 * 3] -= sum * t3; c__[j + (c_dim1 << 2)] -= sum * t4; c__[j + c_dim1 * 5] -= sum * t5; c__[j + c_dim1 * 6] -= sum * t6; // L320: } goto L410; L330: // // Special code for 7 x 7 Householder // v1 = v[1]; t1 = *tau * v1; v2 = v[2]; t2 = *tau * v2; v3 = v[3]; t3 = *tau * v3; v4 = v[4]; t4 = *tau * v4; v5 = v[5]; t5 = *tau * v5; v6 = v[6]; t6 = *tau * v6; v7 = v[7]; t7 = *tau * v7; i__1 = *m; for (j = 1; j <= i__1; ++j) { sum = v1 * c__[j + c_dim1] + v2 * c__[j + (c_dim1 << 1)] + v3 * c__[j + c_dim1 * 3] + v4 * c__[j + (c_dim1 << 2)] + v5 * c__[j + c_dim1 * 5] + v6 * c__[j + c_dim1 * 6] + v7 * c__[ j + c_dim1 * 7]; c__[j + c_dim1] -= sum * t1; c__[j + (c_dim1 << 1)] -= sum * t2; c__[j + c_dim1 * 3] -= sum * t3; c__[j + (c_dim1 << 2)] -= sum * t4; c__[j + c_dim1 * 5] -= sum * t5; c__[j + c_dim1 * 6] -= sum * t6; c__[j + c_dim1 * 7] -= sum * t7; // L340: } goto L410; L350: // // Special code for 8 x 8 Householder // v1 = v[1]; t1 = *tau * v1; v2 = v[2]; t2 = *tau * v2; v3 = v[3]; t3 = *tau * v3; v4 = v[4]; t4 = *tau * v4; v5 = v[5]; t5 = *tau * v5; v6 = v[6]; t6 = *tau * v6; v7 = v[7]; t7 = *tau * v7; v8 = v[8]; t8 = *tau * v8; i__1 = *m; for (j = 1; j <= i__1; ++j) { sum = v1 * c__[j + c_dim1] + v2 * c__[j + (c_dim1 << 1)] + v3 * c__[j + c_dim1 * 3] + v4 * c__[j + (c_dim1 << 2)] + v5 * c__[j + c_dim1 * 5] + v6 * c__[j + c_dim1 * 6] + v7 * c__[ j + c_dim1 * 7] + v8 * c__[j + (c_dim1 << 3)]; c__[j + c_dim1] -= sum * t1; c__[j + (c_dim1 << 1)] -= sum * t2; c__[j + c_dim1 * 3] -= sum * t3; c__[j + (c_dim1 << 2)] -= sum * t4; c__[j + c_dim1 * 5] -= sum * t5; c__[j + c_dim1 * 6] -= sum * t6; c__[j + c_dim1 * 7] -= sum * t7; c__[j + (c_dim1 << 3)] -= sum * t8; // L360: } goto L410; L370: // // Special code for 9 x 9 Householder // v1 = v[1]; t1 = *tau * v1; v2 = v[2]; t2 = *tau * v2; v3 = v[3]; t3 = *tau * v3; v4 = v[4]; t4 = *tau * v4; v5 = v[5]; t5 = *tau * v5; v6 = v[6]; t6 = *tau * v6; v7 = v[7]; t7 = *tau * v7; v8 = v[8]; t8 = *tau * v8; v9 = v[9]; t9 = *tau * v9; i__1 = *m; for (j = 1; j <= i__1; ++j) { sum = v1 * c__[j + c_dim1] + v2 * c__[j + (c_dim1 << 1)] + v3 * c__[j + c_dim1 * 3] + v4 * c__[j + (c_dim1 << 2)] + v5 * c__[j + c_dim1 * 5] + v6 * c__[j + c_dim1 * 6] + v7 * c__[ j + c_dim1 * 7] + v8 * c__[j + (c_dim1 << 3)] + v9 * c__[ j + c_dim1 * 9]; c__[j + c_dim1] -= sum * t1; c__[j + (c_dim1 << 1)] -= sum * t2; c__[j + c_dim1 * 3] -= sum * t3; c__[j + (c_dim1 << 2)] -= sum * t4; c__[j + c_dim1 * 5] -= sum * t5; c__[j + c_dim1 * 6] -= sum * t6; c__[j + c_dim1 * 7] -= sum * t7; c__[j + (c_dim1 << 3)] -= sum * t8; c__[j + c_dim1 * 9] -= sum * t9; // L380: } goto L410; L390: // // Special code for 10 x 10 Householder // v1 = v[1]; t1 = *tau * v1; v2 = v[2]; t2 = *tau * v2; v3 = v[3]; t3 = *tau * v3; v4 = v[4]; t4 = *tau * v4; v5 = v[5]; t5 = *tau * v5; v6 = v[6]; t6 = *tau * v6; v7 = v[7]; t7 = *tau * v7; v8 = v[8]; t8 = *tau * v8; v9 = v[9]; t9 = *tau * v9; v10 = v[10]; t10 = *tau * v10; i__1 = *m; for (j = 1; j <= i__1; ++j) { sum = v1 * c__[j + c_dim1] + v2 * c__[j + (c_dim1 << 1)] + v3 * c__[j + c_dim1 * 3] + v4 * c__[j + (c_dim1 << 2)] + v5 * c__[j + c_dim1 * 5] + v6 * c__[j + c_dim1 * 6] + v7 * c__[ j + c_dim1 * 7] + v8 * c__[j + (c_dim1 << 3)] + v9 * c__[ j + c_dim1 * 9] + v10 * c__[j + c_dim1 * 10]; c__[j + c_dim1] -= sum * t1; c__[j + (c_dim1 << 1)] -= sum * t2; c__[j + c_dim1 * 3] -= sum * t3; c__[j + (c_dim1 << 2)] -= sum * t4; c__[j + c_dim1 * 5] -= sum * t5; c__[j + c_dim1 * 6] -= sum * t6; c__[j + c_dim1 * 7] -= sum * t7; c__[j + (c_dim1 << 3)] -= sum * t8; c__[j + c_dim1 * 9] -= sum * t9; c__[j + c_dim1 * 10] -= sum * t10; // L400: } goto L410; } L410: return 0; // // End of DLARFX // } // dlarfx_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DLASY2 solves the Sylvester matrix equation where the matrices are of order 1 or 2. // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DLASY2 + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DLASY2( LTRANL, LTRANR, ISGN, N1, N2, TL, LDTL, TR, // LDTR, B, LDB, SCALE, X, LDX, XNORM, INFO ) // // .. Scalar Arguments .. // LOGICAL LTRANL, LTRANR // INTEGER INFO, ISGN, LDB, LDTL, LDTR, LDX, N1, N2 // DOUBLE PRECISION SCALE, XNORM // .. // .. Array Arguments .. // DOUBLE PRECISION B( LDB, * ), TL( LDTL, * ), TR( LDTR, * ), // $ X( LDX, * ) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> DLASY2 solves for the N1 by N2 matrix X, 1 <= N1,N2 <= 2, in //> //> op(TL)*X + ISGN*X*op(TR) = SCALE*B, //> //> where TL is N1 by N1, TR is N2 by N2, B is N1 by N2, and ISGN = 1 or //> -1. op(T) = T or T**T, where T**T denotes the transpose of T. //> \endverbatim // // Arguments: // ========== // //> \param[in] LTRANL //> \verbatim //> LTRANL is LOGICAL //> On entry, LTRANL specifies the op(TL): //> = .FALSE., op(TL) = TL, //> = .TRUE., op(TL) = TL**T. //> \endverbatim //> //> \param[in] LTRANR //> \verbatim //> LTRANR is LOGICAL //> On entry, LTRANR specifies the op(TR): //> = .FALSE., op(TR) = TR, //> = .TRUE., op(TR) = TR**T. //> \endverbatim //> //> \param[in] ISGN //> \verbatim //> ISGN is INTEGER //> On entry, ISGN specifies the sign of the equation //> as described before. ISGN may only be 1 or -1. //> \endverbatim //> //> \param[in] N1 //> \verbatim //> N1 is INTEGER //> On entry, N1 specifies the order of matrix TL. //> N1 may only be 0, 1 or 2. //> \endverbatim //> //> \param[in] N2 //> \verbatim //> N2 is INTEGER //> On entry, N2 specifies the order of matrix TR. //> N2 may only be 0, 1 or 2. //> \endverbatim //> //> \param[in] TL //> \verbatim //> TL is DOUBLE PRECISION array, dimension (LDTL,2) //> On entry, TL contains an N1 by N1 matrix. //> \endverbatim //> //> \param[in] LDTL //> \verbatim //> LDTL is INTEGER //> The leading dimension of the matrix TL. LDTL >= max(1,N1). //> \endverbatim //> //> \param[in] TR //> \verbatim //> TR is DOUBLE PRECISION array, dimension (LDTR,2) //> On entry, TR contains an N2 by N2 matrix. //> \endverbatim //> //> \param[in] LDTR //> \verbatim //> LDTR is INTEGER //> The leading dimension of the matrix TR. LDTR >= max(1,N2). //> \endverbatim //> //> \param[in] B //> \verbatim //> B is DOUBLE PRECISION array, dimension (LDB,2) //> On entry, the N1 by N2 matrix B contains the right-hand //> side of the equation. //> \endverbatim //> //> \param[in] LDB //> \verbatim //> LDB is INTEGER //> The leading dimension of the matrix B. LDB >= max(1,N1). //> \endverbatim //> //> \param[out] SCALE //> \verbatim //> SCALE is DOUBLE PRECISION //> On exit, SCALE contains the scale factor. SCALE is chosen //> less than or equal to 1 to prevent the solution overflowing. //> \endverbatim //> //> \param[out] X //> \verbatim //> X is DOUBLE PRECISION array, dimension (LDX,2) //> On exit, X contains the N1 by N2 solution. //> \endverbatim //> //> \param[in] LDX //> \verbatim //> LDX is INTEGER //> The leading dimension of the matrix X. LDX >= max(1,N1). //> \endverbatim //> //> \param[out] XNORM //> \verbatim //> XNORM is DOUBLE PRECISION //> On exit, XNORM is the infinity-norm of the solution. //> \endverbatim //> //> \param[out] INFO //> \verbatim //> INFO is INTEGER //> On exit, INFO is set to //> 0: successful exit. //> 1: TL and TR have too close eigenvalues, so TL or //> TR is perturbed to get a nonsingular equation. //> NOTE: In the interests of speed, this routine does not //> check the inputs for errors. //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date June 2016 // //> \ingroup doubleSYauxiliary // // ===================================================================== /* Subroutine */ int dlasy2_(int *ltranl, int *ltranr, int *isgn, int *n1, int *n2, double *tl, int *ldtl, double *tr, int *ldtr, double *b, int *ldb, double *scale, double *x, int *ldx, double *xnorm, int *info) { // Table of constant values int c__4 = 4; int c__1 = 1; int c__16 = 16; int c__0 = 0; /* Initialized data */ static int locu12[4] = { 3,4,1,2 }; static int locl21[4] = { 2,1,4,3 }; static int locu22[4] = { 4,3,2,1 }; static int xswpiv[4] = { FALSE_,FALSE_,TRUE_,TRUE_ }; static int bswpiv[4] = { FALSE_,TRUE_,FALSE_,TRUE_ }; // System generated locals int b_dim1, b_offset, tl_dim1, tl_offset, tr_dim1, tr_offset, x_dim1, x_offset; double d__1, d__2, d__3, d__4, d__5, d__6, d__7, d__8; // Local variables int i__, j, k; double x2[2], l21, u11, u12; int ip, jp; double u22, t16[16] /* was [4][4] */, gam, bet, eps, sgn, tmp[4], tau1, btmp[4], smin; int ipiv; double temp; int jpiv[4]; double xmax; int ipsv, jpsv; int bswap; extern /* Subroutine */ int dcopy_(int *, double *, int *, double *, int * ), dswap_(int *, double *, int *, double *, int *); int xswap; extern double dlamch_(char *); extern int idamax_(int *, double *, int *); double smlnum; // // -- LAPACK auxiliary routine (version 3.7.0) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // June 2016 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // //===================================================================== // // .. Parameters .. // .. // .. Local Scalars .. // .. // .. Local Arrays .. // .. // .. External Functions .. // .. // .. External Subroutines .. // .. // .. Intrinsic Functions .. // .. // .. Data statements .. // Parameter adjustments tl_dim1 = *ldtl; tl_offset = 1 + tl_dim1; tl -= tl_offset; tr_dim1 = *ldtr; tr_offset = 1 + tr_dim1; tr -= tr_offset; b_dim1 = *ldb; b_offset = 1 + b_dim1; b -= b_offset; x_dim1 = *ldx; x_offset = 1 + x_dim1; x -= x_offset; // Function Body // .. // .. Executable Statements .. // // Do not check the input parameters for errors // *info = 0; // // Quick return if possible // if (*n1 == 0 || *n2 == 0) { return 0; } // // Set constants to control overflow // eps = dlamch_("P"); smlnum = dlamch_("S") / eps; sgn = (double) (*isgn); k = *n1 + *n1 + *n2 - 2; switch (k) { case 1: goto L10; case 2: goto L20; case 3: goto L30; case 4: goto L50; } // // 1 by 1: TL11*X + SGN*X*TR11 = B11 // L10: tau1 = tl[tl_dim1 + 1] + sgn * tr[tr_dim1 + 1]; bet = abs(tau1); if (bet <= smlnum) { tau1 = smlnum; bet = smlnum; *info = 1; } *scale = 1.; gam = (d__1 = b[b_dim1 + 1], abs(d__1)); if (smlnum * gam > bet) { *scale = 1. / gam; } x[x_dim1 + 1] = b[b_dim1 + 1] * *scale / tau1; *xnorm = (d__1 = x[x_dim1 + 1], abs(d__1)); return 0; // // 1 by 2: // TL11*[X11 X12] + ISGN*[X11 X12]*op[TR11 TR12] = [B11 B12] // [TR21 TR22] // L20: // // Computing MAX // Computing MAX d__7 = (d__1 = tl[tl_dim1 + 1], abs(d__1)), d__8 = (d__2 = tr[tr_dim1 + 1] , abs(d__2)), d__7 = max(d__7,d__8), d__8 = (d__3 = tr[(tr_dim1 << 1) + 1], abs(d__3)), d__7 = max(d__7,d__8), d__8 = (d__4 = tr[ tr_dim1 + 2], abs(d__4)), d__7 = max(d__7,d__8), d__8 = (d__5 = tr[(tr_dim1 << 1) + 2], abs(d__5)); d__6 = eps * max(d__7,d__8); smin = max(d__6,smlnum); tmp[0] = tl[tl_dim1 + 1] + sgn * tr[tr_dim1 + 1]; tmp[3] = tl[tl_dim1 + 1] + sgn * tr[(tr_dim1 << 1) + 2]; if (*ltranr) { tmp[1] = sgn * tr[tr_dim1 + 2]; tmp[2] = sgn * tr[(tr_dim1 << 1) + 1]; } else { tmp[1] = sgn * tr[(tr_dim1 << 1) + 1]; tmp[2] = sgn * tr[tr_dim1 + 2]; } btmp[0] = b[b_dim1 + 1]; btmp[1] = b[(b_dim1 << 1) + 1]; goto L40; // // 2 by 1: // op[TL11 TL12]*[X11] + ISGN* [X11]*TR11 = [B11] // [TL21 TL22] [X21] [X21] [B21] // L30: // Computing MAX // Computing MAX d__7 = (d__1 = tr[tr_dim1 + 1], abs(d__1)), d__8 = (d__2 = tl[tl_dim1 + 1] , abs(d__2)), d__7 = max(d__7,d__8), d__8 = (d__3 = tl[(tl_dim1 << 1) + 1], abs(d__3)), d__7 = max(d__7,d__8), d__8 = (d__4 = tl[ tl_dim1 + 2], abs(d__4)), d__7 = max(d__7,d__8), d__8 = (d__5 = tl[(tl_dim1 << 1) + 2], abs(d__5)); d__6 = eps * max(d__7,d__8); smin = max(d__6,smlnum); tmp[0] = tl[tl_dim1 + 1] + sgn * tr[tr_dim1 + 1]; tmp[3] = tl[(tl_dim1 << 1) + 2] + sgn * tr[tr_dim1 + 1]; if (*ltranl) { tmp[1] = tl[(tl_dim1 << 1) + 1]; tmp[2] = tl[tl_dim1 + 2]; } else { tmp[1] = tl[tl_dim1 + 2]; tmp[2] = tl[(tl_dim1 << 1) + 1]; } btmp[0] = b[b_dim1 + 1]; btmp[1] = b[b_dim1 + 2]; L40: // // Solve 2 by 2 system using complete pivoting. // Set pivots less than SMIN to SMIN. // ipiv = idamax_(&c__4, tmp, &c__1); u11 = tmp[ipiv - 1]; if (abs(u11) <= smin) { *info = 1; u11 = smin; } u12 = tmp[locu12[ipiv - 1] - 1]; l21 = tmp[locl21[ipiv - 1] - 1] / u11; u22 = tmp[locu22[ipiv - 1] - 1] - u12 * l21; xswap = xswpiv[ipiv - 1]; bswap = bswpiv[ipiv - 1]; if (abs(u22) <= smin) { *info = 1; u22 = smin; } if (bswap) { temp = btmp[1]; btmp[1] = btmp[0] - l21 * temp; btmp[0] = temp; } else { btmp[1] -= l21 * btmp[0]; } *scale = 1.; if (smlnum * 2. * abs(btmp[1]) > abs(u22) || smlnum * 2. * abs(btmp[0]) > abs(u11)) { // Computing MAX d__1 = abs(btmp[0]), d__2 = abs(btmp[1]); *scale = .5 / max(d__1,d__2); btmp[0] *= *scale; btmp[1] *= *scale; } x2[1] = btmp[1] / u22; x2[0] = btmp[0] / u11 - u12 / u11 * x2[1]; if (xswap) { temp = x2[1]; x2[1] = x2[0]; x2[0] = temp; } x[x_dim1 + 1] = x2[0]; if (*n1 == 1) { x[(x_dim1 << 1) + 1] = x2[1]; *xnorm = (d__1 = x[x_dim1 + 1], abs(d__1)) + (d__2 = x[(x_dim1 << 1) + 1], abs(d__2)); } else { x[x_dim1 + 2] = x2[1]; // Computing MAX d__3 = (d__1 = x[x_dim1 + 1], abs(d__1)), d__4 = (d__2 = x[x_dim1 + 2] , abs(d__2)); *xnorm = max(d__3,d__4); } return 0; // // 2 by 2: // op[TL11 TL12]*[X11 X12] +ISGN* [X11 X12]*op[TR11 TR12] = [B11 B12] // [TL21 TL22] [X21 X22] [X21 X22] [TR21 TR22] [B21 B22] // // Solve equivalent 4 by 4 system using complete pivoting. // Set pivots less than SMIN to SMIN. // L50: // Computing MAX d__5 = (d__1 = tr[tr_dim1 + 1], abs(d__1)), d__6 = (d__2 = tr[(tr_dim1 << 1) + 1], abs(d__2)), d__5 = max(d__5,d__6), d__6 = (d__3 = tr[ tr_dim1 + 2], abs(d__3)), d__5 = max(d__5,d__6), d__6 = (d__4 = tr[(tr_dim1 << 1) + 2], abs(d__4)); smin = max(d__5,d__6); // Computing MAX d__5 = smin, d__6 = (d__1 = tl[tl_dim1 + 1], abs(d__1)), d__5 = max(d__5, d__6), d__6 = (d__2 = tl[(tl_dim1 << 1) + 1], abs(d__2)), d__5 = max(d__5,d__6), d__6 = (d__3 = tl[tl_dim1 + 2], abs(d__3)), d__5 = max(d__5,d__6), d__6 = (d__4 = tl[(tl_dim1 << 1) + 2], abs(d__4)) ; smin = max(d__5,d__6); // Computing MAX d__1 = eps * smin; smin = max(d__1,smlnum); btmp[0] = 0.; dcopy_(&c__16, btmp, &c__0, t16, &c__1); t16[0] = tl[tl_dim1 + 1] + sgn * tr[tr_dim1 + 1]; t16[5] = tl[(tl_dim1 << 1) + 2] + sgn * tr[tr_dim1 + 1]; t16[10] = tl[tl_dim1 + 1] + sgn * tr[(tr_dim1 << 1) + 2]; t16[15] = tl[(tl_dim1 << 1) + 2] + sgn * tr[(tr_dim1 << 1) + 2]; if (*ltranl) { t16[4] = tl[tl_dim1 + 2]; t16[1] = tl[(tl_dim1 << 1) + 1]; t16[14] = tl[tl_dim1 + 2]; t16[11] = tl[(tl_dim1 << 1) + 1]; } else { t16[4] = tl[(tl_dim1 << 1) + 1]; t16[1] = tl[tl_dim1 + 2]; t16[14] = tl[(tl_dim1 << 1) + 1]; t16[11] = tl[tl_dim1 + 2]; } if (*ltranr) { t16[8] = sgn * tr[(tr_dim1 << 1) + 1]; t16[13] = sgn * tr[(tr_dim1 << 1) + 1]; t16[2] = sgn * tr[tr_dim1 + 2]; t16[7] = sgn * tr[tr_dim1 + 2]; } else { t16[8] = sgn * tr[tr_dim1 + 2]; t16[13] = sgn * tr[tr_dim1 + 2]; t16[2] = sgn * tr[(tr_dim1 << 1) + 1]; t16[7] = sgn * tr[(tr_dim1 << 1) + 1]; } btmp[0] = b[b_dim1 + 1]; btmp[1] = b[b_dim1 + 2]; btmp[2] = b[(b_dim1 << 1) + 1]; btmp[3] = b[(b_dim1 << 1) + 2]; // // Perform elimination // for (i__ = 1; i__ <= 3; ++i__) { xmax = 0.; for (ip = i__; ip <= 4; ++ip) { for (jp = i__; jp <= 4; ++jp) { if ((d__1 = t16[ip + (jp << 2) - 5], abs(d__1)) >= xmax) { xmax = (d__1 = t16[ip + (jp << 2) - 5], abs(d__1)); ipsv = ip; jpsv = jp; } // L60: } // L70: } if (ipsv != i__) { dswap_(&c__4, &t16[ipsv - 1], &c__4, &t16[i__ - 1], &c__4); temp = btmp[i__ - 1]; btmp[i__ - 1] = btmp[ipsv - 1]; btmp[ipsv - 1] = temp; } if (jpsv != i__) { dswap_(&c__4, &t16[(jpsv << 2) - 4], &c__1, &t16[(i__ << 2) - 4], &c__1); } jpiv[i__ - 1] = jpsv; if ((d__1 = t16[i__ + (i__ << 2) - 5], abs(d__1)) < smin) { *info = 1; t16[i__ + (i__ << 2) - 5] = smin; } for (j = i__ + 1; j <= 4; ++j) { t16[j + (i__ << 2) - 5] /= t16[i__ + (i__ << 2) - 5]; btmp[j - 1] -= t16[j + (i__ << 2) - 5] * btmp[i__ - 1]; for (k = i__ + 1; k <= 4; ++k) { t16[j + (k << 2) - 5] -= t16[j + (i__ << 2) - 5] * t16[i__ + ( k << 2) - 5]; // L80: } // L90: } // L100: } if (abs(t16[15]) < smin) { *info = 1; t16[15] = smin; } *scale = 1.; if (smlnum * 8. * abs(btmp[0]) > abs(t16[0]) || smlnum * 8. * abs(btmp[1]) > abs(t16[5]) || smlnum * 8. * abs(btmp[2]) > abs(t16[10]) || smlnum * 8. * abs(btmp[3]) > abs(t16[15])) { // Computing MAX d__1 = abs(btmp[0]), d__2 = abs(btmp[1]), d__1 = max(d__1,d__2), d__2 = abs(btmp[2]), d__1 = max(d__1,d__2), d__2 = abs(btmp[3]); *scale = .125 / max(d__1,d__2); btmp[0] *= *scale; btmp[1] *= *scale; btmp[2] *= *scale; btmp[3] *= *scale; } for (i__ = 1; i__ <= 4; ++i__) { k = 5 - i__; temp = 1. / t16[k + (k << 2) - 5]; tmp[k - 1] = btmp[k - 1] * temp; for (j = k + 1; j <= 4; ++j) { tmp[k - 1] -= temp * t16[k + (j << 2) - 5] * tmp[j - 1]; // L110: } // L120: } for (i__ = 1; i__ <= 3; ++i__) { if (jpiv[4 - i__ - 1] != 4 - i__) { temp = tmp[4 - i__ - 1]; tmp[4 - i__ - 1] = tmp[jpiv[4 - i__ - 1] - 1]; tmp[jpiv[4 - i__ - 1] - 1] = temp; } // L130: } x[x_dim1 + 1] = tmp[0]; x[x_dim1 + 2] = tmp[1]; x[(x_dim1 << 1) + 1] = tmp[2]; x[(x_dim1 << 1) + 2] = tmp[3]; // Computing MAX d__1 = abs(tmp[0]) + abs(tmp[2]), d__2 = abs(tmp[1]) + abs(tmp[3]); *xnorm = max(d__1,d__2); return 0; // // End of DLASY2 // } // dlasy2_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DORGHR // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DORGHR + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DORGHR( N, ILO, IHI, A, LDA, TAU, WORK, LWORK, INFO ) // // .. Scalar Arguments .. // INTEGER IHI, ILO, INFO, LDA, LWORK, N // .. // .. Array Arguments .. // DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> 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). //> \endverbatim // // Arguments: // ========== // //> \param[in] N //> \verbatim //> N is INTEGER //> The order of the matrix Q. N >= 0. //> \endverbatim //> //> \param[in] ILO //> \verbatim //> ILO is INTEGER //> \endverbatim //> //> \param[in] IHI //> \verbatim //> IHI is 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. //> \endverbatim //> //> \param[in,out] A //> \verbatim //> A is 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. //> \endverbatim //> //> \param[in] LDA //> \verbatim //> LDA is INTEGER //> The leading dimension of the array A. LDA >= max(1,N). //> \endverbatim //> //> \param[in] TAU //> \verbatim //> TAU is DOUBLE PRECISION array, dimension (N-1) //> TAU(i) must contain the scalar factor of the elementary //> reflector H(i), as returned by DGEHRD. //> \endverbatim //> //> \param[out] WORK //> \verbatim //> WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK)) //> On exit, if INFO = 0, WORK(1) returns the optimal LWORK. //> \endverbatim //> //> \param[in] LWORK //> \verbatim //> LWORK is 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. //> \endverbatim //> //> \param[out] INFO //> \verbatim //> INFO is INTEGER //> = 0: successful exit //> < 0: if INFO = -i, the i-th argument had an illegal value //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date December 2016 // //> \ingroup doubleOTHERcomputational // // ===================================================================== /* Subroutine */ int dorghr_(int *n, int *ilo, int *ihi, double *a, int *lda, double *tau, double *work, int *lwork, int *info) { // Table of constant values int c__1 = 1; int c_n1 = -1; // System generated locals int a_dim1, a_offset, i__1, i__2; // Local variables int i__, j, nb, nh, iinfo; extern /* Subroutine */ int xerbla_(char *, int *); extern int ilaenv_(int *, char *, char *, int *, int *, int *, int *); extern /* Subroutine */ int dorgqr_(int *, int *, int *, double *, int *, double *, double *, int *, int *); int lwkopt; int lquery; // // -- LAPACK computational routine (version 3.7.0) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // December 2016 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // // ===================================================================== // // .. 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] = (double) 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] = (double) lwkopt; return 0; // // End of DORGHR // } // dorghr_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DORMHR // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DORMHR + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DORMHR( SIDE, TRANS, M, N, ILO, IHI, A, LDA, TAU, C, // LDC, WORK, LWORK, INFO ) // // .. Scalar Arguments .. // CHARACTER SIDE, TRANS // INTEGER IHI, ILO, INFO, LDA, LDC, LWORK, M, N // .. // .. Array Arguments .. // DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * ) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> DORMHR overwrites the general real M-by-N matrix C with //> //> SIDE = 'L' SIDE = 'R' //> TRANS = 'N': Q * C C * Q //> TRANS = 'T': Q**T * C C * Q**T //> //> where Q is a real orthogonal matrix of order nq, with nq = m if //> SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of //> IHI-ILO elementary reflectors, as returned by DGEHRD: //> //> Q = H(ilo) H(ilo+1) . . . H(ihi-1). //> \endverbatim // // Arguments: // ========== // //> \param[in] SIDE //> \verbatim //> SIDE is CHARACTER*1 //> = 'L': apply Q or Q**T from the Left; //> = 'R': apply Q or Q**T from the Right. //> \endverbatim //> //> \param[in] TRANS //> \verbatim //> TRANS is CHARACTER*1 //> = 'N': No transpose, apply Q; //> = 'T': Transpose, apply Q**T. //> \endverbatim //> //> \param[in] M //> \verbatim //> M is INTEGER //> The number of rows of the matrix C. M >= 0. //> \endverbatim //> //> \param[in] N //> \verbatim //> N is INTEGER //> The number of columns of the matrix C. N >= 0. //> \endverbatim //> //> \param[in] ILO //> \verbatim //> ILO is INTEGER //> \endverbatim //> //> \param[in] IHI //> \verbatim //> IHI is 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). //> If SIDE = 'L', then 1 <= ILO <= IHI <= M, if M > 0, and //> ILO = 1 and IHI = 0, if M = 0; //> if SIDE = 'R', then 1 <= ILO <= IHI <= N, if N > 0, and //> ILO = 1 and IHI = 0, if N = 0. //> \endverbatim //> //> \param[in] A //> \verbatim //> A is DOUBLE PRECISION array, dimension //> (LDA,M) if SIDE = 'L' //> (LDA,N) if SIDE = 'R' //> The vectors which define the elementary reflectors, as //> returned by DGEHRD. //> \endverbatim //> //> \param[in] LDA //> \verbatim //> LDA is INTEGER //> The leading dimension of the array A. //> LDA >= max(1,M) if SIDE = 'L'; LDA >= max(1,N) if SIDE = 'R'. //> \endverbatim //> //> \param[in] TAU //> \verbatim //> TAU is DOUBLE PRECISION array, dimension //> (M-1) if SIDE = 'L' //> (N-1) if SIDE = 'R' //> TAU(i) must contain the scalar factor of the elementary //> reflector H(i), as returned by DGEHRD. //> \endverbatim //> //> \param[in,out] C //> \verbatim //> C is DOUBLE PRECISION array, dimension (LDC,N) //> On entry, the M-by-N matrix C. //> On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. //> \endverbatim //> //> \param[in] LDC //> \verbatim //> LDC is INTEGER //> The leading dimension of the array C. LDC >= max(1,M). //> \endverbatim //> //> \param[out] WORK //> \verbatim //> WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK)) //> On exit, if INFO = 0, WORK(1) returns the optimal LWORK. //> \endverbatim //> //> \param[in] LWORK //> \verbatim //> LWORK is INTEGER //> The dimension of the array WORK. //> If SIDE = 'L', LWORK >= max(1,N); //> if SIDE = 'R', LWORK >= max(1,M). //> For optimum performance LWORK >= N*NB if SIDE = 'L', and //> LWORK >= M*NB if SIDE = 'R', where NB is the optimal //> blocksize. //> //> If LWORK = -1, then a workspace query is assumed; the routine //> only calculates the optimal size of the WORK array, returns //> this value as the first entry of the WORK array, and no error //> message related to LWORK is issued by XERBLA. //> \endverbatim //> //> \param[out] INFO //> \verbatim //> INFO is INTEGER //> = 0: successful exit //> < 0: if INFO = -i, the i-th argument had an illegal value //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date December 2016 // //> \ingroup doubleOTHERcomputational // // ===================================================================== /* Subroutine */ int dormhr_(char *side, char *trans, int *m, int *n, int * ilo, int *ihi, double *a, int *lda, double *tau, double *c__, int * ldc, double *work, int *lwork, int *info) { // Table of constant values int c__1 = 1; int c_n1 = -1; int c__2 = 2; // System generated locals address a__1[2]; int a_dim1, a_offset, c_dim1, c_offset, i__1[2], i__2; char ch__1[2+1]={'\0'}; // Local variables int i1, i2, nb, mi, nh, ni, nq, nw; int left; extern int lsame_(char *, char *); int iinfo; extern /* Subroutine */ int xerbla_(char *, int *); extern int ilaenv_(int *, char *, char *, int *, int *, int *, int *); extern /* Subroutine */ int dormqr_(char *, char *, int *, int *, int *, double *, int *, double *, double *, int *, double *, int *, int * ); int lwkopt; int lquery; // // -- LAPACK computational routine (version 3.7.0) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // December 2016 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // // ===================================================================== // // .. Local Scalars .. // .. // .. External Functions .. // .. // .. External Subroutines .. // .. // .. Intrinsic Functions .. // .. // .. Executable Statements .. // // Test the input arguments // // Parameter adjustments a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; --tau; c_dim1 = *ldc; c_offset = 1 + c_dim1; c__ -= c_offset; --work; // Function Body *info = 0; nh = *ihi - *ilo; left = lsame_(side, "L"); lquery = *lwork == -1; // // NQ is the order of Q and NW is the minimum dimension of WORK // if (left) { nq = *m; nw = *n; } else { nq = *n; nw = *m; } if (! left && ! lsame_(side, "R")) { *info = -1; } else if (! lsame_(trans, "N") && ! lsame_(trans, "T")) { *info = -2; } else if (*m < 0) { *info = -3; } else if (*n < 0) { *info = -4; } else if (*ilo < 1 || *ilo > max(1,nq)) { *info = -5; } else if (*ihi < min(*ilo,nq) || *ihi > nq) { *info = -6; } else if (*lda < max(1,nq)) { *info = -8; } else if (*ldc < max(1,*m)) { *info = -11; } else if (*lwork < max(1,nw) && ! lquery) { *info = -13; } if (*info == 0) { if (left) { // Writing concatenation i__1[0] = 1, a__1[0] = side; i__1[1] = 1, a__1[1] = trans; s_cat(ch__1, a__1, i__1, &c__2); nb = ilaenv_(&c__1, "DORMQR", ch__1, &nh, n, &nh, &c_n1); } else { // Writing concatenation i__1[0] = 1, a__1[0] = side; i__1[1] = 1, a__1[1] = trans; s_cat(ch__1, a__1, i__1, &c__2); nb = ilaenv_(&c__1, "DORMQR", ch__1, m, &nh, &nh, &c_n1); } lwkopt = max(1,nw) * nb; work[1] = (double) lwkopt; } if (*info != 0) { i__2 = -(*info); xerbla_("DORMHR", &i__2); return 0; } else if (lquery) { return 0; } // // Quick return if possible // if (*m == 0 || *n == 0 || nh == 0) { work[1] = 1.; return 0; } if (left) { mi = nh; ni = *n; i1 = *ilo + 1; i2 = 1; } else { mi = *m; ni = nh; i1 = 1; i2 = *ilo + 1; } dormqr_(side, trans, &mi, &ni, &nh, &a[*ilo + 1 + *ilo * a_dim1], lda, & tau[*ilo], &c__[i1 + i2 * c_dim1], ldc, &work[1], lwork, &iinfo); work[1] = (double) lwkopt; return 0; // // End of DORMHR // } // dormhr_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DTREVC3 // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DTREVC3 + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DTREVC3( SIDE, HOWMNY, SELECT, N, T, LDT, VL, LDVL, // VR, LDVR, MM, M, WORK, LWORK, INFO ) // // .. Scalar Arguments .. // CHARACTER HOWMNY, SIDE // INTEGER INFO, LDT, LDVL, LDVR, LWORK, M, MM, N // .. // .. Array Arguments .. // LOGICAL SELECT( * ) // DOUBLE PRECISION T( LDT, * ), VL( LDVL, * ), VR( LDVR, * ), // $ WORK( * ) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> DTREVC3 computes some or all of the right and/or left eigenvectors of //> a real upper quasi-triangular matrix T. //> Matrices of this type are produced by the Schur factorization of //> a real general matrix: A = Q*T*Q**T, as computed by DHSEQR. //> //> The right eigenvector x and the left eigenvector y of T corresponding //> to an eigenvalue w are defined by: //> //> T*x = w*x, (y**T)*T = w*(y**T) //> //> where y**T denotes the transpose of the vector y. //> The eigenvalues are not input to this routine, but are read directly //> from the diagonal blocks of T. //> //> This routine returns the matrices X and/or Y of right and left //> eigenvectors of T, or the products Q*X and/or Q*Y, where Q is an //> input matrix. If Q is the orthogonal factor that reduces a matrix //> A to Schur form T, then Q*X and Q*Y are the matrices of right and //> left eigenvectors of A. //> //> This uses a Level 3 BLAS version of the back transformation. //> \endverbatim // // Arguments: // ========== // //> \param[in] SIDE //> \verbatim //> SIDE is CHARACTER*1 //> = 'R': compute right eigenvectors only; //> = 'L': compute left eigenvectors only; //> = 'B': compute both right and left eigenvectors. //> \endverbatim //> //> \param[in] HOWMNY //> \verbatim //> HOWMNY is CHARACTER*1 //> = 'A': compute all right and/or left eigenvectors; //> = 'B': compute all right and/or left eigenvectors, //> backtransformed by the matrices in VR and/or VL; //> = 'S': compute selected right and/or left eigenvectors, //> as indicated by the logical array SELECT. //> \endverbatim //> //> \param[in,out] SELECT //> \verbatim //> SELECT is LOGICAL array, dimension (N) //> If HOWMNY = 'S', SELECT specifies the eigenvectors to be //> computed. //> If w(j) is a real eigenvalue, the corresponding real //> eigenvector is computed if SELECT(j) is .TRUE.. //> If w(j) and w(j+1) are the real and imaginary parts of a //> complex eigenvalue, the corresponding complex eigenvector is //> computed if either SELECT(j) or SELECT(j+1) is .TRUE., and //> on exit SELECT(j) is set to .TRUE. and SELECT(j+1) is set to //> .FALSE.. //> Not referenced if HOWMNY = 'A' or 'B'. //> \endverbatim //> //> \param[in] N //> \verbatim //> N is INTEGER //> The order of the matrix T. N >= 0. //> \endverbatim //> //> \param[in] T //> \verbatim //> T is DOUBLE PRECISION array, dimension (LDT,N) //> The upper quasi-triangular matrix T in Schur canonical form. //> \endverbatim //> //> \param[in] LDT //> \verbatim //> LDT is INTEGER //> The leading dimension of the array T. LDT >= max(1,N). //> \endverbatim //> //> \param[in,out] VL //> \verbatim //> VL is DOUBLE PRECISION array, dimension (LDVL,MM) //> On entry, if SIDE = 'L' or 'B' and HOWMNY = 'B', VL must //> contain an N-by-N matrix Q (usually the orthogonal matrix Q //> of Schur vectors returned by DHSEQR). //> On exit, if SIDE = 'L' or 'B', VL contains: //> if HOWMNY = 'A', the matrix Y of left eigenvectors of T; //> if HOWMNY = 'B', the matrix Q*Y; //> if HOWMNY = 'S', the left eigenvectors of T specified by //> SELECT, stored consecutively in the columns //> of VL, in the same order as their //> eigenvalues. //> A complex eigenvector corresponding to a complex eigenvalue //> is stored in two consecutive columns, the first holding the //> real part, and the second the imaginary part. //> Not referenced if SIDE = 'R'. //> \endverbatim //> //> \param[in] LDVL //> \verbatim //> LDVL is INTEGER //> The leading dimension of the array VL. //> LDVL >= 1, and if SIDE = 'L' or 'B', LDVL >= N. //> \endverbatim //> //> \param[in,out] VR //> \verbatim //> VR is DOUBLE PRECISION array, dimension (LDVR,MM) //> On entry, if SIDE = 'R' or 'B' and HOWMNY = 'B', VR must //> contain an N-by-N matrix Q (usually the orthogonal matrix Q //> of Schur vectors returned by DHSEQR). //> On exit, if SIDE = 'R' or 'B', VR contains: //> if HOWMNY = 'A', the matrix X of right eigenvectors of T; //> if HOWMNY = 'B', the matrix Q*X; //> if HOWMNY = 'S', the right eigenvectors of T specified by //> SELECT, stored consecutively in the columns //> of VR, in the same order as their //> eigenvalues. //> A complex eigenvector corresponding to a complex eigenvalue //> is stored in two consecutive columns, the first holding the //> real part and the second the imaginary part. //> Not referenced if SIDE = 'L'. //> \endverbatim //> //> \param[in] LDVR //> \verbatim //> LDVR is INTEGER //> The leading dimension of the array VR. //> LDVR >= 1, and if SIDE = 'R' or 'B', LDVR >= N. //> \endverbatim //> //> \param[in] MM //> \verbatim //> MM is INTEGER //> The number of columns in the arrays VL and/or VR. MM >= M. //> \endverbatim //> //> \param[out] M //> \verbatim //> M is INTEGER //> The number of columns in the arrays VL and/or VR actually //> used to store the eigenvectors. //> If HOWMNY = 'A' or 'B', M is set to N. //> Each selected real eigenvector occupies one column and each //> selected complex eigenvector occupies two columns. //> \endverbatim //> //> \param[out] WORK //> \verbatim //> WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK)) //> \endverbatim //> //> \param[in] LWORK //> \verbatim //> LWORK is INTEGER //> The dimension of array WORK. LWORK >= max(1,3*N). //> For optimum performance, LWORK >= N + 2*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. //> \endverbatim //> //> \param[out] INFO //> \verbatim //> INFO is INTEGER //> = 0: successful exit //> < 0: if INFO = -i, the i-th argument had an illegal value //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date November 2017 // // @precisions fortran d -> s // //> \ingroup doubleOTHERcomputational // //> \par Further Details: // ===================== //> //> \verbatim //> //> The algorithm used in this program is basically backward (forward) //> substitution, with scaling to make the the code robust against //> possible overflow. //> //> Each eigenvector is normalized so that the element of largest //> magnitude has magnitude 1; here the magnitude of a complex number //> (x,y) is taken to be |x| + |y|. //> \endverbatim //> // ===================================================================== /* Subroutine */ int dtrevc3_(char *side, char *howmny, int *select, int *n, double *t, int *ldt, double *vl, int *ldvl, double *vr, int *ldvr, int *mm, int *m, double *work, int *lwork, int *info) { // Table of constant values int c__1 = 1; int c_n1 = -1; int c__2 = 2; double c_b17 = 0.; int c_false = FALSE_; double c_b29 = 1.; int c_true = TRUE_; // System generated locals address a__1[2]; int t_dim1, t_offset, vl_dim1, vl_offset, vr_dim1, vr_offset, i__1[2], i__2, i__3, i__4; double d__1, d__2, d__3, d__4; char ch__1[2+1]={'\0'}; // Local variables int i__, j, k; double x[4] /* was [2][2] */; int j1, j2, iscomplex[128], nb, ii, ki, ip, is, iv; double wi, wr; int ki2; double rec, ulp, beta, emax; int pair; extern double ddot_(int *, double *, int *, double *, int *); int allv; int ierr; double unfl, ovfl, smin; int over; double vmax; int jnxt; extern /* Subroutine */ int dscal_(int *, double *, double *, int *); double scale; extern /* Subroutine */ int dgemm_(char *, char *, int *, int *, int *, double *, double *, int *, double *, int *, double *, double *, int *); extern int lsame_(char *, char *); extern /* Subroutine */ int dgemv_(char *, int *, int *, double *, double *, int *, double *, int *, double *, double *, int *); double remax; extern /* Subroutine */ int dcopy_(int *, double *, int *, double *, int * ); int leftv, bothv; extern /* Subroutine */ int daxpy_(int *, double *, double *, int *, double *, int *); double vcrit; int somev; double xnorm; extern /* Subroutine */ int dlaln2_(int *, int *, int *, double *, double *, double *, int *, double *, double *, double *, int *, double *, double *, double *, int *, double *, double *, int *), dlabad_( double *, double *); extern double dlamch_(char *); extern int idamax_(int *, double *, int *); extern /* Subroutine */ int dlaset_(char *, int *, int *, double *, double *, double *, int *), xerbla_(char *, int *); extern int ilaenv_(int *, char *, char *, int *, int *, int *, int *); extern /* Subroutine */ int dlacpy_(char *, int *, int *, double *, int *, double *, int *); double bignum; int rightv; int maxwrk; double smlnum; int lquery; // // -- LAPACK computational routine (version 3.8.0) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // November 2017 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // // ===================================================================== // // .. Parameters .. // .. // .. Local Scalars .. // .. // .. External Functions .. // .. // .. External Subroutines .. // .. // .. Intrinsic Functions .. // .. // .. Local Arrays .. // .. // .. Executable Statements .. // // Decode and test the input parameters // // Parameter adjustments --select; t_dim1 = *ldt; t_offset = 1 + t_dim1; t -= t_offset; 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 bothv = lsame_(side, "B"); rightv = lsame_(side, "R") || bothv; leftv = lsame_(side, "L") || bothv; allv = lsame_(howmny, "A"); over = lsame_(howmny, "B"); somev = lsame_(howmny, "S"); *info = 0; // Writing concatenation i__1[0] = 1, a__1[0] = side; i__1[1] = 1, a__1[1] = howmny; s_cat(ch__1, a__1, i__1, &c__2); nb = ilaenv_(&c__1, "DTREVC", ch__1, n, &c_n1, &c_n1, &c_n1); maxwrk = *n + (*n << 1) * nb; work[1] = (double) maxwrk; lquery = *lwork == -1; if (! rightv && ! leftv) { *info = -1; } else if (! allv && ! over && ! somev) { *info = -2; } else if (*n < 0) { *info = -4; } else if (*ldt < max(1,*n)) { *info = -6; } else if (*ldvl < 1 || leftv && *ldvl < *n) { *info = -8; } else if (*ldvr < 1 || rightv && *ldvr < *n) { *info = -10; } else /* if(complicated condition) */ { // Computing MAX i__2 = 1, i__3 = *n * 3; if (*lwork < max(i__2,i__3) && ! lquery) { *info = -14; } else { // // Set M to the number of columns required to store the selected // eigenvectors, standardize the array SELECT if necessary, and // test MM. // if (somev) { *m = 0; pair = FALSE_; i__2 = *n; for (j = 1; j <= i__2; ++j) { if (pair) { pair = FALSE_; select[j] = FALSE_; } else { if (j < *n) { if (t[j + 1 + j * t_dim1] == 0.) { if (select[j]) { ++(*m); } } else { pair = TRUE_; if (select[j] || select[j + 1]) { select[j] = TRUE_; *m += 2; } } } else { if (select[*n]) { ++(*m); } } } // L10: } } else { *m = *n; } if (*mm < *m) { *info = -11; } } } if (*info != 0) { i__2 = -(*info); xerbla_("DTREVC3", &i__2); return 0; } else if (lquery) { return 0; } // // Quick return if possible. // if (*n == 0) { return 0; } // // Use blocked version of back-transformation if sufficient workspace. // Zero-out the workspace to avoid potential NaN propagation. // if (over && *lwork >= *n + (*n << 4)) { nb = (*lwork - *n) / (*n << 1); nb = min(nb,128); i__2 = (nb << 1) + 1; dlaset_("F", n, &i__2, &c_b17, &c_b17, &work[1], n); } else { nb = 1; } // // Set the constants to control overflow. // unfl = dlamch_("Safe minimum"); ovfl = 1. / unfl; dlabad_(&unfl, &ovfl); ulp = dlamch_("Precision"); smlnum = unfl * (*n / ulp); bignum = (1. - ulp) / smlnum; // // Compute 1-norm of each column of strictly upper triangular // part of T to control overflow in triangular solver. // work[1] = 0.; i__2 = *n; for (j = 2; j <= i__2; ++j) { work[j] = 0.; i__3 = j - 1; for (i__ = 1; i__ <= i__3; ++i__) { work[j] += (d__1 = t[i__ + j * t_dim1], abs(d__1)); // L20: } // L30: } // // Index IP is used to specify the real or complex eigenvalue: // IP = 0, real eigenvalue, // 1, first of conjugate complex pair: (wr,wi) // -1, second of conjugate complex pair: (wr,wi) // ISCOMPLEX array stores IP for each column in current block. // if (rightv) { // // ============================================================ // Compute right eigenvectors. // // IV is index of column in current block. // For complex right vector, uses IV-1 for real part and IV for complex part. // Non-blocked version always uses IV=2; // blocked version starts with IV=NB, goes down to 1 or 2. // (Note the "0-th" column is used for 1-norms computed above.) iv = 2; if (nb > 2) { iv = nb; } ip = 0; is = *m; for (ki = *n; ki >= 1; --ki) { if (ip == -1) { // previous iteration (ki+1) was second of conjugate pair, // so this ki is first of conjugate pair; skip to end of loop ip = 1; goto L140; } else if (ki == 1) { // last column, so this ki must be real eigenvalue ip = 0; } else if (t[ki + (ki - 1) * t_dim1] == 0.) { // zero on sub-diagonal, so this ki is real eigenvalue ip = 0; } else { // non-zero on sub-diagonal, so this ki is second of conjugate pair ip = -1; } if (somev) { if (ip == 0) { if (! select[ki]) { goto L140; } } else { if (! select[ki - 1]) { goto L140; } } } // // Compute the KI-th eigenvalue (WR,WI). // wr = t[ki + ki * t_dim1]; wi = 0.; if (ip != 0) { wi = sqrt((d__1 = t[ki + (ki - 1) * t_dim1], abs(d__1))) * sqrt((d__2 = t[ki - 1 + ki * t_dim1], abs(d__2))); } // Computing MAX d__1 = ulp * (abs(wr) + abs(wi)); smin = max(d__1,smlnum); if (ip == 0) { // // -------------------------------------------------------- // Real right eigenvector // work[ki + iv * *n] = 1.; // // Form right-hand side. // i__2 = ki - 1; for (k = 1; k <= i__2; ++k) { work[k + iv * *n] = -t[k + ki * t_dim1]; // L50: } // // Solve upper quasi-triangular system: // [ T(1:KI-1,1:KI-1) - WR ]*X = SCALE*WORK. // jnxt = ki - 1; for (j = ki - 1; j >= 1; --j) { if (j > jnxt) { goto L60; } j1 = j; j2 = j; jnxt = j - 1; if (j > 1) { if (t[j + (j - 1) * t_dim1] != 0.) { j1 = j - 1; jnxt = j - 2; } } if (j1 == j2) { // // 1-by-1 diagonal block // dlaln2_(&c_false, &c__1, &c__1, &smin, &c_b29, &t[j + j * t_dim1], ldt, &c_b29, &c_b29, &work[j + iv * *n], n, &wr, &c_b17, x, &c__2, &scale, & xnorm, &ierr); // // Scale X(1,1) to avoid overflow when updating // the right-hand side. // if (xnorm > 1.) { if (work[j] > bignum / xnorm) { x[0] /= xnorm; scale /= xnorm; } } // // Scale if necessary // if (scale != 1.) { dscal_(&ki, &scale, &work[iv * *n + 1], &c__1); } work[j + iv * *n] = x[0]; // // Update right-hand side // i__2 = j - 1; d__1 = -x[0]; daxpy_(&i__2, &d__1, &t[j * t_dim1 + 1], &c__1, &work[ iv * *n + 1], &c__1); } else { // // 2-by-2 diagonal block // dlaln2_(&c_false, &c__2, &c__1, &smin, &c_b29, &t[j - 1 + (j - 1) * t_dim1], ldt, &c_b29, &c_b29, & work[j - 1 + iv * *n], n, &wr, &c_b17, x, & c__2, &scale, &xnorm, &ierr); // // Scale X(1,1) and X(2,1) to avoid overflow when // updating the right-hand side. // if (xnorm > 1.) { // Computing MAX d__1 = work[j - 1], d__2 = work[j]; beta = max(d__1,d__2); if (beta > bignum / xnorm) { x[0] /= xnorm; x[1] /= xnorm; scale /= xnorm; } } // // Scale if necessary // if (scale != 1.) { dscal_(&ki, &scale, &work[iv * *n + 1], &c__1); } work[j - 1 + iv * *n] = x[0]; work[j + iv * *n] = x[1]; // // Update right-hand side // i__2 = j - 2; d__1 = -x[0]; daxpy_(&i__2, &d__1, &t[(j - 1) * t_dim1 + 1], &c__1, &work[iv * *n + 1], &c__1); i__2 = j - 2; d__1 = -x[1]; daxpy_(&i__2, &d__1, &t[j * t_dim1 + 1], &c__1, &work[ iv * *n + 1], &c__1); } L60: ; } // // Copy the vector x or Q*x to VR and normalize. // if (! over) { // ------------------------------ // no back-transform: copy x to VR and normalize. dcopy_(&ki, &work[iv * *n + 1], &c__1, &vr[is * vr_dim1 + 1], &c__1); ii = idamax_(&ki, &vr[is * vr_dim1 + 1], &c__1); remax = 1. / (d__1 = vr[ii + is * vr_dim1], abs(d__1)); dscal_(&ki, &remax, &vr[is * vr_dim1 + 1], &c__1); i__2 = *n; for (k = ki + 1; k <= i__2; ++k) { vr[k + is * vr_dim1] = 0.; // L70: } } else if (nb == 1) { // ------------------------------ // version 1: back-transform each vector with GEMV, Q*x. if (ki > 1) { i__2 = ki - 1; dgemv_("N", n, &i__2, &c_b29, &vr[vr_offset], ldvr, & work[iv * *n + 1], &c__1, &work[ki + iv * *n], &vr[ki * vr_dim1 + 1], &c__1); } ii = idamax_(n, &vr[ki * vr_dim1 + 1], &c__1); remax = 1. / (d__1 = vr[ii + ki * vr_dim1], abs(d__1)); dscal_(n, &remax, &vr[ki * vr_dim1 + 1], &c__1); } else { // ------------------------------ // version 2: back-transform block of vectors with GEMM // zero out below vector i__2 = *n; for (k = ki + 1; k <= i__2; ++k) { work[k + iv * *n] = 0.; } iscomplex[iv - 1] = ip; // back-transform and normalization is done below } } else { // // -------------------------------------------------------- // Complex right eigenvector. // // Initial solve // [ ( T(KI-1,KI-1) T(KI-1,KI) ) - (WR + I*WI) ]*X = 0. // [ ( T(KI, KI-1) T(KI, KI) ) ] // if ((d__1 = t[ki - 1 + ki * t_dim1], abs(d__1)) >= (d__2 = t[ ki + (ki - 1) * t_dim1], abs(d__2))) { work[ki - 1 + (iv - 1) * *n] = 1.; work[ki + iv * *n] = wi / t[ki - 1 + ki * t_dim1]; } else { work[ki - 1 + (iv - 1) * *n] = -wi / t[ki + (ki - 1) * t_dim1]; work[ki + iv * *n] = 1.; } work[ki + (iv - 1) * *n] = 0.; work[ki - 1 + iv * *n] = 0.; // // Form right-hand side. // i__2 = ki - 2; for (k = 1; k <= i__2; ++k) { work[k + (iv - 1) * *n] = -work[ki - 1 + (iv - 1) * *n] * t[k + (ki - 1) * t_dim1]; work[k + iv * *n] = -work[ki + iv * *n] * t[k + ki * t_dim1]; // L80: } // // Solve upper quasi-triangular system: // [ T(1:KI-2,1:KI-2) - (WR+i*WI) ]*X = SCALE*(WORK+i*WORK2) // jnxt = ki - 2; for (j = ki - 2; j >= 1; --j) { if (j > jnxt) { goto L90; } j1 = j; j2 = j; jnxt = j - 1; if (j > 1) { if (t[j + (j - 1) * t_dim1] != 0.) { j1 = j - 1; jnxt = j - 2; } } if (j1 == j2) { // // 1-by-1 diagonal block // dlaln2_(&c_false, &c__1, &c__2, &smin, &c_b29, &t[j + j * t_dim1], ldt, &c_b29, &c_b29, &work[j + ( iv - 1) * *n], n, &wr, &wi, x, &c__2, &scale, &xnorm, &ierr); // // Scale X(1,1) and X(1,2) to avoid overflow when // updating the right-hand side. // if (xnorm > 1.) { if (work[j] > bignum / xnorm) { x[0] /= xnorm; x[2] /= xnorm; scale /= xnorm; } } // // Scale if necessary // if (scale != 1.) { dscal_(&ki, &scale, &work[(iv - 1) * *n + 1], & c__1); dscal_(&ki, &scale, &work[iv * *n + 1], &c__1); } work[j + (iv - 1) * *n] = x[0]; work[j + iv * *n] = x[2]; // // Update the right-hand side // i__2 = j - 1; d__1 = -x[0]; daxpy_(&i__2, &d__1, &t[j * t_dim1 + 1], &c__1, &work[ (iv - 1) * *n + 1], &c__1); i__2 = j - 1; d__1 = -x[2]; daxpy_(&i__2, &d__1, &t[j * t_dim1 + 1], &c__1, &work[ iv * *n + 1], &c__1); } else { // // 2-by-2 diagonal block // dlaln2_(&c_false, &c__2, &c__2, &smin, &c_b29, &t[j - 1 + (j - 1) * t_dim1], ldt, &c_b29, &c_b29, & work[j - 1 + (iv - 1) * *n], n, &wr, &wi, x, & c__2, &scale, &xnorm, &ierr); // // Scale X to avoid overflow when updating // the right-hand side. // if (xnorm > 1.) { // Computing MAX d__1 = work[j - 1], d__2 = work[j]; beta = max(d__1,d__2); if (beta > bignum / xnorm) { rec = 1. / xnorm; x[0] *= rec; x[2] *= rec; x[1] *= rec; x[3] *= rec; scale *= rec; } } // // Scale if necessary // if (scale != 1.) { dscal_(&ki, &scale, &work[(iv - 1) * *n + 1], & c__1); dscal_(&ki, &scale, &work[iv * *n + 1], &c__1); } work[j - 1 + (iv - 1) * *n] = x[0]; work[j + (iv - 1) * *n] = x[1]; work[j - 1 + iv * *n] = x[2]; work[j + iv * *n] = x[3]; // // Update the right-hand side // i__2 = j - 2; d__1 = -x[0]; daxpy_(&i__2, &d__1, &t[(j - 1) * t_dim1 + 1], &c__1, &work[(iv - 1) * *n + 1], &c__1); i__2 = j - 2; d__1 = -x[1]; daxpy_(&i__2, &d__1, &t[j * t_dim1 + 1], &c__1, &work[ (iv - 1) * *n + 1], &c__1); i__2 = j - 2; d__1 = -x[2]; daxpy_(&i__2, &d__1, &t[(j - 1) * t_dim1 + 1], &c__1, &work[iv * *n + 1], &c__1); i__2 = j - 2; d__1 = -x[3]; daxpy_(&i__2, &d__1, &t[j * t_dim1 + 1], &c__1, &work[ iv * *n + 1], &c__1); } L90: ; } // // Copy the vector x or Q*x to VR and normalize. // if (! over) { // ------------------------------ // no back-transform: copy x to VR and normalize. dcopy_(&ki, &work[(iv - 1) * *n + 1], &c__1, &vr[(is - 1) * vr_dim1 + 1], &c__1); dcopy_(&ki, &work[iv * *n + 1], &c__1, &vr[is * vr_dim1 + 1], &c__1); emax = 0.; i__2 = ki; for (k = 1; k <= i__2; ++k) { // Computing MAX d__3 = emax, d__4 = (d__1 = vr[k + (is - 1) * vr_dim1] , abs(d__1)) + (d__2 = vr[k + is * vr_dim1], abs(d__2)); emax = max(d__3,d__4); // L100: } remax = 1. / emax; dscal_(&ki, &remax, &vr[(is - 1) * vr_dim1 + 1], &c__1); dscal_(&ki, &remax, &vr[is * vr_dim1 + 1], &c__1); i__2 = *n; for (k = ki + 1; k <= i__2; ++k) { vr[k + (is - 1) * vr_dim1] = 0.; vr[k + is * vr_dim1] = 0.; // L110: } } else if (nb == 1) { // ------------------------------ // version 1: back-transform each vector with GEMV, Q*x. if (ki > 2) { i__2 = ki - 2; dgemv_("N", n, &i__2, &c_b29, &vr[vr_offset], ldvr, & work[(iv - 1) * *n + 1], &c__1, &work[ki - 1 + (iv - 1) * *n], &vr[(ki - 1) * vr_dim1 + 1], &c__1); i__2 = ki - 2; dgemv_("N", n, &i__2, &c_b29, &vr[vr_offset], ldvr, & work[iv * *n + 1], &c__1, &work[ki + iv * *n], &vr[ki * vr_dim1 + 1], &c__1); } else { dscal_(n, &work[ki - 1 + (iv - 1) * *n], &vr[(ki - 1) * vr_dim1 + 1], &c__1); dscal_(n, &work[ki + iv * *n], &vr[ki * vr_dim1 + 1], &c__1); } emax = 0.; i__2 = *n; for (k = 1; k <= i__2; ++k) { // Computing MAX d__3 = emax, d__4 = (d__1 = vr[k + (ki - 1) * vr_dim1] , abs(d__1)) + (d__2 = vr[k + ki * vr_dim1], abs(d__2)); emax = max(d__3,d__4); // L120: } remax = 1. / emax; dscal_(n, &remax, &vr[(ki - 1) * vr_dim1 + 1], &c__1); dscal_(n, &remax, &vr[ki * vr_dim1 + 1], &c__1); } else { // ------------------------------ // version 2: back-transform block of vectors with GEMM // zero out below vector i__2 = *n; for (k = ki + 1; k <= i__2; ++k) { work[k + (iv - 1) * *n] = 0.; work[k + iv * *n] = 0.; } iscomplex[iv - 2] = -ip; iscomplex[iv - 1] = ip; --iv; // back-transform and normalization is done below } } if (nb > 1) { // -------------------------------------------------------- // Blocked version of back-transform // For complex case, KI2 includes both vectors (KI-1 and KI) if (ip == 0) { ki2 = ki; } else { ki2 = ki - 1; } // Columns IV:NB of work are valid vectors. // When the number of vectors stored reaches NB-1 or NB, // or if this was last vector, do the GEMM if (iv <= 2 || ki2 == 1) { i__2 = nb - iv + 1; i__3 = ki2 + nb - iv; dgemm_("N", "N", n, &i__2, &i__3, &c_b29, &vr[vr_offset], ldvr, &work[iv * *n + 1], n, &c_b17, &work[(nb + iv) * *n + 1], n); // normalize vectors i__2 = nb; for (k = iv; k <= i__2; ++k) { if (iscomplex[k - 1] == 0) { // real eigenvector ii = idamax_(n, &work[(nb + k) * *n + 1], &c__1); remax = 1. / (d__1 = work[ii + (nb + k) * *n], abs(d__1)); } else if (iscomplex[k - 1] == 1) { // first eigenvector of conjugate pair emax = 0.; i__3 = *n; for (ii = 1; ii <= i__3; ++ii) { // Computing MAX d__3 = emax, d__4 = (d__1 = work[ii + (nb + k) * *n], abs(d__1)) + (d__2 = work[ii + (nb + k + 1) * *n], abs(d__2)); emax = max(d__3,d__4); } remax = 1. / emax; // else if ISCOMPLEX(K).EQ.-1 // second eigenvector of conjugate pair // reuse same REMAX as previous K } dscal_(n, &remax, &work[(nb + k) * *n + 1], &c__1); } i__2 = nb - iv + 1; dlacpy_("F", n, &i__2, &work[(nb + iv) * *n + 1], n, &vr[ ki2 * vr_dim1 + 1], ldvr); iv = nb; } else { --iv; } } // // blocked back-transform --is; if (ip != 0) { --is; } L140: ; } } if (leftv) { // // ============================================================ // Compute left eigenvectors. // // IV is index of column in current block. // For complex left vector, uses IV for real part and IV+1 for complex part. // Non-blocked version always uses IV=1; // blocked version starts with IV=1, goes up to NB-1 or NB. // (Note the "0-th" column is used for 1-norms computed above.) iv = 1; ip = 0; is = 1; i__2 = *n; for (ki = 1; ki <= i__2; ++ki) { if (ip == 1) { // previous iteration (ki-1) was first of conjugate pair, // so this ki is second of conjugate pair; skip to end of loop ip = -1; goto L260; } else if (ki == *n) { // last column, so this ki must be real eigenvalue ip = 0; } else if (t[ki + 1 + ki * t_dim1] == 0.) { // zero on sub-diagonal, so this ki is real eigenvalue ip = 0; } else { // non-zero on sub-diagonal, so this ki is first of conjugate pair ip = 1; } if (somev) { if (! select[ki]) { goto L260; } } // // Compute the KI-th eigenvalue (WR,WI). // wr = t[ki + ki * t_dim1]; wi = 0.; if (ip != 0) { wi = sqrt((d__1 = t[ki + (ki + 1) * t_dim1], abs(d__1))) * sqrt((d__2 = t[ki + 1 + ki * t_dim1], abs(d__2))); } // Computing MAX d__1 = ulp * (abs(wr) + abs(wi)); smin = max(d__1,smlnum); if (ip == 0) { // // -------------------------------------------------------- // Real left eigenvector // work[ki + iv * *n] = 1.; // // Form right-hand side. // i__3 = *n; for (k = ki + 1; k <= i__3; ++k) { work[k + iv * *n] = -t[ki + k * t_dim1]; // L160: } // // Solve transposed quasi-triangular system: // [ T(KI+1:N,KI+1:N) - WR ]**T * X = SCALE*WORK // vmax = 1.; vcrit = bignum; jnxt = ki + 1; i__3 = *n; for (j = ki + 1; j <= i__3; ++j) { if (j < jnxt) { goto L170; } j1 = j; j2 = j; jnxt = j + 1; if (j < *n) { if (t[j + 1 + j * t_dim1] != 0.) { j2 = j + 1; jnxt = j + 2; } } if (j1 == j2) { // // 1-by-1 diagonal block // // Scale if necessary to avoid overflow when forming // the right-hand side. // if (work[j] > vcrit) { rec = 1. / vmax; i__4 = *n - ki + 1; dscal_(&i__4, &rec, &work[ki + iv * *n], &c__1); vmax = 1.; vcrit = bignum; } i__4 = j - ki - 1; work[j + iv * *n] -= ddot_(&i__4, &t[ki + 1 + j * t_dim1], &c__1, &work[ki + 1 + iv * *n], & c__1); // // Solve [ T(J,J) - WR ]**T * X = WORK // dlaln2_(&c_false, &c__1, &c__1, &smin, &c_b29, &t[j + j * t_dim1], ldt, &c_b29, &c_b29, &work[j + iv * *n], n, &wr, &c_b17, x, &c__2, &scale, & xnorm, &ierr); // // Scale if necessary // if (scale != 1.) { i__4 = *n - ki + 1; dscal_(&i__4, &scale, &work[ki + iv * *n], &c__1); } work[j + iv * *n] = x[0]; // Computing MAX d__2 = (d__1 = work[j + iv * *n], abs(d__1)); vmax = max(d__2,vmax); vcrit = bignum / vmax; } else { // // 2-by-2 diagonal block // // Scale if necessary to avoid overflow when forming // the right-hand side. // // Computing MAX d__1 = work[j], d__2 = work[j + 1]; beta = max(d__1,d__2); if (beta > vcrit) { rec = 1. / vmax; i__4 = *n - ki + 1; dscal_(&i__4, &rec, &work[ki + iv * *n], &c__1); vmax = 1.; vcrit = bignum; } i__4 = j - ki - 1; work[j + iv * *n] -= ddot_(&i__4, &t[ki + 1 + j * t_dim1], &c__1, &work[ki + 1 + iv * *n], & c__1); i__4 = j - ki - 1; work[j + 1 + iv * *n] -= ddot_(&i__4, &t[ki + 1 + (j + 1) * t_dim1], &c__1, &work[ki + 1 + iv * *n] , &c__1); // // Solve // [ T(J,J)-WR T(J,J+1) ]**T * X = SCALE*( WORK1 ) // [ T(J+1,J) T(J+1,J+1)-WR ] ( WORK2 ) // dlaln2_(&c_true, &c__2, &c__1, &smin, &c_b29, &t[j + j * t_dim1], ldt, &c_b29, &c_b29, &work[j + iv * *n], n, &wr, &c_b17, x, &c__2, &scale, & xnorm, &ierr); // // Scale if necessary // if (scale != 1.) { i__4 = *n - ki + 1; dscal_(&i__4, &scale, &work[ki + iv * *n], &c__1); } work[j + iv * *n] = x[0]; work[j + 1 + iv * *n] = x[1]; // // Computing MAX d__3 = (d__1 = work[j + iv * *n], abs(d__1)), d__4 = ( d__2 = work[j + 1 + iv * *n], abs(d__2)), d__3 = max(d__3,d__4); vmax = max(d__3,vmax); vcrit = bignum / vmax; } L170: ; } // // Copy the vector x or Q*x to VL and normalize. // if (! over) { // ------------------------------ // no back-transform: copy x to VL and normalize. i__3 = *n - ki + 1; dcopy_(&i__3, &work[ki + iv * *n], &c__1, &vl[ki + is * vl_dim1], &c__1); i__3 = *n - ki + 1; ii = idamax_(&i__3, &vl[ki + is * vl_dim1], &c__1) + ki - 1; remax = 1. / (d__1 = vl[ii + is * vl_dim1], abs(d__1)); i__3 = *n - ki + 1; dscal_(&i__3, &remax, &vl[ki + is * vl_dim1], &c__1); i__3 = ki - 1; for (k = 1; k <= i__3; ++k) { vl[k + is * vl_dim1] = 0.; // L180: } } else if (nb == 1) { // ------------------------------ // version 1: back-transform each vector with GEMV, Q*x. if (ki < *n) { i__3 = *n - ki; dgemv_("N", n, &i__3, &c_b29, &vl[(ki + 1) * vl_dim1 + 1], ldvl, &work[ki + 1 + iv * *n], &c__1, & work[ki + iv * *n], &vl[ki * vl_dim1 + 1], & c__1); } ii = idamax_(n, &vl[ki * vl_dim1 + 1], &c__1); remax = 1. / (d__1 = vl[ii + ki * vl_dim1], abs(d__1)); dscal_(n, &remax, &vl[ki * vl_dim1 + 1], &c__1); } else { // ------------------------------ // version 2: back-transform block of vectors with GEMM // zero out above vector // could go from KI-NV+1 to KI-1 i__3 = ki - 1; for (k = 1; k <= i__3; ++k) { work[k + iv * *n] = 0.; } iscomplex[iv - 1] = ip; // back-transform and normalization is done below } } else { // // -------------------------------------------------------- // Complex left eigenvector. // // Initial solve: // [ ( T(KI,KI) T(KI,KI+1) )**T - (WR - I* WI) ]*X = 0. // [ ( T(KI+1,KI) T(KI+1,KI+1) ) ] // if ((d__1 = t[ki + (ki + 1) * t_dim1], abs(d__1)) >= (d__2 = t[ki + 1 + ki * t_dim1], abs(d__2))) { work[ki + iv * *n] = wi / t[ki + (ki + 1) * t_dim1]; work[ki + 1 + (iv + 1) * *n] = 1.; } else { work[ki + iv * *n] = 1.; work[ki + 1 + (iv + 1) * *n] = -wi / t[ki + 1 + ki * t_dim1]; } work[ki + 1 + iv * *n] = 0.; work[ki + (iv + 1) * *n] = 0.; // // Form right-hand side. // i__3 = *n; for (k = ki + 2; k <= i__3; ++k) { work[k + iv * *n] = -work[ki + iv * *n] * t[ki + k * t_dim1]; work[k + (iv + 1) * *n] = -work[ki + 1 + (iv + 1) * *n] * t[ki + 1 + k * t_dim1]; // L190: } // // Solve transposed quasi-triangular system: // [ T(KI+2:N,KI+2:N)**T - (WR-i*WI) ]*X = WORK1+i*WORK2 // vmax = 1.; vcrit = bignum; jnxt = ki + 2; i__3 = *n; for (j = ki + 2; j <= i__3; ++j) { if (j < jnxt) { goto L200; } j1 = j; j2 = j; jnxt = j + 1; if (j < *n) { if (t[j + 1 + j * t_dim1] != 0.) { j2 = j + 1; jnxt = j + 2; } } if (j1 == j2) { // // 1-by-1 diagonal block // // Scale if necessary to avoid overflow when // forming the right-hand side elements. // if (work[j] > vcrit) { rec = 1. / vmax; i__4 = *n - ki + 1; dscal_(&i__4, &rec, &work[ki + iv * *n], &c__1); i__4 = *n - ki + 1; dscal_(&i__4, &rec, &work[ki + (iv + 1) * *n], & c__1); vmax = 1.; vcrit = bignum; } i__4 = j - ki - 2; work[j + iv * *n] -= ddot_(&i__4, &t[ki + 2 + j * t_dim1], &c__1, &work[ki + 2 + iv * *n], & c__1); i__4 = j - ki - 2; work[j + (iv + 1) * *n] -= ddot_(&i__4, &t[ki + 2 + j * t_dim1], &c__1, &work[ki + 2 + (iv + 1) * * n], &c__1); // // Solve [ T(J,J)-(WR-i*WI) ]*(X11+i*X12)= WK+I*WK2 // d__1 = -wi; dlaln2_(&c_false, &c__1, &c__2, &smin, &c_b29, &t[j + j * t_dim1], ldt, &c_b29, &c_b29, &work[j + iv * *n], n, &wr, &d__1, x, &c__2, &scale, & xnorm, &ierr); // // Scale if necessary // if (scale != 1.) { i__4 = *n - ki + 1; dscal_(&i__4, &scale, &work[ki + iv * *n], &c__1); i__4 = *n - ki + 1; dscal_(&i__4, &scale, &work[ki + (iv + 1) * *n], & c__1); } work[j + iv * *n] = x[0]; work[j + (iv + 1) * *n] = x[2]; // Computing MAX d__3 = (d__1 = work[j + iv * *n], abs(d__1)), d__4 = ( d__2 = work[j + (iv + 1) * *n], abs(d__2)), d__3 = max(d__3,d__4); vmax = max(d__3,vmax); vcrit = bignum / vmax; } else { // // 2-by-2 diagonal block // // Scale if necessary to avoid overflow when forming // the right-hand side elements. // // Computing MAX d__1 = work[j], d__2 = work[j + 1]; beta = max(d__1,d__2); if (beta > vcrit) { rec = 1. / vmax; i__4 = *n - ki + 1; dscal_(&i__4, &rec, &work[ki + iv * *n], &c__1); i__4 = *n - ki + 1; dscal_(&i__4, &rec, &work[ki + (iv + 1) * *n], & c__1); vmax = 1.; vcrit = bignum; } i__4 = j - ki - 2; work[j + iv * *n] -= ddot_(&i__4, &t[ki + 2 + j * t_dim1], &c__1, &work[ki + 2 + iv * *n], & c__1); i__4 = j - ki - 2; work[j + (iv + 1) * *n] -= ddot_(&i__4, &t[ki + 2 + j * t_dim1], &c__1, &work[ki + 2 + (iv + 1) * * n], &c__1); i__4 = j - ki - 2; work[j + 1 + iv * *n] -= ddot_(&i__4, &t[ki + 2 + (j + 1) * t_dim1], &c__1, &work[ki + 2 + iv * *n] , &c__1); i__4 = j - ki - 2; work[j + 1 + (iv + 1) * *n] -= ddot_(&i__4, &t[ki + 2 + (j + 1) * t_dim1], &c__1, &work[ki + 2 + ( iv + 1) * *n], &c__1); // // Solve 2-by-2 complex linear equation // [ (T(j,j) T(j,j+1) )**T - (wr-i*wi)*I ]*X = SCALE*B // [ (T(j+1,j) T(j+1,j+1)) ] // d__1 = -wi; dlaln2_(&c_true, &c__2, &c__2, &smin, &c_b29, &t[j + j * t_dim1], ldt, &c_b29, &c_b29, &work[j + iv * *n], n, &wr, &d__1, x, &c__2, &scale, & xnorm, &ierr); // // Scale if necessary // if (scale != 1.) { i__4 = *n - ki + 1; dscal_(&i__4, &scale, &work[ki + iv * *n], &c__1); i__4 = *n - ki + 1; dscal_(&i__4, &scale, &work[ki + (iv + 1) * *n], & c__1); } work[j + iv * *n] = x[0]; work[j + (iv + 1) * *n] = x[2]; work[j + 1 + iv * *n] = x[1]; work[j + 1 + (iv + 1) * *n] = x[3]; // Computing MAX d__1 = abs(x[0]), d__2 = abs(x[2]), d__1 = max(d__1, d__2), d__2 = abs(x[1]), d__1 = max(d__1,d__2) , d__2 = abs(x[3]), d__1 = max(d__1,d__2); vmax = max(d__1,vmax); vcrit = bignum / vmax; } L200: ; } // // Copy the vector x or Q*x to VL and normalize. // if (! over) { // ------------------------------ // no back-transform: copy x to VL and normalize. i__3 = *n - ki + 1; dcopy_(&i__3, &work[ki + iv * *n], &c__1, &vl[ki + is * vl_dim1], &c__1); i__3 = *n - ki + 1; dcopy_(&i__3, &work[ki + (iv + 1) * *n], &c__1, &vl[ki + ( is + 1) * vl_dim1], &c__1); emax = 0.; i__3 = *n; for (k = ki; k <= i__3; ++k) { // Computing MAX d__3 = emax, d__4 = (d__1 = vl[k + is * vl_dim1], abs( d__1)) + (d__2 = vl[k + (is + 1) * vl_dim1], abs(d__2)); emax = max(d__3,d__4); // L220: } remax = 1. / emax; i__3 = *n - ki + 1; dscal_(&i__3, &remax, &vl[ki + is * vl_dim1], &c__1); i__3 = *n - ki + 1; dscal_(&i__3, &remax, &vl[ki + (is + 1) * vl_dim1], &c__1) ; i__3 = ki - 1; for (k = 1; k <= i__3; ++k) { vl[k + is * vl_dim1] = 0.; vl[k + (is + 1) * vl_dim1] = 0.; // L230: } } else if (nb == 1) { // ------------------------------ // version 1: back-transform each vector with GEMV, Q*x. if (ki < *n - 1) { i__3 = *n - ki - 1; dgemv_("N", n, &i__3, &c_b29, &vl[(ki + 2) * vl_dim1 + 1], ldvl, &work[ki + 2 + iv * *n], &c__1, & work[ki + iv * *n], &vl[ki * vl_dim1 + 1], & c__1); i__3 = *n - ki - 1; dgemv_("N", n, &i__3, &c_b29, &vl[(ki + 2) * vl_dim1 + 1], ldvl, &work[ki + 2 + (iv + 1) * *n], & c__1, &work[ki + 1 + (iv + 1) * *n], &vl[(ki + 1) * vl_dim1 + 1], &c__1); } else { dscal_(n, &work[ki + iv * *n], &vl[ki * vl_dim1 + 1], &c__1); dscal_(n, &work[ki + 1 + (iv + 1) * *n], &vl[(ki + 1) * vl_dim1 + 1], &c__1); } emax = 0.; i__3 = *n; for (k = 1; k <= i__3; ++k) { // Computing MAX d__3 = emax, d__4 = (d__1 = vl[k + ki * vl_dim1], abs( d__1)) + (d__2 = vl[k + (ki + 1) * vl_dim1], abs(d__2)); emax = max(d__3,d__4); // L240: } remax = 1. / emax; dscal_(n, &remax, &vl[ki * vl_dim1 + 1], &c__1); dscal_(n, &remax, &vl[(ki + 1) * vl_dim1 + 1], &c__1); } else { // ------------------------------ // version 2: back-transform block of vectors with GEMM // zero out above vector // could go from KI-NV+1 to KI-1 i__3 = ki - 1; for (k = 1; k <= i__3; ++k) { work[k + iv * *n] = 0.; work[k + (iv + 1) * *n] = 0.; } iscomplex[iv - 1] = ip; iscomplex[iv] = -ip; ++iv; // back-transform and normalization is done below } } if (nb > 1) { // -------------------------------------------------------- // Blocked version of back-transform // For complex case, KI2 includes both vectors (KI and KI+1) if (ip == 0) { ki2 = ki; } else { ki2 = ki + 1; } // Columns 1:IV of work are valid vectors. // When the number of vectors stored reaches NB-1 or NB, // or if this was last vector, do the GEMM if (iv >= nb - 1 || ki2 == *n) { i__3 = *n - ki2 + iv; dgemm_("N", "N", n, &iv, &i__3, &c_b29, &vl[(ki2 - iv + 1) * vl_dim1 + 1], ldvl, &work[ki2 - iv + 1 + *n], n, &c_b17, &work[(nb + 1) * *n + 1], n); // normalize vectors i__3 = iv; for (k = 1; k <= i__3; ++k) { if (iscomplex[k - 1] == 0) { // real eigenvector ii = idamax_(n, &work[(nb + k) * *n + 1], &c__1); remax = 1. / (d__1 = work[ii + (nb + k) * *n], abs(d__1)); } else if (iscomplex[k - 1] == 1) { // first eigenvector of conjugate pair emax = 0.; i__4 = *n; for (ii = 1; ii <= i__4; ++ii) { // Computing MAX d__3 = emax, d__4 = (d__1 = work[ii + (nb + k) * *n], abs(d__1)) + (d__2 = work[ii + (nb + k + 1) * *n], abs(d__2)); emax = max(d__3,d__4); } remax = 1. / emax; // else if ISCOMPLEX(K).EQ.-1 // second eigenvector of conjugate pair // reuse same REMAX as previous K } dscal_(n, &remax, &work[(nb + k) * *n + 1], &c__1); } dlacpy_("F", n, &iv, &work[(nb + 1) * *n + 1], n, &vl[( ki2 - iv + 1) * vl_dim1 + 1], ldvl); iv = 1; } else { ++iv; } } // // blocked back-transform ++is; if (ip != 0) { ++is; } L260: ; } } return 0; // // End of DTREVC3 // } // dtrevc3_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b DTREXC // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // //> \htmlonly //> Download DTREXC + dependencies //> //> [TGZ] //> //> [ZIP] //> //> [TXT] //> \endhtmlonly // // Definition: // =========== // // SUBROUTINE DTREXC( COMPQ, N, T, LDT, Q, LDQ, IFST, ILST, WORK, // INFO ) // // .. Scalar Arguments .. // CHARACTER COMPQ // INTEGER IFST, ILST, INFO, LDQ, LDT, N // .. // .. Array Arguments .. // DOUBLE PRECISION Q( LDQ, * ), T( LDT, * ), WORK( * ) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> DTREXC reorders the real Schur factorization of a real matrix //> A = Q*T*Q**T, so that the diagonal block of T with row index IFST is //> moved to row ILST. //> //> The real Schur form T is reordered by an orthogonal similarity //> transformation Z**T*T*Z, and optionally the matrix Q of Schur vectors //> is updated by postmultiplying it with Z. //> //> T must be in Schur canonical form (as returned by DHSEQR), that is, //> block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; each //> 2-by-2 diagonal block has its diagonal elements equal and its //> off-diagonal elements of opposite sign. //> \endverbatim // // Arguments: // ========== // //> \param[in] COMPQ //> \verbatim //> COMPQ is CHARACTER*1 //> = 'V': update the matrix Q of Schur vectors; //> = 'N': do not update Q. //> \endverbatim //> //> \param[in] N //> \verbatim //> N is INTEGER //> The order of the matrix T. N >= 0. //> If N == 0 arguments ILST and IFST may be any value. //> \endverbatim //> //> \param[in,out] T //> \verbatim //> T is DOUBLE PRECISION array, dimension (LDT,N) //> On entry, the upper quasi-triangular matrix T, in Schur //> Schur canonical form. //> On exit, the reordered upper quasi-triangular matrix, again //> in Schur canonical form. //> \endverbatim //> //> \param[in] LDT //> \verbatim //> LDT is INTEGER //> The leading dimension of the array T. LDT >= max(1,N). //> \endverbatim //> //> \param[in,out] Q //> \verbatim //> Q is DOUBLE PRECISION array, dimension (LDQ,N) //> On entry, if COMPQ = 'V', the matrix Q of Schur vectors. //> On exit, if COMPQ = 'V', Q has been postmultiplied by the //> orthogonal transformation matrix Z which reorders T. //> If COMPQ = 'N', Q is not referenced. //> \endverbatim //> //> \param[in] LDQ //> \verbatim //> LDQ is INTEGER //> The leading dimension of the array Q. LDQ >= 1, and if //> COMPQ = 'V', LDQ >= max(1,N). //> \endverbatim //> //> \param[in,out] IFST //> \verbatim //> IFST is INTEGER //> \endverbatim //> //> \param[in,out] ILST //> \verbatim //> ILST is INTEGER //> //> Specify the reordering of the diagonal blocks of T. //> The block with row index IFST is moved to row ILST, by a //> sequence of transpositions between adjacent blocks. //> On exit, if IFST pointed on entry to the second row of a //> 2-by-2 block, it is changed to point to the first row; ILST //> always points to the first row of the block in its final //> position (which may differ from its input value by +1 or -1). //> 1 <= IFST <= N; 1 <= ILST <= N. //> \endverbatim //> //> \param[out] WORK //> \verbatim //> WORK is DOUBLE PRECISION array, dimension (N) //> \endverbatim //> //> \param[out] INFO //> \verbatim //> INFO is INTEGER //> = 0: successful exit //> < 0: if INFO = -i, the i-th argument had an illegal value //> = 1: two adjacent blocks were too close to swap (the problem //> is very ill-conditioned); T may have been partially //> reordered, and ILST points to the first row of the //> current position of the block being moved. //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date December 2016 // //> \ingroup doubleOTHERcomputational // // ===================================================================== /* Subroutine */ int dtrexc_(char *compq, int *n, double *t, int *ldt, double *q, int *ldq, int *ifst, int *ilst, double *work, int *info) { // Table of constant values int c__1 = 1; int c__2 = 2; // System generated locals int q_dim1, q_offset, t_dim1, t_offset, i__1; // Local variables int nbf, nbl, here; extern int lsame_(char *, char *); int wantq; extern /* Subroutine */ int dlaexc_(int *, int *, double *, int *, double *, int *, int *, int *, int *, double *, int *), xerbla_(char *, int *); int nbnext; // // -- LAPACK computational routine (version 3.7.0) -- // -- LAPACK is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // December 2016 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // // ===================================================================== // // .. Parameters .. // .. // .. Local Scalars .. // .. // .. External Functions .. // .. // .. External Subroutines .. // .. // .. Intrinsic Functions .. // .. // .. Executable Statements .. // // Decode and test the input arguments. // // Parameter adjustments t_dim1 = *ldt; t_offset = 1 + t_dim1; t -= t_offset; q_dim1 = *ldq; q_offset = 1 + q_dim1; q -= q_offset; --work; // Function Body *info = 0; wantq = lsame_(compq, "V"); if (! wantq && ! lsame_(compq, "N")) { *info = -1; } else if (*n < 0) { *info = -2; } else if (*ldt < max(1,*n)) { *info = -4; } else if (*ldq < 1 || wantq && *ldq < max(1,*n)) { *info = -6; } else if ((*ifst < 1 || *ifst > *n) && *n > 0) { *info = -7; } else if ((*ilst < 1 || *ilst > *n) && *n > 0) { *info = -8; } if (*info != 0) { i__1 = -(*info); xerbla_("DTREXC", &i__1); return 0; } // // Quick return if possible // if (*n <= 1) { return 0; } // // Determine the first row of specified block // and find out it is 1 by 1 or 2 by 2. // if (*ifst > 1) { if (t[*ifst + (*ifst - 1) * t_dim1] != 0.) { --(*ifst); } } nbf = 1; if (*ifst < *n) { if (t[*ifst + 1 + *ifst * t_dim1] != 0.) { nbf = 2; } } // // Determine the first row of the final block // and find out it is 1 by 1 or 2 by 2. // if (*ilst > 1) { if (t[*ilst + (*ilst - 1) * t_dim1] != 0.) { --(*ilst); } } nbl = 1; if (*ilst < *n) { if (t[*ilst + 1 + *ilst * t_dim1] != 0.) { nbl = 2; } } if (*ifst == *ilst) { return 0; } if (*ifst < *ilst) { // // Update ILST // if (nbf == 2 && nbl == 1) { --(*ilst); } if (nbf == 1 && nbl == 2) { ++(*ilst); } here = *ifst; L10: // // Swap block with next one below // if (nbf == 1 || nbf == 2) { // // Current block either 1 by 1 or 2 by 2 // nbnext = 1; if (here + nbf + 1 <= *n) { if (t[here + nbf + 1 + (here + nbf) * t_dim1] != 0.) { nbnext = 2; } } dlaexc_(&wantq, n, &t[t_offset], ldt, &q[q_offset], ldq, &here, & nbf, &nbnext, &work[1], info); if (*info != 0) { *ilst = here; return 0; } here += nbnext; // // Test if 2 by 2 block breaks into two 1 by 1 blocks // if (nbf == 2) { if (t[here + 1 + here * t_dim1] == 0.) { nbf = 3; } } } else { // // Current block consists of two 1 by 1 blocks each of which // must be swapped individually // nbnext = 1; if (here + 3 <= *n) { if (t[here + 3 + (here + 2) * t_dim1] != 0.) { nbnext = 2; } } i__1 = here + 1; dlaexc_(&wantq, n, &t[t_offset], ldt, &q[q_offset], ldq, &i__1, & c__1, &nbnext, &work[1], info); if (*info != 0) { *ilst = here; return 0; } if (nbnext == 1) { // // Swap two 1 by 1 blocks, no problems possible // dlaexc_(&wantq, n, &t[t_offset], ldt, &q[q_offset], ldq, & here, &c__1, &nbnext, &work[1], info); ++here; } else { // // Recompute NBNEXT in case 2 by 2 split // if (t[here + 2 + (here + 1) * t_dim1] == 0.) { nbnext = 1; } if (nbnext == 2) { // // 2 by 2 Block did not split // dlaexc_(&wantq, n, &t[t_offset], ldt, &q[q_offset], ldq, & here, &c__1, &nbnext, &work[1], info); if (*info != 0) { *ilst = here; return 0; } here += 2; } else { // // 2 by 2 Block did split // dlaexc_(&wantq, n, &t[t_offset], ldt, &q[q_offset], ldq, & here, &c__1, &c__1, &work[1], info); i__1 = here + 1; dlaexc_(&wantq, n, &t[t_offset], ldt, &q[q_offset], ldq, & i__1, &c__1, &c__1, &work[1], info); here += 2; } } } if (here < *ilst) { goto L10; } } else { here = *ifst; L20: // // Swap block with next one above // if (nbf == 1 || nbf == 2) { // // Current block either 1 by 1 or 2 by 2 // nbnext = 1; if (here >= 3) { if (t[here - 1 + (here - 2) * t_dim1] != 0.) { nbnext = 2; } } i__1 = here - nbnext; dlaexc_(&wantq, n, &t[t_offset], ldt, &q[q_offset], ldq, &i__1, & nbnext, &nbf, &work[1], info); if (*info != 0) { *ilst = here; return 0; } here -= nbnext; // // Test if 2 by 2 block breaks into two 1 by 1 blocks // if (nbf == 2) { if (t[here + 1 + here * t_dim1] == 0.) { nbf = 3; } } } else { // // Current block consists of two 1 by 1 blocks each of which // must be swapped individually // nbnext = 1; if (here >= 3) { if (t[here - 1 + (here - 2) * t_dim1] != 0.) { nbnext = 2; } } i__1 = here - nbnext; dlaexc_(&wantq, n, &t[t_offset], ldt, &q[q_offset], ldq, &i__1, & nbnext, &c__1, &work[1], info); if (*info != 0) { *ilst = here; return 0; } if (nbnext == 1) { // // Swap two 1 by 1 blocks, no problems possible // dlaexc_(&wantq, n, &t[t_offset], ldt, &q[q_offset], ldq, & here, &nbnext, &c__1, &work[1], info); --here; } else { // // Recompute NBNEXT in case 2 by 2 split // if (t[here + (here - 1) * t_dim1] == 0.) { nbnext = 1; } if (nbnext == 2) { // // 2 by 2 Block did not split // i__1 = here - 1; dlaexc_(&wantq, n, &t[t_offset], ldt, &q[q_offset], ldq, & i__1, &c__2, &c__1, &work[1], info); if (*info != 0) { *ilst = here; return 0; } here += -2; } else { // // 2 by 2 Block did split // dlaexc_(&wantq, n, &t[t_offset], ldt, &q[q_offset], ldq, & here, &c__1, &c__1, &work[1], info); i__1 = here - 1; dlaexc_(&wantq, n, &t[t_offset], ldt, &q[q_offset], ldq, & i__1, &c__1, &c__1, &work[1], info); here += -2; } } } if (here > *ilst) { goto L20; } } *ilst = here; return 0; // // End of DTREXC // } // dtrexc_ /* -- translated by f2c (version 20201020 (for_lapack)). -- */ //> \brief \b IDAMAX // // =========== DOCUMENTATION =========== // // Online html documentation available at // http://www.netlib.org/lapack/explore-html/ // // Definition: // =========== // // INTEGER FUNCTION IDAMAX(N,DX,INCX) // // .. Scalar Arguments .. // INTEGER INCX,N // .. // .. Array Arguments .. // DOUBLE PRECISION DX(*) // .. // // //> \par Purpose: // ============= //> //> \verbatim //> //> IDAMAX finds the index of the first element having maximum absolute value. //> \endverbatim // // Arguments: // ========== // //> \param[in] N //> \verbatim //> N is INTEGER //> number of elements in input vector(s) //> \endverbatim //> //> \param[in] DX //> \verbatim //> DX is DOUBLE PRECISION array, dimension ( 1 + ( N - 1 )*abs( INCX ) ) //> \endverbatim //> //> \param[in] INCX //> \verbatim //> INCX is INTEGER //> storage spacing between elements of DX //> \endverbatim // // Authors: // ======== // //> \author Univ. of Tennessee //> \author Univ. of California Berkeley //> \author Univ. of Colorado Denver //> \author NAG Ltd. // //> \date November 2017 // //> \ingroup aux_blas // //> \par Further Details: // ===================== //> //> \verbatim //> //> jack dongarra, linpack, 3/11/78. //> modified 3/93 to return if incx .le. 0. //> modified 12/3/93, array(1) declarations changed to array(*) //> \endverbatim //> // ===================================================================== int idamax_(int *n, double *dx, int *incx) { // System generated locals int ret_val, i__1; double d__1; // Local variables int i__, ix; double dmax__; // // -- Reference BLAS level1 routine (version 3.8.0) -- // -- Reference BLAS is a software package provided by Univ. of Tennessee, -- // -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- // November 2017 // // .. Scalar Arguments .. // .. // .. Array Arguments .. // .. // // ===================================================================== // // .. Local Scalars .. // .. // .. Intrinsic Functions .. // .. // Parameter adjustments --dx; // Function Body ret_val = 0; if (*n < 1 || *incx <= 0) { return ret_val; } ret_val = 1; if (*n == 1) { return ret_val; } if (*incx == 1) { // // code for increment equal to 1 // dmax__ = abs(dx[1]); i__1 = *n; for (i__ = 2; i__ <= i__1; ++i__) { if ((d__1 = dx[i__], abs(d__1)) > dmax__) { ret_val = i__; dmax__ = (d__1 = dx[i__], abs(d__1)); } } } else { // // code for increment not equal to 1 // ix = 1; dmax__ = abs(dx[1]); ix += *incx; i__1 = *n; for (i__ = 2; i__ <= i__1; ++i__) { if ((d__1 = dx[ix], abs(d__1)) > dmax__) { ret_val = i__; dmax__ = (d__1 = dx[ix], abs(d__1)); } ix += *incx; } } return ret_val; } // idamax_