/* -- 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_