예제 #1
0
/* Complex */ VOID cladiv_(complex * ret_val, complex *x, complex *y)
{
/*  -- LAPACK auxiliary routine (version 2.0) --   
       Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,   
       Courant Institute, Argonne National Lab, and Rice University   
       October 31, 1992   


    Purpose   
    =======   

    CLADIV := X / Y, where X and Y are complex.  The computation of X / Y 
  
    will not overflow on an intermediary step unless the results   
    overflows.   

    Arguments   
    =========   

    X       (input) COMPLEX   
    Y       (input) COMPLEX   
            The complex scalars X and Y.   

    ===================================================================== 
*/
    /* System generated locals */
    real r__1, r__2, r__3, r__4;
    complex q__1;
    /* Builtin functions */
    double r_imag(complex *);
    /* Local variables */
    static real zi, zr;
    extern /* Subroutine */ int sladiv_(real *, real *, real *, real *, real *
	    , real *);



    r__1 = x->r;
    r__2 = r_imag(x);
    r__3 = y->r;
    r__4 = r_imag(y);
    sladiv_(&r__1, &r__2, &r__3, &r__4, &zr, &zi);
    q__1.r = zr, q__1.i = zi;
     ret_val->r = q__1.r,  ret_val->i = q__1.i;

    return ;

/*     End of CLADIV */

} /* cladiv_ */
예제 #2
0
파일: slaqtr.c 프로젝트: dacap/loseface
/* Subroutine */ int slaqtr_(logical *ltran, logical *lreal, integer *n, real 
	*t, integer *ldt, real *b, real *w, real *scale, real *x, real *work, 
	integer *info)
{
    /* System generated locals */
    integer t_dim1, t_offset, i__1, i__2;
    real r__1, r__2, r__3, r__4, r__5, r__6;

    /* Local variables */
    real d__[4]	/* was [2][2] */;
    integer i__, j, k;
    real v[4]	/* was [2][2] */, z__;
    integer j1, j2, n1, n2;
    real si, xj, sr, rec, eps, tjj, tmp;
    integer ierr;
    real smin;
    extern doublereal sdot_(integer *, real *, integer *, real *, integer *);
    real xmax;
    extern /* Subroutine */ int sscal_(integer *, real *, real *, integer *);
    integer jnext;
    extern doublereal sasum_(integer *, real *, integer *);
    real sminw, xnorm;
    extern /* Subroutine */ int saxpy_(integer *, real *, real *, integer *, 
	    real *, integer *), slaln2_(logical *, integer *, integer *, real 
	    *, real *, real *, integer *, real *, real *, real *, integer *, 
	    real *, real *, real *, integer *, real *, real *, integer *);
    real scaloc;
    extern doublereal slamch_(char *), slange_(char *, integer *, 
	    integer *, real *, integer *, real *);
    real bignum;
    extern integer isamax_(integer *, real *, integer *);
    extern /* Subroutine */ int sladiv_(real *, real *, real *, real *, real *
, real *);
    logical notran;
    real smlnum;


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

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

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

/*  SLAQTR solves the real quasi-triangular system */

/*               op(T)*p = scale*c,               if LREAL = .TRUE. */

/*  or the complex quasi-triangular systems */

/*             op(T + iB)*(p+iq) = scale*(c+id),  if LREAL = .FALSE. */

/*  in real arithmetic, where T is upper quasi-triangular. */
/*  If LREAL = .FALSE., then the first diagonal block of T must be */
/*  1 by 1, B is the specially structured matrix */

/*                 B = [ b(1) b(2) ... b(n) ] */
/*                     [       w            ] */
/*                     [           w        ] */
/*                     [              .     ] */
/*                     [                 w  ] */

/*  op(A) = A or A', A' denotes the conjugate transpose of */
/*  matrix A. */

/*  On input, X = [ c ].  On output, X = [ p ]. */
/*                [ d ]                  [ q ] */

/*  This subroutine is designed for the condition number estimation */
/*  in routine STRSNA. */

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

/*  LTRAN   (input) LOGICAL */
/*          On entry, LTRAN specifies the option of conjugate transpose: */
/*             = .FALSE.,    op(T+i*B) = T+i*B, */
/*             = .TRUE.,     op(T+i*B) = (T+i*B)'. */

/*  LREAL   (input) LOGICAL */
/*          On entry, LREAL specifies the input matrix structure: */
/*             = .FALSE.,    the input is complex */
/*             = .TRUE.,     the input is real */

/*  N       (input) INTEGER */
/*          On entry, N specifies the order of T+i*B. N >= 0. */

/*  T       (input) REAL array, dimension (LDT,N) */
/*          On entry, T contains a matrix in Schur canonical form. */
/*          If LREAL = .FALSE., then the first diagonal block of T must */
/*          be 1 by 1. */

/*  LDT     (input) INTEGER */
/*          The leading dimension of the matrix T. LDT >= max(1,N). */

/*  B       (input) REAL array, dimension (N) */
/*          On entry, B contains the elements to form the matrix */
/*          B as described above. */
/*          If LREAL = .TRUE., B is not referenced. */

/*  W       (input) REAL */
/*          On entry, W is the diagonal element of the matrix B. */
/*          If LREAL = .TRUE., W is not referenced. */

/*  SCALE   (output) REAL */
/*          On exit, SCALE is the scale factor. */

/*  X       (input/output) REAL array, dimension (2*N) */
/*          On entry, X contains the right hand side of the system. */
/*          On exit, X is overwritten by the solution. */

/*  WORK    (workspace) REAL array, dimension (N) */

/*  INFO    (output) INTEGER */
/*          On exit, INFO is set to */
/*             0: successful exit. */
/*               1: the some diagonal 1 by 1 block has been perturbed by */
/*                  a small number SMIN to keep nonsingularity. */
/*               2: the some diagonal 2 by 2 block has been perturbed by */
/*                  a small number in SLALN2 to keep nonsingularity. */
/*          NOTE: In the interests of speed, this routine does not */
/*                check the inputs for errors. */

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

/*     .. Parameters .. */
/*     .. */
/*     .. Local Scalars .. */
/*     .. */
/*     .. Local Arrays .. */
/*     .. */
/*     .. External Functions .. */
/*     .. */
/*     .. External Subroutines .. */
/*     .. */
/*     .. Intrinsic Functions .. */
/*     .. */
/*     .. Executable Statements .. */

/*     Do not test the input parameters for errors */

    /* Parameter adjustments */
    t_dim1 = *ldt;
    t_offset = 1 + t_dim1;
    t -= t_offset;
    --b;
    --x;
    --work;

    /* Function Body */
    notran = ! (*ltran);
    *info = 0;

/*     Quick return if possible */

    if (*n == 0) {
	return 0;
    }

/*     Set constants to control overflow */

    eps = slamch_("P");
    smlnum = slamch_("S") / eps;
    bignum = 1.f / smlnum;

    xnorm = slange_("M", n, n, &t[t_offset], ldt, d__);
    if (! (*lreal)) {
/* Computing MAX */
	r__1 = xnorm, r__2 = dabs(*w), r__1 = max(r__1,r__2), r__2 = slange_(
		"M", n, &c__1, &b[1], n, d__);
	xnorm = dmax(r__1,r__2);
    }
/* Computing MAX */
    r__1 = smlnum, r__2 = eps * xnorm;
    smin = dmax(r__1,r__2);

/*     Compute 1-norm of each column of strictly upper triangular */
/*     part of T to control overflow in triangular solver. */

    work[1] = 0.f;
    i__1 = *n;
    for (j = 2; j <= i__1; ++j) {
	i__2 = j - 1;
	work[j] = sasum_(&i__2, &t[j * t_dim1 + 1], &c__1);
/* L10: */
    }

    if (! (*lreal)) {
	i__1 = *n;
	for (i__ = 2; i__ <= i__1; ++i__) {
	    work[i__] += (r__1 = b[i__], dabs(r__1));
/* L20: */
	}
    }

    n2 = *n << 1;
    n1 = *n;
    if (! (*lreal)) {
	n1 = n2;
    }
    k = isamax_(&n1, &x[1], &c__1);
    xmax = (r__1 = x[k], dabs(r__1));
    *scale = 1.f;

    if (xmax > bignum) {
	*scale = bignum / xmax;
	sscal_(&n1, scale, &x[1], &c__1);
	xmax = bignum;
    }

    if (*lreal) {

	if (notran) {

/*           Solve T*p = scale*c */

	    jnext = *n;
	    for (j = *n; j >= 1; --j) {
		if (j > jnext) {
		    goto L30;
		}
		j1 = j;
		j2 = j;
		jnext = j - 1;
		if (j > 1) {
		    if (t[j + (j - 1) * t_dim1] != 0.f) {
			j1 = j - 1;
			jnext = j - 2;
		    }
		}

		if (j1 == j2) {

/*                 Meet 1 by 1 diagonal block */

/*                 Scale to avoid overflow when computing */
/*                     x(j) = b(j)/T(j,j) */

		    xj = (r__1 = x[j1], dabs(r__1));
		    tjj = (r__1 = t[j1 + j1 * t_dim1], dabs(r__1));
		    tmp = t[j1 + j1 * t_dim1];
		    if (tjj < smin) {
			tmp = smin;
			tjj = smin;
			*info = 1;
		    }

		    if (xj == 0.f) {
			goto L30;
		    }

		    if (tjj < 1.f) {
			if (xj > bignum * tjj) {
			    rec = 1.f / xj;
			    sscal_(n, &rec, &x[1], &c__1);
			    *scale *= rec;
			    xmax *= rec;
			}
		    }
		    x[j1] /= tmp;
		    xj = (r__1 = x[j1], dabs(r__1));

/*                 Scale x if necessary to avoid overflow when adding a */
/*                 multiple of column j1 of T. */

		    if (xj > 1.f) {
			rec = 1.f / xj;
			if (work[j1] > (bignum - xmax) * rec) {
			    sscal_(n, &rec, &x[1], &c__1);
			    *scale *= rec;
			}
		    }
		    if (j1 > 1) {
			i__1 = j1 - 1;
			r__1 = -x[j1];
			saxpy_(&i__1, &r__1, &t[j1 * t_dim1 + 1], &c__1, &x[1]
, &c__1);
			i__1 = j1 - 1;
			k = isamax_(&i__1, &x[1], &c__1);
			xmax = (r__1 = x[k], dabs(r__1));
		    }

		} else {

/*                 Meet 2 by 2 diagonal block */

/*                 Call 2 by 2 linear system solve, to take */
/*                 care of possible overflow by scaling factor. */

		    d__[0] = x[j1];
		    d__[1] = x[j2];
		    slaln2_(&c_false, &c__2, &c__1, &smin, &c_b21, &t[j1 + j1 
			    * t_dim1], ldt, &c_b21, &c_b21, d__, &c__2, &
			    c_b25, &c_b25, v, &c__2, &scaloc, &xnorm, &ierr);
		    if (ierr != 0) {
			*info = 2;
		    }

		    if (scaloc != 1.f) {
			sscal_(n, &scaloc, &x[1], &c__1);
			*scale *= scaloc;
		    }
		    x[j1] = v[0];
		    x[j2] = v[1];

/*                 Scale V(1,1) (= X(J1)) and/or V(2,1) (=X(J2)) */
/*                 to avoid overflow in updating right-hand side. */

/* Computing MAX */
		    r__1 = dabs(v[0]), r__2 = dabs(v[1]);
		    xj = dmax(r__1,r__2);
		    if (xj > 1.f) {
			rec = 1.f / xj;
/* Computing MAX */
			r__1 = work[j1], r__2 = work[j2];
			if (dmax(r__1,r__2) > (bignum - xmax) * rec) {
			    sscal_(n, &rec, &x[1], &c__1);
			    *scale *= rec;
			}
		    }

/*                 Update right-hand side */

		    if (j1 > 1) {
			i__1 = j1 - 1;
			r__1 = -x[j1];
			saxpy_(&i__1, &r__1, &t[j1 * t_dim1 + 1], &c__1, &x[1]
, &c__1);
			i__1 = j1 - 1;
			r__1 = -x[j2];
			saxpy_(&i__1, &r__1, &t[j2 * t_dim1 + 1], &c__1, &x[1]
, &c__1);
			i__1 = j1 - 1;
			k = isamax_(&i__1, &x[1], &c__1);
			xmax = (r__1 = x[k], dabs(r__1));
		    }

		}

L30:
		;
	    }

	} else {

/*           Solve T'*p = scale*c */

	    jnext = 1;
	    i__1 = *n;
	    for (j = 1; j <= i__1; ++j) {
		if (j < jnext) {
		    goto L40;
		}
		j1 = j;
		j2 = j;
		jnext = j + 1;
		if (j < *n) {
		    if (t[j + 1 + j * t_dim1] != 0.f) {
			j2 = j + 1;
			jnext = j + 2;
		    }
		}

		if (j1 == j2) {

/*                 1 by 1 diagonal block */

/*                 Scale if necessary to avoid overflow in forming the */
/*                 right-hand side element by inner product. */

		    xj = (r__1 = x[j1], dabs(r__1));
		    if (xmax > 1.f) {
			rec = 1.f / xmax;
			if (work[j1] > (bignum - xj) * rec) {
			    sscal_(n, &rec, &x[1], &c__1);
			    *scale *= rec;
			    xmax *= rec;
			}
		    }

		    i__2 = j1 - 1;
		    x[j1] -= sdot_(&i__2, &t[j1 * t_dim1 + 1], &c__1, &x[1], &
			    c__1);

		    xj = (r__1 = x[j1], dabs(r__1));
		    tjj = (r__1 = t[j1 + j1 * t_dim1], dabs(r__1));
		    tmp = t[j1 + j1 * t_dim1];
		    if (tjj < smin) {
			tmp = smin;
			tjj = smin;
			*info = 1;
		    }

		    if (tjj < 1.f) {
			if (xj > bignum * tjj) {
			    rec = 1.f / xj;
			    sscal_(n, &rec, &x[1], &c__1);
			    *scale *= rec;
			    xmax *= rec;
			}
		    }
		    x[j1] /= tmp;
/* Computing MAX */
		    r__2 = xmax, r__3 = (r__1 = x[j1], dabs(r__1));
		    xmax = dmax(r__2,r__3);

		} else {

/*                 2 by 2 diagonal block */

/*                 Scale if necessary to avoid overflow in forming the */
/*                 right-hand side elements by inner product. */

/* Computing MAX */
		    r__3 = (r__1 = x[j1], dabs(r__1)), r__4 = (r__2 = x[j2], 
			    dabs(r__2));
		    xj = dmax(r__3,r__4);
		    if (xmax > 1.f) {
			rec = 1.f / xmax;
/* Computing MAX */
			r__1 = work[j2], r__2 = work[j1];
			if (dmax(r__1,r__2) > (bignum - xj) * rec) {
			    sscal_(n, &rec, &x[1], &c__1);
			    *scale *= rec;
			    xmax *= rec;
			}
		    }

		    i__2 = j1 - 1;
		    d__[0] = x[j1] - sdot_(&i__2, &t[j1 * t_dim1 + 1], &c__1, 
			    &x[1], &c__1);
		    i__2 = j1 - 1;
		    d__[1] = x[j2] - sdot_(&i__2, &t[j2 * t_dim1 + 1], &c__1, 
			    &x[1], &c__1);

		    slaln2_(&c_true, &c__2, &c__1, &smin, &c_b21, &t[j1 + j1 *
			     t_dim1], ldt, &c_b21, &c_b21, d__, &c__2, &c_b25, 
			     &c_b25, v, &c__2, &scaloc, &xnorm, &ierr);
		    if (ierr != 0) {
			*info = 2;
		    }

		    if (scaloc != 1.f) {
			sscal_(n, &scaloc, &x[1], &c__1);
			*scale *= scaloc;
		    }
		    x[j1] = v[0];
		    x[j2] = v[1];
/* Computing MAX */
		    r__3 = (r__1 = x[j1], dabs(r__1)), r__4 = (r__2 = x[j2], 
			    dabs(r__2)), r__3 = max(r__3,r__4);
		    xmax = dmax(r__3,xmax);

		}
L40:
		;
	    }
	}

    } else {

/* Computing MAX */
	r__1 = eps * dabs(*w);
	sminw = dmax(r__1,smin);
	if (notran) {

/*           Solve (T + iB)*(p+iq) = c+id */

	    jnext = *n;
	    for (j = *n; j >= 1; --j) {
		if (j > jnext) {
		    goto L70;
		}
		j1 = j;
		j2 = j;
		jnext = j - 1;
		if (j > 1) {
		    if (t[j + (j - 1) * t_dim1] != 0.f) {
			j1 = j - 1;
			jnext = j - 2;
		    }
		}

		if (j1 == j2) {

/*                 1 by 1 diagonal block */

/*                 Scale if necessary to avoid overflow in division */

		    z__ = *w;
		    if (j1 == 1) {
			z__ = b[1];
		    }
		    xj = (r__1 = x[j1], dabs(r__1)) + (r__2 = x[*n + j1], 
			    dabs(r__2));
		    tjj = (r__1 = t[j1 + j1 * t_dim1], dabs(r__1)) + dabs(z__)
			    ;
		    tmp = t[j1 + j1 * t_dim1];
		    if (tjj < sminw) {
			tmp = sminw;
			tjj = sminw;
			*info = 1;
		    }

		    if (xj == 0.f) {
			goto L70;
		    }

		    if (tjj < 1.f) {
			if (xj > bignum * tjj) {
			    rec = 1.f / xj;
			    sscal_(&n2, &rec, &x[1], &c__1);
			    *scale *= rec;
			    xmax *= rec;
			}
		    }
		    sladiv_(&x[j1], &x[*n + j1], &tmp, &z__, &sr, &si);
		    x[j1] = sr;
		    x[*n + j1] = si;
		    xj = (r__1 = x[j1], dabs(r__1)) + (r__2 = x[*n + j1], 
			    dabs(r__2));

/*                 Scale x if necessary to avoid overflow when adding a */
/*                 multiple of column j1 of T. */

		    if (xj > 1.f) {
			rec = 1.f / xj;
			if (work[j1] > (bignum - xmax) * rec) {
			    sscal_(&n2, &rec, &x[1], &c__1);
			    *scale *= rec;
			}
		    }

		    if (j1 > 1) {
			i__1 = j1 - 1;
			r__1 = -x[j1];
			saxpy_(&i__1, &r__1, &t[j1 * t_dim1 + 1], &c__1, &x[1]
, &c__1);
			i__1 = j1 - 1;
			r__1 = -x[*n + j1];
			saxpy_(&i__1, &r__1, &t[j1 * t_dim1 + 1], &c__1, &x[*
				n + 1], &c__1);

			x[1] += b[j1] * x[*n + j1];
			x[*n + 1] -= b[j1] * x[j1];

			xmax = 0.f;
			i__1 = j1 - 1;
			for (k = 1; k <= i__1; ++k) {
/* Computing MAX */
			    r__3 = xmax, r__4 = (r__1 = x[k], dabs(r__1)) + (
				    r__2 = x[k + *n], dabs(r__2));
			    xmax = dmax(r__3,r__4);
/* L50: */
			}
		    }

		} else {

/*                 Meet 2 by 2 diagonal block */

		    d__[0] = x[j1];
		    d__[1] = x[j2];
		    d__[2] = x[*n + j1];
		    d__[3] = x[*n + j2];
		    r__1 = -(*w);
		    slaln2_(&c_false, &c__2, &c__2, &sminw, &c_b21, &t[j1 + 
			    j1 * t_dim1], ldt, &c_b21, &c_b21, d__, &c__2, &
			    c_b25, &r__1, v, &c__2, &scaloc, &xnorm, &ierr);
		    if (ierr != 0) {
			*info = 2;
		    }

		    if (scaloc != 1.f) {
			i__1 = *n << 1;
			sscal_(&i__1, &scaloc, &x[1], &c__1);
			*scale = scaloc * *scale;
		    }
		    x[j1] = v[0];
		    x[j2] = v[1];
		    x[*n + j1] = v[2];
		    x[*n + j2] = v[3];

/*                 Scale X(J1), .... to avoid overflow in */
/*                 updating right hand side. */

/* Computing MAX */
		    r__1 = dabs(v[0]) + dabs(v[2]), r__2 = dabs(v[1]) + dabs(
			    v[3]);
		    xj = dmax(r__1,r__2);
		    if (xj > 1.f) {
			rec = 1.f / xj;
/* Computing MAX */
			r__1 = work[j1], r__2 = work[j2];
			if (dmax(r__1,r__2) > (bignum - xmax) * rec) {
			    sscal_(&n2, &rec, &x[1], &c__1);
			    *scale *= rec;
			}
		    }

/*                 Update the right-hand side. */

		    if (j1 > 1) {
			i__1 = j1 - 1;
			r__1 = -x[j1];
			saxpy_(&i__1, &r__1, &t[j1 * t_dim1 + 1], &c__1, &x[1]
, &c__1);
			i__1 = j1 - 1;
			r__1 = -x[j2];
			saxpy_(&i__1, &r__1, &t[j2 * t_dim1 + 1], &c__1, &x[1]
, &c__1);

			i__1 = j1 - 1;
			r__1 = -x[*n + j1];
			saxpy_(&i__1, &r__1, &t[j1 * t_dim1 + 1], &c__1, &x[*
				n + 1], &c__1);
			i__1 = j1 - 1;
			r__1 = -x[*n + j2];
			saxpy_(&i__1, &r__1, &t[j2 * t_dim1 + 1], &c__1, &x[*
				n + 1], &c__1);

			x[1] = x[1] + b[j1] * x[*n + j1] + b[j2] * x[*n + j2];
			x[*n + 1] = x[*n + 1] - b[j1] * x[j1] - b[j2] * x[j2];

			xmax = 0.f;
			i__1 = j1 - 1;
			for (k = 1; k <= i__1; ++k) {
/* Computing MAX */
			    r__3 = (r__1 = x[k], dabs(r__1)) + (r__2 = x[k + *
				    n], dabs(r__2));
			    xmax = dmax(r__3,xmax);
/* L60: */
			}
		    }

		}
L70:
		;
	    }

	} else {

/*           Solve (T + iB)'*(p+iq) = c+id */

	    jnext = 1;
	    i__1 = *n;
	    for (j = 1; j <= i__1; ++j) {
		if (j < jnext) {
		    goto L80;
		}
		j1 = j;
		j2 = j;
		jnext = j + 1;
		if (j < *n) {
		    if (t[j + 1 + j * t_dim1] != 0.f) {
			j2 = j + 1;
			jnext = j + 2;
		    }
		}

		if (j1 == j2) {

/*                 1 by 1 diagonal block */

/*                 Scale if necessary to avoid overflow in forming the */
/*                 right-hand side element by inner product. */

		    xj = (r__1 = x[j1], dabs(r__1)) + (r__2 = x[j1 + *n], 
			    dabs(r__2));
		    if (xmax > 1.f) {
			rec = 1.f / xmax;
			if (work[j1] > (bignum - xj) * rec) {
			    sscal_(&n2, &rec, &x[1], &c__1);
			    *scale *= rec;
			    xmax *= rec;
			}
		    }

		    i__2 = j1 - 1;
		    x[j1] -= sdot_(&i__2, &t[j1 * t_dim1 + 1], &c__1, &x[1], &
			    c__1);
		    i__2 = j1 - 1;
		    x[*n + j1] -= sdot_(&i__2, &t[j1 * t_dim1 + 1], &c__1, &x[
			    *n + 1], &c__1);
		    if (j1 > 1) {
			x[j1] -= b[j1] * x[*n + 1];
			x[*n + j1] += b[j1] * x[1];
		    }
		    xj = (r__1 = x[j1], dabs(r__1)) + (r__2 = x[j1 + *n], 
			    dabs(r__2));

		    z__ = *w;
		    if (j1 == 1) {
			z__ = b[1];
		    }

/*                 Scale if necessary to avoid overflow in */
/*                 complex division */

		    tjj = (r__1 = t[j1 + j1 * t_dim1], dabs(r__1)) + dabs(z__)
			    ;
		    tmp = t[j1 + j1 * t_dim1];
		    if (tjj < sminw) {
			tmp = sminw;
			tjj = sminw;
			*info = 1;
		    }

		    if (tjj < 1.f) {
			if (xj > bignum * tjj) {
			    rec = 1.f / xj;
			    sscal_(&n2, &rec, &x[1], &c__1);
			    *scale *= rec;
			    xmax *= rec;
			}
		    }
		    r__1 = -z__;
		    sladiv_(&x[j1], &x[*n + j1], &tmp, &r__1, &sr, &si);
		    x[j1] = sr;
		    x[j1 + *n] = si;
/* Computing MAX */
		    r__3 = (r__1 = x[j1], dabs(r__1)) + (r__2 = x[j1 + *n], 
			    dabs(r__2));
		    xmax = dmax(r__3,xmax);

		} else {

/*                 2 by 2 diagonal block */

/*                 Scale if necessary to avoid overflow in forming the */
/*                 right-hand side element by inner product. */

/* Computing MAX */
		    r__5 = (r__1 = x[j1], dabs(r__1)) + (r__2 = x[*n + j1], 
			    dabs(r__2)), r__6 = (r__3 = x[j2], dabs(r__3)) + (
			    r__4 = x[*n + j2], dabs(r__4));
		    xj = dmax(r__5,r__6);
		    if (xmax > 1.f) {
			rec = 1.f / xmax;
/* Computing MAX */
			r__1 = work[j1], r__2 = work[j2];
			if (dmax(r__1,r__2) > (bignum - xj) / xmax) {
			    sscal_(&n2, &rec, &x[1], &c__1);
			    *scale *= rec;
			    xmax *= rec;
			}
		    }

		    i__2 = j1 - 1;
		    d__[0] = x[j1] - sdot_(&i__2, &t[j1 * t_dim1 + 1], &c__1, 
			    &x[1], &c__1);
		    i__2 = j1 - 1;
		    d__[1] = x[j2] - sdot_(&i__2, &t[j2 * t_dim1 + 1], &c__1, 
			    &x[1], &c__1);
		    i__2 = j1 - 1;
		    d__[2] = x[*n + j1] - sdot_(&i__2, &t[j1 * t_dim1 + 1], &
			    c__1, &x[*n + 1], &c__1);
		    i__2 = j1 - 1;
		    d__[3] = x[*n + j2] - sdot_(&i__2, &t[j2 * t_dim1 + 1], &
			    c__1, &x[*n + 1], &c__1);
		    d__[0] -= b[j1] * x[*n + 1];
		    d__[1] -= b[j2] * x[*n + 1];
		    d__[2] += b[j1] * x[1];
		    d__[3] += b[j2] * x[1];

		    slaln2_(&c_true, &c__2, &c__2, &sminw, &c_b21, &t[j1 + j1 
			    * t_dim1], ldt, &c_b21, &c_b21, d__, &c__2, &
			    c_b25, w, v, &c__2, &scaloc, &xnorm, &ierr);
		    if (ierr != 0) {
			*info = 2;
		    }

		    if (scaloc != 1.f) {
			sscal_(&n2, &scaloc, &x[1], &c__1);
			*scale = scaloc * *scale;
		    }
		    x[j1] = v[0];
		    x[j2] = v[1];
		    x[*n + j1] = v[2];
		    x[*n + j2] = v[3];
/* Computing MAX */
		    r__5 = (r__1 = x[j1], dabs(r__1)) + (r__2 = x[*n + j1], 
			    dabs(r__2)), r__6 = (r__3 = x[j2], dabs(r__3)) + (
			    r__4 = x[*n + j2], dabs(r__4)), r__5 = max(r__5,
			    r__6);
		    xmax = dmax(r__5,xmax);

		}

L80:
		;
	    }

	}

    }

    return 0;

/*     End of SLAQTR */

} /* slaqtr_ */
예제 #3
0
파일: slaein.c 프로젝트: flame/libflame
/* Subroutine */
int slaein_(logical *rightv, logical *noinit, integer *n, real *h__, integer *ldh, real *wr, real *wi, real *vr, real *vi, real *b, integer *ldb, real *work, real *eps3, real *smlnum, real *bignum, integer *info)
{
    /* System generated locals */
    integer b_dim1, b_offset, h_dim1, h_offset, i__1, i__2, i__3, i__4;
    real r__1, r__2, r__3, r__4;
    /* Builtin functions */
    double sqrt(doublereal);
    /* Local variables */
    integer i__, j;
    real w, x, y;
    integer i1, i2, i3;
    real w1, ei, ej, xi, xr, rec;
    integer its, ierr;
    real temp, norm, vmax;
    extern real snrm2_(integer *, real *, integer *);
    real scale;
    extern /* Subroutine */
    int sscal_(integer *, real *, real *, integer *);
    char trans[1];
    real vcrit;
    extern real sasum_(integer *, real *, integer *);
    real rootn, vnorm;
    extern real slapy2_(real *, real *);
    real absbii, absbjj;
    extern integer isamax_(integer *, real *, integer *);
    extern /* Subroutine */
    int sladiv_(real *, real *, real *, real *, real * , real *);
    char normin[1];
    real nrmsml;
    extern /* Subroutine */
    int slatrs_(char *, char *, char *, char *, integer *, real *, integer *, real *, real *, real *, integer *);
    real growto;
    /* -- LAPACK auxiliary routine (version 3.4.2) -- */
    /* -- LAPACK is a software package provided by Univ. of Tennessee, -- */
    /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */
    /* September 2012 */
    /* .. Scalar Arguments .. */
    /* .. */
    /* .. Array Arguments .. */
    /* .. */
    /* ===================================================================== */
    /* .. Parameters .. */
    /* .. */
    /* .. Local Scalars .. */
    /* .. */
    /* .. External Functions .. */
    /* .. */
    /* .. External Subroutines .. */
    /* .. */
    /* .. Intrinsic Functions .. */
    /* .. */
    /* .. Executable Statements .. */
    /* Parameter adjustments */
    h_dim1 = *ldh;
    h_offset = 1 + h_dim1;
    h__ -= h_offset;
    --vr;
    --vi;
    b_dim1 = *ldb;
    b_offset = 1 + b_dim1;
    b -= b_offset;
    --work;
    /* Function Body */
    *info = 0;
    /* GROWTO is the threshold used in the acceptance test for an */
    /* eigenvector. */
    rootn = sqrt((real) (*n));
    growto = .1f / rootn;
    /* Computing MAX */
    r__1 = 1.f;
    r__2 = *eps3 * rootn; // , expr subst
    nrmsml = max(r__1,r__2) * *smlnum;
    /* Form B = H - (WR,WI)*I (except that the subdiagonal elements and */
    /* the imaginary parts of the diagonal elements are not stored). */
    i__1 = *n;
    for (j = 1;
            j <= i__1;
            ++j)
    {
        i__2 = j - 1;
        for (i__ = 1;
                i__ <= i__2;
                ++i__)
        {
            b[i__ + j * b_dim1] = h__[i__ + j * h_dim1];
            /* L10: */
        }
        b[j + j * b_dim1] = h__[j + j * h_dim1] - *wr;
        /* L20: */
    }
    if (*wi == 0.f)
    {
        /* Real eigenvalue. */
        if (*noinit)
        {
            /* Set initial vector. */
            i__1 = *n;
            for (i__ = 1;
                    i__ <= i__1;
                    ++i__)
            {
                vr[i__] = *eps3;
                /* L30: */
            }
        }
        else
        {
            /* Scale supplied initial vector. */
            vnorm = snrm2_(n, &vr[1], &c__1);
            r__1 = *eps3 * rootn / max(vnorm,nrmsml);
            sscal_(n, &r__1, &vr[1], &c__1);
        }
        if (*rightv)
        {
            /* LU decomposition with partial pivoting of B, replacing zero */
            /* pivots by EPS3. */
            i__1 = *n - 1;
            for (i__ = 1;
                    i__ <= i__1;
                    ++i__)
            {
                ei = h__[i__ + 1 + i__ * h_dim1];
                if ((r__1 = b[i__ + i__ * b_dim1], f2c_abs(r__1)) < f2c_abs(ei))
                {
                    /* Interchange rows and eliminate. */
                    x = b[i__ + i__ * b_dim1] / ei;
                    b[i__ + i__ * b_dim1] = ei;
                    i__2 = *n;
                    for (j = i__ + 1;
                            j <= i__2;
                            ++j)
                    {
                        temp = b[i__ + 1 + j * b_dim1];
                        b[i__ + 1 + j * b_dim1] = b[i__ + j * b_dim1] - x * temp;
                        b[i__ + j * b_dim1] = temp;
                        /* L40: */
                    }
                }
                else
                {
                    /* Eliminate without interchange. */
                    if (b[i__ + i__ * b_dim1] == 0.f)
                    {
                        b[i__ + i__ * b_dim1] = *eps3;
                    }
                    x = ei / b[i__ + i__ * b_dim1];
                    if (x != 0.f)
                    {
                        i__2 = *n;
                        for (j = i__ + 1;
                                j <= i__2;
                                ++j)
                        {
                            b[i__ + 1 + j * b_dim1] -= x * b[i__ + j * b_dim1] ;
                            /* L50: */
                        }
                    }
                }
                /* L60: */
            }
            if (b[*n + *n * b_dim1] == 0.f)
            {
                b[*n + *n * b_dim1] = *eps3;
            }
            *(unsigned char *)trans = 'N';
        }
        else
        {
            /* UL decomposition with partial pivoting of B, replacing zero */
            /* pivots by EPS3. */
            for (j = *n;
                    j >= 2;
                    --j)
            {
                ej = h__[j + (j - 1) * h_dim1];
                if ((r__1 = b[j + j * b_dim1], f2c_abs(r__1)) < f2c_abs(ej))
                {
                    /* Interchange columns and eliminate. */
                    x = b[j + j * b_dim1] / ej;
                    b[j + j * b_dim1] = ej;
                    i__1 = j - 1;
                    for (i__ = 1;
                            i__ <= i__1;
                            ++i__)
                    {
                        temp = b[i__ + (j - 1) * b_dim1];
                        b[i__ + (j - 1) * b_dim1] = b[i__ + j * b_dim1] - x * temp;
                        b[i__ + j * b_dim1] = temp;
                        /* L70: */
                    }
                }
                else
                {
                    /* Eliminate without interchange. */
                    if (b[j + j * b_dim1] == 0.f)
                    {
                        b[j + j * b_dim1] = *eps3;
                    }
                    x = ej / b[j + j * b_dim1];
                    if (x != 0.f)
                    {
                        i__1 = j - 1;
                        for (i__ = 1;
                                i__ <= i__1;
                                ++i__)
                        {
                            b[i__ + (j - 1) * b_dim1] -= x * b[i__ + j * b_dim1];
                            /* L80: */
                        }
                    }
                }
                /* L90: */
            }
            if (b[b_dim1 + 1] == 0.f)
            {
                b[b_dim1 + 1] = *eps3;
            }
            *(unsigned char *)trans = 'T';
        }
        *(unsigned char *)normin = 'N';
        i__1 = *n;
        for (its = 1;
                its <= i__1;
                ++its)
        {
            /* Solve U*x = scale*v for a right eigenvector */
            /* or U**T*x = scale*v for a left eigenvector, */
            /* overwriting x on v. */
            slatrs_("Upper", trans, "Nonunit", normin, n, &b[b_offset], ldb, & vr[1], &scale, &work[1], &ierr);
            *(unsigned char *)normin = 'Y';
            /* Test for sufficient growth in the norm of v. */
            vnorm = sasum_(n, &vr[1], &c__1);
            if (vnorm >= growto * scale)
            {
                goto L120;
            }
            /* Choose new orthogonal starting vector and try again. */
            temp = *eps3 / (rootn + 1.f);
            vr[1] = *eps3;
            i__2 = *n;
            for (i__ = 2;
                    i__ <= i__2;
                    ++i__)
            {
                vr[i__] = temp;
                /* L100: */
            }
            vr[*n - its + 1] -= *eps3 * rootn;
            /* L110: */
        }
        /* Failure to find eigenvector in N iterations. */
        *info = 1;
L120: /* Normalize eigenvector. */
        i__ = isamax_(n, &vr[1], &c__1);
        r__2 = 1.f / (r__1 = vr[i__], f2c_abs(r__1));
        sscal_(n, &r__2, &vr[1], &c__1);
    }
    else
    {
        /* Complex eigenvalue. */
        if (*noinit)
        {
            /* Set initial vector. */
            i__1 = *n;
            for (i__ = 1;
                    i__ <= i__1;
                    ++i__)
            {
                vr[i__] = *eps3;
                vi[i__] = 0.f;
                /* L130: */
            }
        }
        else
        {
            /* Scale supplied initial vector. */
            r__1 = snrm2_(n, &vr[1], &c__1);
            r__2 = snrm2_(n, &vi[1], &c__1);
            norm = slapy2_(&r__1, &r__2);
            rec = *eps3 * rootn / max(norm,nrmsml);
            sscal_(n, &rec, &vr[1], &c__1);
            sscal_(n, &rec, &vi[1], &c__1);
        }
        if (*rightv)
        {
            /* LU decomposition with partial pivoting of B, replacing zero */
            /* pivots by EPS3. */
            /* The imaginary part of the (i,j)-th element of U is stored in */
            /* B(j+1,i). */
            b[b_dim1 + 2] = -(*wi);
            i__1 = *n;
            for (i__ = 2;
                    i__ <= i__1;
                    ++i__)
            {
                b[i__ + 1 + b_dim1] = 0.f;
                /* L140: */
            }
            i__1 = *n - 1;
            for (i__ = 1;
                    i__ <= i__1;
                    ++i__)
            {
                absbii = slapy2_(&b[i__ + i__ * b_dim1], &b[i__ + 1 + i__ * b_dim1]);
                ei = h__[i__ + 1 + i__ * h_dim1];
                if (absbii < f2c_abs(ei))
                {
                    /* Interchange rows and eliminate. */
                    xr = b[i__ + i__ * b_dim1] / ei;
                    xi = b[i__ + 1 + i__ * b_dim1] / ei;
                    b[i__ + i__ * b_dim1] = ei;
                    b[i__ + 1 + i__ * b_dim1] = 0.f;
                    i__2 = *n;
                    for (j = i__ + 1;
                            j <= i__2;
                            ++j)
                    {
                        temp = b[i__ + 1 + j * b_dim1];
                        b[i__ + 1 + j * b_dim1] = b[i__ + j * b_dim1] - xr * temp;
                        b[j + 1 + (i__ + 1) * b_dim1] = b[j + 1 + i__ * b_dim1] - xi * temp;
                        b[i__ + j * b_dim1] = temp;
                        b[j + 1 + i__ * b_dim1] = 0.f;
                        /* L150: */
                    }
                    b[i__ + 2 + i__ * b_dim1] = -(*wi);
                    b[i__ + 1 + (i__ + 1) * b_dim1] -= xi * *wi;
                    b[i__ + 2 + (i__ + 1) * b_dim1] += xr * *wi;
                }
                else
                {
                    /* Eliminate without interchanging rows. */
                    if (absbii == 0.f)
                    {
                        b[i__ + i__ * b_dim1] = *eps3;
                        b[i__ + 1 + i__ * b_dim1] = 0.f;
                        absbii = *eps3;
                    }
                    ei = ei / absbii / absbii;
                    xr = b[i__ + i__ * b_dim1] * ei;
                    xi = -b[i__ + 1 + i__ * b_dim1] * ei;
                    i__2 = *n;
                    for (j = i__ + 1;
                            j <= i__2;
                            ++j)
                    {
                        b[i__ + 1 + j * b_dim1] = b[i__ + 1 + j * b_dim1] - xr * b[i__ + j * b_dim1] + xi * b[j + 1 + i__ * b_dim1];
                        b[j + 1 + (i__ + 1) * b_dim1] = -xr * b[j + 1 + i__ * b_dim1] - xi * b[i__ + j * b_dim1];
                        /* L160: */
                    }
                    b[i__ + 2 + (i__ + 1) * b_dim1] -= *wi;
                }
                /* Compute 1-norm of offdiagonal elements of i-th row. */
                i__2 = *n - i__;
                i__3 = *n - i__;
                work[i__] = sasum_(&i__2, &b[i__ + (i__ + 1) * b_dim1], ldb) + sasum_(&i__3, &b[i__ + 2 + i__ * b_dim1], &c__1);
                /* L170: */
            }
            if (b[*n + *n * b_dim1] == 0.f && b[*n + 1 + *n * b_dim1] == 0.f)
            {
                b[*n + *n * b_dim1] = *eps3;
            }
            work[*n] = 0.f;
            i1 = *n;
            i2 = 1;
            i3 = -1;
        }
        else
        {
            /* UL decomposition with partial pivoting of conjg(B), */
            /* replacing zero pivots by EPS3. */
            /* The imaginary part of the (i,j)-th element of U is stored in */
            /* B(j+1,i). */
            b[*n + 1 + *n * b_dim1] = *wi;
            i__1 = *n - 1;
            for (j = 1;
                    j <= i__1;
                    ++j)
            {
                b[*n + 1 + j * b_dim1] = 0.f;
                /* L180: */
            }
            for (j = *n;
                    j >= 2;
                    --j)
            {
                ej = h__[j + (j - 1) * h_dim1];
                absbjj = slapy2_(&b[j + j * b_dim1], &b[j + 1 + j * b_dim1]);
                if (absbjj < f2c_abs(ej))
                {
                    /* Interchange columns and eliminate */
                    xr = b[j + j * b_dim1] / ej;
                    xi = b[j + 1 + j * b_dim1] / ej;
                    b[j + j * b_dim1] = ej;
                    b[j + 1 + j * b_dim1] = 0.f;
                    i__1 = j - 1;
                    for (i__ = 1;
                            i__ <= i__1;
                            ++i__)
                    {
                        temp = b[i__ + (j - 1) * b_dim1];
                        b[i__ + (j - 1) * b_dim1] = b[i__ + j * b_dim1] - xr * temp;
                        b[j + i__ * b_dim1] = b[j + 1 + i__ * b_dim1] - xi * temp;
                        b[i__ + j * b_dim1] = temp;
                        b[j + 1 + i__ * b_dim1] = 0.f;
                        /* L190: */
                    }
                    b[j + 1 + (j - 1) * b_dim1] = *wi;
                    b[j - 1 + (j - 1) * b_dim1] += xi * *wi;
                    b[j + (j - 1) * b_dim1] -= xr * *wi;
                }
                else
                {
                    /* Eliminate without interchange. */
                    if (absbjj == 0.f)
                    {
                        b[j + j * b_dim1] = *eps3;
                        b[j + 1 + j * b_dim1] = 0.f;
                        absbjj = *eps3;
                    }
                    ej = ej / absbjj / absbjj;
                    xr = b[j + j * b_dim1] * ej;
                    xi = -b[j + 1 + j * b_dim1] * ej;
                    i__1 = j - 1;
                    for (i__ = 1;
                            i__ <= i__1;
                            ++i__)
                    {
                        b[i__ + (j - 1) * b_dim1] = b[i__ + (j - 1) * b_dim1] - xr * b[i__ + j * b_dim1] + xi * b[j + 1 + i__ * b_dim1];
                        b[j + i__ * b_dim1] = -xr * b[j + 1 + i__ * b_dim1] - xi * b[i__ + j * b_dim1];
                        /* L200: */
                    }
                    b[j + (j - 1) * b_dim1] += *wi;
                }
                /* Compute 1-norm of offdiagonal elements of j-th column. */
                i__1 = j - 1;
                i__2 = j - 1;
                work[j] = sasum_(&i__1, &b[j * b_dim1 + 1], &c__1) + sasum_(& i__2, &b[j + 1 + b_dim1], ldb);
                /* L210: */
            }
            if (b[b_dim1 + 1] == 0.f && b[b_dim1 + 2] == 0.f)
            {
                b[b_dim1 + 1] = *eps3;
            }
            work[1] = 0.f;
            i1 = 1;
            i2 = *n;
            i3 = 1;
        }
        i__1 = *n;
        for (its = 1;
                its <= i__1;
                ++its)
        {
            scale = 1.f;
            vmax = 1.f;
            vcrit = *bignum;
            /* Solve U*(xr,xi) = scale*(vr,vi) for a right eigenvector, */
            /* or U**T*(xr,xi) = scale*(vr,vi) for a left eigenvector, */
            /* overwriting (xr,xi) on (vr,vi). */
            i__2 = i2;
            i__3 = i3;
            for (i__ = i1;
                    i__3 < 0 ? i__ >= i__2 : i__ <= i__2;
                    i__ += i__3)
            {
                if (work[i__] > vcrit)
                {
                    rec = 1.f / vmax;
                    sscal_(n, &rec, &vr[1], &c__1);
                    sscal_(n, &rec, &vi[1], &c__1);
                    scale *= rec;
                    vmax = 1.f;
                    vcrit = *bignum;
                }
                xr = vr[i__];
                xi = vi[i__];
                if (*rightv)
                {
                    i__4 = *n;
                    for (j = i__ + 1;
                            j <= i__4;
                            ++j)
                    {
                        xr = xr - b[i__ + j * b_dim1] * vr[j] + b[j + 1 + i__ * b_dim1] * vi[j];
                        xi = xi - b[i__ + j * b_dim1] * vi[j] - b[j + 1 + i__ * b_dim1] * vr[j];
                        /* L220: */
                    }
                }
                else
                {
                    i__4 = i__ - 1;
                    for (j = 1;
                            j <= i__4;
                            ++j)
                    {
                        xr = xr - b[j + i__ * b_dim1] * vr[j] + b[i__ + 1 + j * b_dim1] * vi[j];
                        xi = xi - b[j + i__ * b_dim1] * vi[j] - b[i__ + 1 + j * b_dim1] * vr[j];
                        /* L230: */
                    }
                }
                w = (r__1 = b[i__ + i__ * b_dim1], f2c_abs(r__1)) + (r__2 = b[i__ + 1 + i__ * b_dim1], f2c_abs(r__2));
                if (w > *smlnum)
                {
                    if (w < 1.f)
                    {
                        w1 = f2c_abs(xr) + f2c_abs(xi);
                        if (w1 > w * *bignum)
                        {
                            rec = 1.f / w1;
                            sscal_(n, &rec, &vr[1], &c__1);
                            sscal_(n, &rec, &vi[1], &c__1);
                            xr = vr[i__];
                            xi = vi[i__];
                            scale *= rec;
                            vmax *= rec;
                        }
                    }
                    /* Divide by diagonal element of B. */
                    sladiv_(&xr, &xi, &b[i__ + i__ * b_dim1], &b[i__ + 1 + i__ * b_dim1], &vr[i__], &vi[i__]);
                    /* Computing MAX */
                    r__3 = (r__1 = vr[i__], f2c_abs(r__1)) + (r__2 = vi[i__], f2c_abs( r__2));
                    vmax = max(r__3,vmax);
                    vcrit = *bignum / vmax;
                }
                else
                {
                    i__4 = *n;
                    for (j = 1;
                            j <= i__4;
                            ++j)
                    {
                        vr[j] = 0.f;
                        vi[j] = 0.f;
                        /* L240: */
                    }
                    vr[i__] = 1.f;
                    vi[i__] = 1.f;
                    scale = 0.f;
                    vmax = 1.f;
                    vcrit = *bignum;
                }
                /* L250: */
            }
            /* Test for sufficient growth in the norm of (VR,VI). */
            vnorm = sasum_(n, &vr[1], &c__1) + sasum_(n, &vi[1], &c__1);
            if (vnorm >= growto * scale)
            {
                goto L280;
            }
            /* Choose a new orthogonal starting vector and try again. */
            y = *eps3 / (rootn + 1.f);
            vr[1] = *eps3;
            vi[1] = 0.f;
            i__3 = *n;
            for (i__ = 2;
                    i__ <= i__3;
                    ++i__)
            {
                vr[i__] = y;
                vi[i__] = 0.f;
                /* L260: */
            }
            vr[*n - its + 1] -= *eps3 * rootn;
            /* L270: */
        }
        /* Failure to find eigenvector in N iterations */
        *info = 1;
L280: /* Normalize eigenvector. */
        vnorm = 0.f;
        i__1 = *n;
        for (i__ = 1;
                i__ <= i__1;
                ++i__)
        {
            /* Computing MAX */
            r__3 = vnorm;
            r__4 = (r__1 = vr[i__], f2c_abs(r__1)) + (r__2 = vi[i__] , f2c_abs(r__2)); // , expr subst
            vnorm = max(r__3,r__4);
            /* L290: */
        }
        r__1 = 1.f / vnorm;
        sscal_(n, &r__1, &vr[1], &c__1);
        r__1 = 1.f / vnorm;
        sscal_(n, &r__1, &vi[1], &c__1);
    }
    return 0;
    /* End of SLAEIN */
}
예제 #4
0
/* Subroutine */ int slaln2_(logical *ltrans, integer *na, integer *nw, real *
	smin, real *ca, real *a, integer *lda, real *d1, real *d2, real *b, 
	integer *ldb, real *wr, real *wi, real *x, integer *ldx, real *scale, 
	real *xnorm, integer *info)
{
/*  -- LAPACK auxiliary routine (version 2.0) --   
       Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,   
       Courant Institute, Argonne National Lab, and Rice University   
       October 31, 1992   


    Purpose   
    =======   

    SLALN2 solves a system of the form  (ca A - w D ) X = s B   
    or (ca A' - w D) X = s B   with possible scaling ("s") and   
    perturbation of A.  (A' 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 (.LE. 1), computed by SLALN2, 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.)   

    Arguments   
    ==========   

    LTRANS  (input) LOGICAL   
            =.TRUE.:  A-transpose will be used.   
            =.FALSE.: A will be used (not transposed.)   

    NA      (input) INTEGER   
            The size of the matrix A.  It may (only) be 1 or 2.   

    NW      (input) INTEGER   
            1 if "w" is real, 2 if "w" is complex.  It may only be 1   
            or 2.   

    SMIN    (input) REAL   
            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.)   

    CA      (input) REAL   
            The coefficient c, which A is multiplied by.   

    A       (input) REAL array, dimension (LDA,NA)   
            The NA x NA matrix A.   

    LDA     (input) INTEGER   
            The leading dimension of A.  It must be at least NA.   

    D1      (input) REAL   
            The 1,1 element in the diagonal matrix D.   

    D2      (input) REAL   
            The 2,2 element in the diagonal matrix D.  Not used if NW=1. 
  

    B       (input) REAL 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.   

    LDB     (input) INTEGER   
            The leading dimension of B.  It must be at least NA.   

    WR      (input) REAL   
            The real part of the scalar "w".   

    WI      (input) REAL   
            The imaginary part of the scalar "w".  Not used if NW=1.   

    X       (output) REAL array, dimension (LDX,NW)   
            The NA x NW matrix X (unknowns), as computed by SLALN2.   
            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.   

    LDX     (input) INTEGER   
            The leading dimension of X.  It must be at least NA.   

    SCALE   (output) REAL   
            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.   

    XNORM   (output) REAL   
            The infinity-norm of X, when X is regarded as an NA x NW   
            real matrix.   

    INFO    (output) 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.   

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

    
   Parameter adjustments   
       Function Body */
    /* Initialized data */
    static logical cswap[4] = { FALSE_,FALSE_,TRUE_,TRUE_ };
    static logical rswap[4] = { FALSE_,TRUE_,FALSE_,TRUE_ };
    static integer ipivot[16]	/* was [4][4] */ = { 1,2,3,4,2,1,4,3,3,4,1,2,
	    4,3,2,1 };
    /* System generated locals */
    integer a_dim1, a_offset, b_dim1, b_offset, x_dim1, x_offset;
    real r__1, r__2, r__3, r__4, r__5, r__6;
    static real equiv_0[4], equiv_1[4];
    /* Local variables */
    static real bbnd, cmax, ui11r, ui12s, temp, ur11r, ur12s;
    static integer j;
    static real u22abs;
    static integer icmax;
    static real bnorm, cnorm, smini;
#define ci (equiv_0)
#define cr (equiv_1)
    extern doublereal slamch_(char *);
    static real bignum;
    extern /* Subroutine */ int sladiv_(real *, real *, real *, real *, real *
	    , real *);
    static real bi1, bi2, br1, br2, smlnum, xi1, xi2, xr1, xr2, ci21, ci22, 
	    cr21, cr22, li21, csi, ui11, lr21, ui12, ui22;
#define civ (equiv_0)
    static real csr, ur11, ur12, ur22;
#define crv (equiv_1)


#define IPIVOT(I) ipivot[(I)]
#define WAS(I) was[(I)]

#define A(I,J) a[(I)-1 + ((J)-1)* ( *lda)]
#define B(I,J) b[(I)-1 + ((J)-1)* ( *ldb)]
#define X(I,J) x[(I)-1 + ((J)-1)* ( *ldx)]


/*     Compute BIGNUM */

    smlnum = slamch_("Safe minimum") * 2.f;
    bignum = 1.f / smlnum;
    smini = dmax(*smin,smlnum);

/*     Don't check for input errors */

    *info = 0;

/*     Standard Initializations */

    *scale = 1.f;

    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(1,1) - *wr * *d1;
	    cnorm = dabs(csr);

/*           If | C | < SMINI, use C = SMINI */

	    if (cnorm < smini) {
		csr = smini;
		cnorm = smini;
		*info = 1;
	    }

/*           Check scaling for  X = B / C */

	    bnorm = (r__1 = B(1,1), dabs(r__1));
	    if (cnorm < 1.f && bnorm > 1.f) {
		if (bnorm > bignum * cnorm) {
		    *scale = 1.f / bnorm;
		}
	    }

/*           Compute X */

	    X(1,1) = B(1,1) * *scale / csr;
	    *xnorm = (r__1 = X(1,1), dabs(r__1));
	} else {

/*           Complex 1x1 system (w is complex)   

             C = ca A - w D */

	    csr = *ca * A(1,1) - *wr * *d1;
	    csi = -(doublereal)(*wi) * *d1;
	    cnorm = dabs(csr) + dabs(csi);

/*           If | C | < SMINI, use C = SMINI */

	    if (cnorm < smini) {
		csr = smini;
		csi = 0.f;
		cnorm = smini;
		*info = 1;
	    }

/*           Check scaling for  X = B / C */

	    bnorm = (r__1 = B(1,1), dabs(r__1)) + (r__2 = B(1,2), dabs(r__2));
	    if (cnorm < 1.f && bnorm > 1.f) {
		if (bnorm > bignum * cnorm) {
		    *scale = 1.f / bnorm;
		}
	    }

/*           Compute X */

	    r__1 = *scale * B(1,1);
	    r__2 = *scale * B(1,2);
	    sladiv_(&r__1, &r__2, &csr, &csi, &X(1,1), &X(1,2));
	    *xnorm = (r__1 = X(1,1), dabs(r__1)) + (r__2 = X(1,2), dabs(r__2));
	}

    } else {

/*        2x2 System   

          Compute the real part of  C = ca A - w D  (or  ca A' - w D )
 */

	cr[0] = *ca * A(1,1) - *wr * *d1;
	cr[3] = *ca * A(2,2) - *wr * *d2;
	if (*ltrans) {
	    cr[2] = *ca * A(2,1);
	    cr[1] = *ca * A(1,2);
	} else {
	    cr[1] = *ca * A(2,1);
	    cr[2] = *ca * A(1,2);
	}

	if (*nw == 1) {

/*           Real 2x2 system  (w is real)   

             Find the largest element in C */

	    cmax = 0.f;
	    icmax = 0;

	    for (j = 1; j <= 4; ++j) {
		if ((r__1 = crv[j - 1], dabs(r__1)) > cmax) {
		    cmax = (r__1 = crv[j - 1], dabs(r__1));
		    icmax = j;
		}
/* L10: */
	    }

/*           If norm(C) < SMINI, use SMINI*identity. */

	    if (cmax < smini) {
/* Computing MAX */
		r__3 = (r__1 = B(1,1), dabs(r__1)), r__4 = (r__2 = B(2,1), dabs(r__2));
		bnorm = dmax(r__3,r__4);
		if (smini < 1.f && bnorm > 1.f) {
		    if (bnorm > bignum * smini) {
			*scale = 1.f / bnorm;
		    }
		}
		temp = *scale / smini;
		X(1,1) = temp * B(1,1);
		X(2,1) = temp * B(2,1);
		*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.f / ur11;
	    lr21 = ur11r * cr21;
	    ur22 = cr22 - ur12 * lr21;

/*           If smaller pivot < SMINI, use SMINI */

	    if (dabs(ur22) < smini) {
		ur22 = smini;
		*info = 1;
	    }
	    if (rswap[icmax - 1]) {
		br1 = B(2,1);
		br2 = B(1,1);
	    } else {
		br1 = B(1,1);
		br2 = B(2,1);
	    }
	    br2 -= lr21 * br1;
/* Computing MAX */
	    r__2 = (r__1 = br1 * (ur22 * ur11r), dabs(r__1)), r__3 = dabs(br2)
		    ;
	    bbnd = dmax(r__2,r__3);
	    if (bbnd > 1.f && dabs(ur22) < 1.f) {
		if (bbnd >= bignum * dabs(ur22)) {
		    *scale = 1.f / bbnd;
		}
	    }

	    xr2 = br2 * *scale / ur22;
	    xr1 = *scale * br1 * ur11r - xr2 * (ur11r * ur12);
	    if (cswap[icmax - 1]) {
		X(1,1) = xr2;
		X(2,1) = xr1;
	    } else {
		X(1,1) = xr1;
		X(2,1) = xr2;
	    }
/* Computing MAX */
	    r__1 = dabs(xr1), r__2 = dabs(xr2);
	    *xnorm = dmax(r__1,r__2);

/*           Further scaling if  norm(A) norm(X) > overflow */

	    if (*xnorm > 1.f && cmax > 1.f) {
		if (*xnorm > bignum / cmax) {
		    temp = cmax / bignum;
		    X(1,1) = temp * X(1,1);
		    X(2,1) = temp * X(2,1);
		    *xnorm = temp * *xnorm;
		    *scale = temp * *scale;
		}
	    }
	} else {

/*           Complex 2x2 system  (w is complex)   

             Find the largest element in C */

	    ci[0] = -(doublereal)(*wi) * *d1;
	    ci[1] = 0.f;
	    ci[2] = 0.f;
	    ci[3] = -(doublereal)(*wi) * *d2;
	    cmax = 0.f;
	    icmax = 0;

	    for (j = 1; j <= 4; ++j) {
		if ((r__1 = crv[j - 1], dabs(r__1)) + (r__2 = civ[j - 1], 
			dabs(r__2)) > cmax) {
		    cmax = (r__1 = crv[j - 1], dabs(r__1)) + (r__2 = civ[j - 
			    1], dabs(r__2));
		    icmax = j;
		}
/* L20: */
	    }

/*           If norm(C) < SMINI, use SMINI*identity. */

	    if (cmax < smini) {
/* Computing MAX */
		r__5 = (r__1 = B(1,1), dabs(r__1)) + (r__2 = B(1,2), dabs(r__2)), r__6 = (r__3 = B(2,1),
			 dabs(r__3)) + (r__4 = B(2,2), dabs(
			r__4));
		bnorm = dmax(r__5,r__6);
		if (smini < 1.f && bnorm > 1.f) {
		    if (bnorm > bignum * smini) {
			*scale = 1.f / bnorm;
		    }
		}
		temp = *scale / smini;
		X(1,1) = temp * B(1,1);
		X(2,1) = temp * B(2,1);
		X(1,2) = temp * B(1,2);
		X(2,2) = temp * B(2,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 (dabs(ur11) > dabs(ui11)) {
		    temp = ui11 / ur11;
/* Computing 2nd power */
		    r__1 = temp;
		    ur11r = 1.f / (ur11 * (r__1 * r__1 + 1.f));
		    ui11r = -(doublereal)temp * ur11r;
		} else {
		    temp = ur11 / ui11;
/* Computing 2nd power */
		    r__1 = temp;
		    ui11r = -1.f / (ui11 * (r__1 * r__1 + 1.f));
		    ur11r = -(doublereal)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.f / ur11;
		ui11r = 0.f;
		lr21 = cr21 * ur11r;
		li21 = ci21 * ur11r;
		ur12s = ur12 * ur11r;
		ui12s = ui12 * ur11r;
		ur22 = cr22 - ur12 * lr21 + ui12 * li21;
		ui22 = -(doublereal)ur12 * li21 - ui12 * lr21;
	    }
	    u22abs = dabs(ur22) + dabs(ui22);

/*           If smaller pivot < SMINI, use SMINI */

	    if (u22abs < smini) {
		ur22 = smini;
		ui22 = 0.f;
		*info = 1;
	    }
	    if (rswap[icmax - 1]) {
		br2 = B(1,1);
		br1 = B(2,1);
		bi2 = B(1,2);
		bi1 = B(2,2);
	    } else {
		br1 = B(1,1);
		br2 = B(2,1);
		bi1 = B(1,2);
		bi2 = B(2,2);
	    }
	    br2 = br2 - lr21 * br1 + li21 * bi1;
	    bi2 = bi2 - li21 * br1 - lr21 * bi1;
/* Computing MAX */
	    r__1 = (dabs(br1) + dabs(bi1)) * (u22abs * (dabs(ur11r) + dabs(
		    ui11r))), r__2 = dabs(br2) + dabs(bi2);
	    bbnd = dmax(r__1,r__2);
	    if (bbnd > 1.f && u22abs < 1.f) {
		if (bbnd >= bignum * u22abs) {
		    *scale = 1.f / bbnd;
		    br1 = *scale * br1;
		    bi1 = *scale * bi1;
		    br2 = *scale * br2;
		    bi2 = *scale * bi2;
		}
	    }

	    sladiv_(&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 (cswap[icmax - 1]) {
		X(1,1) = xr2;
		X(2,1) = xr1;
		X(1,2) = xi2;
		X(2,2) = xi1;
	    } else {
		X(1,1) = xr1;
		X(2,1) = xr2;
		X(1,2) = xi1;
		X(2,2) = xi2;
	    }
/* Computing MAX */
	    r__1 = dabs(xr1) + dabs(xi1), r__2 = dabs(xr2) + dabs(xi2);
	    *xnorm = dmax(r__1,r__2);

/*           Further scaling if  norm(A) norm(X) > overflow */

	    if (*xnorm > 1.f && cmax > 1.f) {
		if (*xnorm > bignum / cmax) {
		    temp = cmax / bignum;
		    X(1,1) = temp * X(1,1);
		    X(2,1) = temp * X(2,1);
		    X(1,2) = temp * X(1,2);
		    X(2,2) = temp * X(2,2);
		    *xnorm = temp * *xnorm;
		    *scale = temp * *scale;
		}
	    }
	}
    }

    return 0;

/*     End of SLALN2 */

} /* slaln2_ */
예제 #5
0
 int slaein_(int *rightv, int *noinit, int *n, 
	float *h__, int *ldh, float *wr, float *wi, float *vr, float *vi, float 
	*b, int *ldb, float *work, float *eps3, float *smlnum, float *bignum, 
	int *info)
{
    /* System generated locals */
    int b_dim1, b_offset, h_dim1, h_offset, i__1, i__2, i__3, i__4;
    float r__1, r__2, r__3, r__4;

    /* Builtin functions */
    double sqrt(double);

    /* Local variables */
    int i__, j;
    float w, x, y;
    int i1, i2, i3;
    float w1, ei, ej, xi, xr, rec;
    int its, ierr;
    float temp, norm, vmax;
    extern double snrm2_(int *, float *, int *);
    float scale;
    extern  int sscal_(int *, float *, float *, int *);
    char trans[1];
    float vcrit;
    extern double sasum_(int *, float *, int *);
    float rootn, vnorm;
    extern double slapy2_(float *, float *);
    float absbii, absbjj;
    extern int isamax_(int *, float *, int *);
    extern  int sladiv_(float *, float *, float *, float *, float *
, float *);
    char normin[1];
    float nrmsml;
    extern  int slatrs_(char *, char *, char *, char *, 
	    int *, float *, int *, float *, float *, float *, int *);
    float growto;


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

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

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

/*  SLAEIN uses inverse iteration to find a right or left eigenvector */
/*  corresponding to the eigenvalue (WR,WI) of a float upper Hessenberg */
/*  matrix H. */

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

/*  RIGHTV   (input) LOGICAL */
/*          = .TRUE. : compute right eigenvector; */
/*          = .FALSE.: compute left eigenvector. */

/*  NOINIT   (input) LOGICAL */
/*          = .TRUE. : no initial vector supplied in (VR,VI). */
/*          = .FALSE.: initial vector supplied in (VR,VI). */

/*  N       (input) INTEGER */
/*          The order of the matrix H.  N >= 0. */

/*  H       (input) REAL array, dimension (LDH,N) */
/*          The upper Hessenberg matrix H. */

/*  LDH     (input) INTEGER */
/*          The leading dimension of the array H.  LDH >= MAX(1,N). */

/*  WR      (input) REAL */
/*  WI      (input) REAL */
/*          The float and imaginary parts of the eigenvalue of H whose */
/*          corresponding right or left eigenvector is to be computed. */

/*  VR      (input/output) REAL array, dimension (N) */
/*  VI      (input/output) REAL array, dimension (N) */
/*          On entry, if NOINIT = .FALSE. and WI = 0.0, VR must contain */
/*          a float starting vector for inverse iteration using the float */
/*          eigenvalue WR; if NOINIT = .FALSE. and WI.ne.0.0, VR and VI */
/*          must contain the float and imaginary parts of a complex */
/*          starting vector for inverse iteration using the complex */
/*          eigenvalue (WR,WI); otherwise VR and VI need not be set. */
/*          On exit, if WI = 0.0 (float eigenvalue), VR contains the */
/*          computed float eigenvector; if WI.ne.0.0 (complex eigenvalue), */
/*          VR and VI contain the float and imaginary parts of the */
/*          computed complex eigenvector. The eigenvector is normalized */
/*          so that the component of largest magnitude has magnitude 1; */
/*          here the magnitude of a complex number (x,y) is taken to be */
/*          |x| + |y|. */
/*          VI is not referenced if WI = 0.0. */

/*  B       (workspace) REAL array, dimension (LDB,N) */

/*  LDB     (input) INTEGER */
/*          The leading dimension of the array B.  LDB >= N+1. */

/*  WORK   (workspace) REAL array, dimension (N) */

/*  EPS3    (input) REAL */
/*          A small machine-dependent value which is used to perturb */
/*          close eigenvalues, and to replace zero pivots. */

/*  SMLNUM  (input) REAL */
/*          A machine-dependent value close to the underflow threshold. */

/*  BIGNUM  (input) REAL */
/*          A machine-dependent value close to the overflow threshold. */

/*  INFO    (output) INTEGER */
/*          = 0:  successful exit */
/*          = 1:  inverse iteration did not converge; VR is set to the */
/*                last iterate, and so is VI if WI.ne.0.0. */

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

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

    /* Parameter adjustments */
    h_dim1 = *ldh;
    h_offset = 1 + h_dim1;
    h__ -= h_offset;
    --vr;
    --vi;
    b_dim1 = *ldb;
    b_offset = 1 + b_dim1;
    b -= b_offset;
    --work;

    /* Function Body */
    *info = 0;

/*     GROWTO is the threshold used in the acceptance test for an */
/*     eigenvector. */

    rootn = sqrt((float) (*n));
    growto = .1f / rootn;
/* Computing MAX */
    r__1 = 1.f, r__2 = *eps3 * rootn;
    nrmsml = MAX(r__1,r__2) * *smlnum;

/*     Form B = H - (WR,WI)*I (except that the subdiagonal elements and */
/*     the imaginary parts of the diagonal elements are not stored). */

    i__1 = *n;
    for (j = 1; j <= i__1; ++j) {
	i__2 = j - 1;
	for (i__ = 1; i__ <= i__2; ++i__) {
	    b[i__ + j * b_dim1] = h__[i__ + j * h_dim1];
/* L10: */
	}
	b[j + j * b_dim1] = h__[j + j * h_dim1] - *wr;
/* L20: */
    }

    if (*wi == 0.f) {

/*        Real eigenvalue. */

	if (*noinit) {

/*           Set initial vector. */

	    i__1 = *n;
	    for (i__ = 1; i__ <= i__1; ++i__) {
		vr[i__] = *eps3;
/* L30: */
	    }
	} else {

/*           Scale supplied initial vector. */

	    vnorm = snrm2_(n, &vr[1], &c__1);
	    r__1 = *eps3 * rootn / MAX(vnorm,nrmsml);
	    sscal_(n, &r__1, &vr[1], &c__1);
	}

	if (*rightv) {

/*           LU decomposition with partial pivoting of B, replacing zero */
/*           pivots by EPS3. */

	    i__1 = *n - 1;
	    for (i__ = 1; i__ <= i__1; ++i__) {
		ei = h__[i__ + 1 + i__ * h_dim1];
		if ((r__1 = b[i__ + i__ * b_dim1], ABS(r__1)) < ABS(ei)) {

/*                 Interchange rows and eliminate. */

		    x = b[i__ + i__ * b_dim1] / ei;
		    b[i__ + i__ * b_dim1] = ei;
		    i__2 = *n;
		    for (j = i__ + 1; j <= i__2; ++j) {
			temp = b[i__ + 1 + j * b_dim1];
			b[i__ + 1 + j * b_dim1] = b[i__ + j * b_dim1] - x * 
				temp;
			b[i__ + j * b_dim1] = temp;
/* L40: */
		    }
		} else {

/*                 Eliminate without interchange. */

		    if (b[i__ + i__ * b_dim1] == 0.f) {
			b[i__ + i__ * b_dim1] = *eps3;
		    }
		    x = ei / b[i__ + i__ * b_dim1];
		    if (x != 0.f) {
			i__2 = *n;
			for (j = i__ + 1; j <= i__2; ++j) {
			    b[i__ + 1 + j * b_dim1] -= x * b[i__ + j * b_dim1]
				    ;
/* L50: */
			}
		    }
		}
/* L60: */
	    }
	    if (b[*n + *n * b_dim1] == 0.f) {
		b[*n + *n * b_dim1] = *eps3;
	    }

	    *(unsigned char *)trans = 'N';

	} else {

/*           UL decomposition with partial pivoting of B, replacing zero */
/*           pivots by EPS3. */

	    for (j = *n; j >= 2; --j) {
		ej = h__[j + (j - 1) * h_dim1];
		if ((r__1 = b[j + j * b_dim1], ABS(r__1)) < ABS(ej)) {

/*                 Interchange columns and eliminate. */

		    x = b[j + j * b_dim1] / ej;
		    b[j + j * b_dim1] = ej;
		    i__1 = j - 1;
		    for (i__ = 1; i__ <= i__1; ++i__) {
			temp = b[i__ + (j - 1) * b_dim1];
			b[i__ + (j - 1) * b_dim1] = b[i__ + j * b_dim1] - x * 
				temp;
			b[i__ + j * b_dim1] = temp;
/* L70: */
		    }
		} else {

/*                 Eliminate without interchange. */

		    if (b[j + j * b_dim1] == 0.f) {
			b[j + j * b_dim1] = *eps3;
		    }
		    x = ej / b[j + j * b_dim1];
		    if (x != 0.f) {
			i__1 = j - 1;
			for (i__ = 1; i__ <= i__1; ++i__) {
			    b[i__ + (j - 1) * b_dim1] -= x * b[i__ + j * 
				    b_dim1];
/* L80: */
			}
		    }
		}
/* L90: */
	    }
	    if (b[b_dim1 + 1] == 0.f) {
		b[b_dim1 + 1] = *eps3;
	    }

	    *(unsigned char *)trans = 'T';

	}

	*(unsigned char *)normin = 'N';
	i__1 = *n;
	for (its = 1; its <= i__1; ++its) {

/*           Solve U*x = scale*v for a right eigenvector */
/*             or U'*x = scale*v for a left eigenvector, */
/*           overwriting x on v. */

	    slatrs_("Upper", trans, "Nonunit", normin, n, &b[b_offset], ldb, &
		    vr[1], &scale, &work[1], &ierr);
	    *(unsigned char *)normin = 'Y';

/*           Test for sufficient growth in the norm of v. */

	    vnorm = sasum_(n, &vr[1], &c__1);
	    if (vnorm >= growto * scale) {
		goto L120;
	    }

/*           Choose new orthogonal starting vector and try again. */

	    temp = *eps3 / (rootn + 1.f);
	    vr[1] = *eps3;
	    i__2 = *n;
	    for (i__ = 2; i__ <= i__2; ++i__) {
		vr[i__] = temp;
/* L100: */
	    }
	    vr[*n - its + 1] -= *eps3 * rootn;
/* L110: */
	}

/*        Failure to find eigenvector in N iterations. */

	*info = 1;

L120:

/*        Normalize eigenvector. */

	i__ = isamax_(n, &vr[1], &c__1);
	r__2 = 1.f / (r__1 = vr[i__], ABS(r__1));
	sscal_(n, &r__2, &vr[1], &c__1);
    } else {

/*        Complex eigenvalue. */

	if (*noinit) {

/*           Set initial vector. */

	    i__1 = *n;
	    for (i__ = 1; i__ <= i__1; ++i__) {
		vr[i__] = *eps3;
		vi[i__] = 0.f;
/* L130: */
	    }
	} else {

/*           Scale supplied initial vector. */

	    r__1 = snrm2_(n, &vr[1], &c__1);
	    r__2 = snrm2_(n, &vi[1], &c__1);
	    norm = slapy2_(&r__1, &r__2);
	    rec = *eps3 * rootn / MAX(norm,nrmsml);
	    sscal_(n, &rec, &vr[1], &c__1);
	    sscal_(n, &rec, &vi[1], &c__1);
	}

	if (*rightv) {

/*           LU decomposition with partial pivoting of B, replacing zero */
/*           pivots by EPS3. */

/*           The imaginary part of the (i,j)-th element of U is stored in */
/*           B(j+1,i). */

	    b[b_dim1 + 2] = -(*wi);
	    i__1 = *n;
	    for (i__ = 2; i__ <= i__1; ++i__) {
		b[i__ + 1 + b_dim1] = 0.f;
/* L140: */
	    }

	    i__1 = *n - 1;
	    for (i__ = 1; i__ <= i__1; ++i__) {
		absbii = slapy2_(&b[i__ + i__ * b_dim1], &b[i__ + 1 + i__ * 
			b_dim1]);
		ei = h__[i__ + 1 + i__ * h_dim1];
		if (absbii < ABS(ei)) {

/*                 Interchange rows and eliminate. */

		    xr = b[i__ + i__ * b_dim1] / ei;
		    xi = b[i__ + 1 + i__ * b_dim1] / ei;
		    b[i__ + i__ * b_dim1] = ei;
		    b[i__ + 1 + i__ * b_dim1] = 0.f;
		    i__2 = *n;
		    for (j = i__ + 1; j <= i__2; ++j) {
			temp = b[i__ + 1 + j * b_dim1];
			b[i__ + 1 + j * b_dim1] = b[i__ + j * b_dim1] - xr * 
				temp;
			b[j + 1 + (i__ + 1) * b_dim1] = b[j + 1 + i__ * 
				b_dim1] - xi * temp;
			b[i__ + j * b_dim1] = temp;
			b[j + 1 + i__ * b_dim1] = 0.f;
/* L150: */
		    }
		    b[i__ + 2 + i__ * b_dim1] = -(*wi);
		    b[i__ + 1 + (i__ + 1) * b_dim1] -= xi * *wi;
		    b[i__ + 2 + (i__ + 1) * b_dim1] += xr * *wi;
		} else {

/*                 Eliminate without interchanging rows. */

		    if (absbii == 0.f) {
			b[i__ + i__ * b_dim1] = *eps3;
			b[i__ + 1 + i__ * b_dim1] = 0.f;
			absbii = *eps3;
		    }
		    ei = ei / absbii / absbii;
		    xr = b[i__ + i__ * b_dim1] * ei;
		    xi = -b[i__ + 1 + i__ * b_dim1] * ei;
		    i__2 = *n;
		    for (j = i__ + 1; j <= i__2; ++j) {
			b[i__ + 1 + j * b_dim1] = b[i__ + 1 + j * b_dim1] - 
				xr * b[i__ + j * b_dim1] + xi * b[j + 1 + i__ 
				* b_dim1];
			b[j + 1 + (i__ + 1) * b_dim1] = -xr * b[j + 1 + i__ * 
				b_dim1] - xi * b[i__ + j * b_dim1];
/* L160: */
		    }
		    b[i__ + 2 + (i__ + 1) * b_dim1] -= *wi;
		}

/*              Compute 1-norm of offdiagonal elements of i-th row. */

		i__2 = *n - i__;
		i__3 = *n - i__;
		work[i__] = sasum_(&i__2, &b[i__ + (i__ + 1) * b_dim1], ldb) 
			+ sasum_(&i__3, &b[i__ + 2 + i__ * b_dim1], &c__1);
/* L170: */
	    }
	    if (b[*n + *n * b_dim1] == 0.f && b[*n + 1 + *n * b_dim1] == 0.f) 
		    {
		b[*n + *n * b_dim1] = *eps3;
	    }
	    work[*n] = 0.f;

	    i1 = *n;
	    i2 = 1;
	    i3 = -1;
	} else {

/*           UL decomposition with partial pivoting of conjg(B), */
/*           replacing zero pivots by EPS3. */

/*           The imaginary part of the (i,j)-th element of U is stored in */
/*           B(j+1,i). */

	    b[*n + 1 + *n * b_dim1] = *wi;
	    i__1 = *n - 1;
	    for (j = 1; j <= i__1; ++j) {
		b[*n + 1 + j * b_dim1] = 0.f;
/* L180: */
	    }

	    for (j = *n; j >= 2; --j) {
		ej = h__[j + (j - 1) * h_dim1];
		absbjj = slapy2_(&b[j + j * b_dim1], &b[j + 1 + j * b_dim1]);
		if (absbjj < ABS(ej)) {

/*                 Interchange columns and eliminate */

		    xr = b[j + j * b_dim1] / ej;
		    xi = b[j + 1 + j * b_dim1] / ej;
		    b[j + j * b_dim1] = ej;
		    b[j + 1 + j * b_dim1] = 0.f;
		    i__1 = j - 1;
		    for (i__ = 1; i__ <= i__1; ++i__) {
			temp = b[i__ + (j - 1) * b_dim1];
			b[i__ + (j - 1) * b_dim1] = b[i__ + j * b_dim1] - xr *
				 temp;
			b[j + i__ * b_dim1] = b[j + 1 + i__ * b_dim1] - xi * 
				temp;
			b[i__ + j * b_dim1] = temp;
			b[j + 1 + i__ * b_dim1] = 0.f;
/* L190: */
		    }
		    b[j + 1 + (j - 1) * b_dim1] = *wi;
		    b[j - 1 + (j - 1) * b_dim1] += xi * *wi;
		    b[j + (j - 1) * b_dim1] -= xr * *wi;
		} else {

/*                 Eliminate without interchange. */

		    if (absbjj == 0.f) {
			b[j + j * b_dim1] = *eps3;
			b[j + 1 + j * b_dim1] = 0.f;
			absbjj = *eps3;
		    }
		    ej = ej / absbjj / absbjj;
		    xr = b[j + j * b_dim1] * ej;
		    xi = -b[j + 1 + j * b_dim1] * ej;
		    i__1 = j - 1;
		    for (i__ = 1; i__ <= i__1; ++i__) {
			b[i__ + (j - 1) * b_dim1] = b[i__ + (j - 1) * b_dim1] 
				- xr * b[i__ + j * b_dim1] + xi * b[j + 1 + 
				i__ * b_dim1];
			b[j + i__ * b_dim1] = -xr * b[j + 1 + i__ * b_dim1] - 
				xi * b[i__ + j * b_dim1];
/* L200: */
		    }
		    b[j + (j - 1) * b_dim1] += *wi;
		}

/*              Compute 1-norm of offdiagonal elements of j-th column. */

		i__1 = j - 1;
		i__2 = j - 1;
		work[j] = sasum_(&i__1, &b[j * b_dim1 + 1], &c__1) + sasum_(&
			i__2, &b[j + 1 + b_dim1], ldb);
/* L210: */
	    }
	    if (b[b_dim1 + 1] == 0.f && b[b_dim1 + 2] == 0.f) {
		b[b_dim1 + 1] = *eps3;
	    }
	    work[1] = 0.f;

	    i1 = 1;
	    i2 = *n;
	    i3 = 1;
	}

	i__1 = *n;
	for (its = 1; its <= i__1; ++its) {
	    scale = 1.f;
	    vmax = 1.f;
	    vcrit = *bignum;

/*           Solve U*(xr,xi) = scale*(vr,vi) for a right eigenvector, */
/*             or U'*(xr,xi) = scale*(vr,vi) for a left eigenvector, */
/*           overwriting (xr,xi) on (vr,vi). */

	    i__2 = i2;
	    i__3 = i3;
	    for (i__ = i1; i__3 < 0 ? i__ >= i__2 : i__ <= i__2; i__ += i__3) 
		    {

		if (work[i__] > vcrit) {
		    rec = 1.f / vmax;
		    sscal_(n, &rec, &vr[1], &c__1);
		    sscal_(n, &rec, &vi[1], &c__1);
		    scale *= rec;
		    vmax = 1.f;
		    vcrit = *bignum;
		}

		xr = vr[i__];
		xi = vi[i__];
		if (*rightv) {
		    i__4 = *n;
		    for (j = i__ + 1; j <= i__4; ++j) {
			xr = xr - b[i__ + j * b_dim1] * vr[j] + b[j + 1 + i__ 
				* b_dim1] * vi[j];
			xi = xi - b[i__ + j * b_dim1] * vi[j] - b[j + 1 + i__ 
				* b_dim1] * vr[j];
/* L220: */
		    }
		} else {
		    i__4 = i__ - 1;
		    for (j = 1; j <= i__4; ++j) {
			xr = xr - b[j + i__ * b_dim1] * vr[j] + b[i__ + 1 + j 
				* b_dim1] * vi[j];
			xi = xi - b[j + i__ * b_dim1] * vi[j] - b[i__ + 1 + j 
				* b_dim1] * vr[j];
/* L230: */
		    }
		}

		w = (r__1 = b[i__ + i__ * b_dim1], ABS(r__1)) + (r__2 = b[
			i__ + 1 + i__ * b_dim1], ABS(r__2));
		if (w > *smlnum) {
		    if (w < 1.f) {
			w1 = ABS(xr) + ABS(xi);
			if (w1 > w * *bignum) {
			    rec = 1.f / w1;
			    sscal_(n, &rec, &vr[1], &c__1);
			    sscal_(n, &rec, &vi[1], &c__1);
			    xr = vr[i__];
			    xi = vi[i__];
			    scale *= rec;
			    vmax *= rec;
			}
		    }

/*                 Divide by diagonal element of B. */

		    sladiv_(&xr, &xi, &b[i__ + i__ * b_dim1], &b[i__ + 1 + 
			    i__ * b_dim1], &vr[i__], &vi[i__]);
/* Computing MAX */
		    r__3 = (r__1 = vr[i__], ABS(r__1)) + (r__2 = vi[i__], 
			    ABS(r__2));
		    vmax = MAX(r__3,vmax);
		    vcrit = *bignum / vmax;
		} else {
		    i__4 = *n;
		    for (j = 1; j <= i__4; ++j) {
			vr[j] = 0.f;
			vi[j] = 0.f;
/* L240: */
		    }
		    vr[i__] = 1.f;
		    vi[i__] = 1.f;
		    scale = 0.f;
		    vmax = 1.f;
		    vcrit = *bignum;
		}
/* L250: */
	    }

/*           Test for sufficient growth in the norm of (VR,VI). */

	    vnorm = sasum_(n, &vr[1], &c__1) + sasum_(n, &vi[1], &c__1);
	    if (vnorm >= growto * scale) {
		goto L280;
	    }

/*           Choose a new orthogonal starting vector and try again. */

	    y = *eps3 / (rootn + 1.f);
	    vr[1] = *eps3;
	    vi[1] = 0.f;

	    i__3 = *n;
	    for (i__ = 2; i__ <= i__3; ++i__) {
		vr[i__] = y;
		vi[i__] = 0.f;
/* L260: */
	    }
	    vr[*n - its + 1] -= *eps3 * rootn;
/* L270: */
	}

/*        Failure to find eigenvector in N iterations */

	*info = 1;

L280:

/*        Normalize eigenvector. */

	vnorm = 0.f;
	i__1 = *n;
	for (i__ = 1; i__ <= i__1; ++i__) {
/* Computing MAX */
	    r__3 = vnorm, r__4 = (r__1 = vr[i__], ABS(r__1)) + (r__2 = vi[
		    i__], ABS(r__2));
	    vnorm = MAX(r__3,r__4);
/* L290: */
	}
	r__1 = 1.f / vnorm;
	sscal_(n, &r__1, &vr[1], &c__1);
	r__1 = 1.f / vnorm;
	sscal_(n, &r__1, &vi[1], &c__1);

    }

    return 0;

/*     End of SLAEIN */

} /* slaein_ */
예제 #6
0
/* Subroutine */ int slaln2_(logical *ltrans, integer *na, integer *nw, real *
                             smin, real *ca, real *a, integer *lda, real *d1, real *d2, real *b,
                             integer *ldb, real *wr, real *wi, real *x, integer *ldx, real *scale,
                             real *xnorm, integer *info)
{
    /* Initialized data */

    static logical cswap[4] = { FALSE_,FALSE_,TRUE_,TRUE_ };
    static logical rswap[4] = { FALSE_,TRUE_,FALSE_,TRUE_ };
    static integer ipivot[16]	/* was [4][4] */ = { 1,2,3,4,2,1,4,3,3,4,1,2,
                                                     4,3,2,1
                                                 };

    /* System generated locals */
    integer a_dim1, a_offset, b_dim1, b_offset, x_dim1, x_offset;
    real r__1, r__2, r__3, r__4, r__5, r__6;
    static real equiv_0[4], equiv_1[4];

    /* Local variables */
    integer j;
#define ci (equiv_0)
#define cr (equiv_1)
    real bi1, bi2, br1, br2, xi1, xi2, xr1, xr2, ci21, ci22, cr21, cr22, li21,
         csi, ui11, lr21, ui12, ui22;
#define civ (equiv_0)
    real csr, ur11, ur12, ur22;
#define crv (equiv_1)
    real bbnd, cmax, ui11r, ui12s, temp, ur11r, ur12s, u22abs;
    integer icmax;
    real bnorm, cnorm, smini;
    real bignum;
    real smlnum;

    /*  -- LAPACK auxiliary routine (version 3.2) -- */
    /*     November 2006 */

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

    /*  SLALN2 solves a system of the form  (ca A - w D ) X = s B */
    /*  or (ca A' - w D) X = s B   with possible scaling ("s") and */
    /*  perturbation of A.  (A' 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 (.LE. 1), computed by SLALN2, 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.) */

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

    /*  LTRANS  (input) LOGICAL */
    /*          =.TRUE.:  A-transpose will be used. */
    /*          =.FALSE.: A will be used (not transposed.) */

    /*  NA      (input) INTEGER */
    /*          The size of the matrix A.  It may (only) be 1 or 2. */

    /*  NW      (input) INTEGER */
    /*          1 if "w" is real, 2 if "w" is complex.  It may only be 1 */
    /*          or 2. */

    /*  SMIN    (input) REAL */
    /*          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.) */

    /*  CA      (input) REAL */
    /*          The coefficient c, which A is multiplied by. */

    /*  A       (input) REAL array, dimension (LDA,NA) */
    /*          The NA x NA matrix A. */

    /*  LDA     (input) INTEGER */
    /*          The leading dimension of A.  It must be at least NA. */

    /*  D1      (input) REAL */
    /*          The 1,1 element in the diagonal matrix D. */

    /*  D2      (input) REAL */
    /*          The 2,2 element in the diagonal matrix D.  Not used if NW=1. */

    /*  B       (input) REAL 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. */

    /*  LDB     (input) INTEGER */
    /*          The leading dimension of B.  It must be at least NA. */

    /*  WR      (input) REAL */
    /*          The real part of the scalar "w". */

    /*  WI      (input) REAL */
    /*          The imaginary part of the scalar "w".  Not used if NW=1. */

    /*  X       (output) REAL array, dimension (LDX,NW) */
    /*          The NA x NW matrix X (unknowns), as computed by SLALN2. */
    /*          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. */

    /*  LDX     (input) INTEGER */
    /*          The leading dimension of X.  It must be at least NA. */

    /*  SCALE   (output) REAL */
    /*          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. */

    /*  XNORM   (output) REAL */
    /*          The infinity-norm of X, when X is regarded as an NA x NW */
    /*          real matrix. */

    /*  INFO    (output) 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. */

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

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

    /*     Compute BIGNUM */

    smlnum = 2.f * slamch_("Safe minimum");
    bignum = 1.f / smlnum;
    smini = dmax(*smin,smlnum);

    /*     Don't check for input errors */

    *info = 0;

    /*     Standard Initializations */

    *scale = 1.f;

    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 = dabs(csr);

            /*           If | C | < SMINI, use C = SMINI */

            if (cnorm < smini) {
                csr = smini;
                cnorm = smini;
                *info = 1;
            }

            /*           Check scaling for  X = B / C */

            bnorm = (r__1 = b[b_dim1 + 1], dabs(r__1));
            if (cnorm < 1.f && bnorm > 1.f) {
                if (bnorm > bignum * cnorm) {
                    *scale = 1.f / bnorm;
                }
            }

            /*           Compute X */

            x[x_dim1 + 1] = b[b_dim1 + 1] * *scale / csr;
            *xnorm = (r__1 = x[x_dim1 + 1], dabs(r__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 = dabs(csr) + dabs(csi);

            /*           If | C | < SMINI, use C = SMINI */

            if (cnorm < smini) {
                csr = smini;
                csi = 0.f;
                cnorm = smini;
                *info = 1;
            }

            /*           Check scaling for  X = B / C */

            bnorm = (r__1 = b[b_dim1 + 1], dabs(r__1)) + (r__2 = b[(b_dim1 <<
                    1) + 1], dabs(r__2));
            if (cnorm < 1.f && bnorm > 1.f) {
                if (bnorm > bignum * cnorm) {
                    *scale = 1.f / bnorm;
                }
            }

            /*           Compute X */

            r__1 = *scale * b[b_dim1 + 1];
            r__2 = *scale * b[(b_dim1 << 1) + 1];
            sladiv_(&r__1, &r__2, &csr, &csi, &x[x_dim1 + 1], &x[(x_dim1 << 1)
                    + 1]);
            *xnorm = (r__1 = x[x_dim1 + 1], dabs(r__1)) + (r__2 = x[(x_dim1 <<
                     1) + 1], dabs(r__2));
        }

    } else {

        /*        2x2 System */

        /*        Compute the real part of  C = ca A - w D  (or  ca A' - 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.f;
            icmax = 0;

            for (j = 1; j <= 4; ++j) {
                if ((r__1 = crv[j - 1], dabs(r__1)) > cmax) {
                    cmax = (r__1 = crv[j - 1], dabs(r__1));
                    icmax = j;
                }
            }

            /*           If norm(C) < SMINI, use SMINI*identity. */

            if (cmax < smini) {
                /* Computing MAX */
                r__3 = (r__1 = b[b_dim1 + 1], dabs(r__1)), r__4 = (r__2 = b[
                            b_dim1 + 2], dabs(r__2));
                bnorm = dmax(r__3,r__4);
                if (smini < 1.f && bnorm > 1.f) {
                    if (bnorm > bignum * smini) {
                        *scale = 1.f / 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.f / ur11;
            lr21 = ur11r * cr21;
            ur22 = cr22 - ur12 * lr21;

            /*           If smaller pivot < SMINI, use SMINI */

            if (dabs(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 */
            r__2 = (r__1 = br1 * (ur22 * ur11r), dabs(r__1)), r__3 = dabs(br2)
                    ;
            bbnd = dmax(r__2,r__3);
            if (bbnd > 1.f && dabs(ur22) < 1.f) {
                if (bbnd >= bignum * dabs(ur22)) {
                    *scale = 1.f / bbnd;
                }
            }

            xr2 = br2 * *scale / ur22;
            xr1 = *scale * br1 * ur11r - xr2 * (ur11r * ur12);
            if (cswap[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 */
            r__1 = dabs(xr1), r__2 = dabs(xr2);
            *xnorm = dmax(r__1,r__2);

            /*           Further scaling if  norm(A) norm(X) > overflow */

            if (*xnorm > 1.f && cmax > 1.f) {
                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.f;
            ci[2] = 0.f;
            ci[3] = -(*wi) * *d2;
            cmax = 0.f;
            icmax = 0;

            for (j = 1; j <= 4; ++j) {
                if ((r__1 = crv[j - 1], dabs(r__1)) + (r__2 = civ[j - 1],
                                                       dabs(r__2)) > cmax) {
                    cmax = (r__1 = crv[j - 1], dabs(r__1)) + (r__2 = civ[j -
                            1], dabs(r__2));
                    icmax = j;
                }
            }

            /*           If norm(C) < SMINI, use SMINI*identity. */

            if (cmax < smini) {
                /* Computing MAX */
                r__5 = (r__1 = b[b_dim1 + 1], dabs(r__1)) + (r__2 = b[(b_dim1
                        << 1) + 1], dabs(r__2)), r__6 = (r__3 = b[b_dim1 + 2],
                                                        dabs(r__3)) + (r__4 = b[(b_dim1 << 1) + 2], dabs(
                                                                r__4));
                bnorm = dmax(r__5,r__6);
                if (smini < 1.f && bnorm > 1.f) {
                    if (bnorm > bignum * smini) {
                        *scale = 1.f / 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 (dabs(ur11) > dabs(ui11)) {
                    temp = ui11 / ur11;
                    /* Computing 2nd power */
                    r__1 = temp;
                    ur11r = 1.f / (ur11 * (r__1 * r__1 + 1.f));
                    ui11r = -temp * ur11r;
                } else {
                    temp = ur11 / ui11;
                    /* Computing 2nd power */
                    r__1 = temp;
                    ui11r = -1.f / (ui11 * (r__1 * r__1 + 1.f));
                    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.f / ur11;
                ui11r = 0.f;
                lr21 = cr21 * ur11r;
                li21 = ci21 * ur11r;
                ur12s = ur12 * ur11r;
                ui12s = ui12 * ur11r;
                ur22 = cr22 - ur12 * lr21 + ui12 * li21;
                ui22 = -ur12 * li21 - ui12 * lr21;
            }
            u22abs = dabs(ur22) + dabs(ui22);

            /*           If smaller pivot < SMINI, use SMINI */

            if (u22abs < smini) {
                ur22 = smini;
                ui22 = 0.f;
                *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 */
            r__1 = (dabs(br1) + dabs(bi1)) * (u22abs * (dabs(ur11r) + dabs(
                                                  ui11r))), r__2 = dabs(br2) + dabs(bi2);
            bbnd = dmax(r__1,r__2);
            if (bbnd > 1.f && u22abs < 1.f) {
                if (bbnd >= bignum * u22abs) {
                    *scale = 1.f / bbnd;
                    br1 = *scale * br1;
                    bi1 = *scale * bi1;
                    br2 = *scale * br2;
                    bi2 = *scale * bi2;
                }
            }

            sladiv_(&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 (cswap[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 */
            r__1 = dabs(xr1) + dabs(xi1), r__2 = dabs(xr2) + dabs(xi2);
            *xnorm = dmax(r__1,r__2);

            /*           Further scaling if  norm(A) norm(X) > overflow */

            if (*xnorm > 1.f && cmax > 1.f) {
                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 SLALN2 */

} /* slaln2_ */
예제 #7
0
파일: slaqtr.c 프로젝트: csapng/libflame
/* Subroutine */
int slaqtr_(logical *ltran, logical *lreal, integer *n, real *t, integer *ldt, real *b, real *w, real *scale, real *x, real *work, integer *info)
{
    /* System generated locals */
    integer t_dim1, t_offset, i__1, i__2;
    real r__1, r__2, r__3, r__4, r__5, r__6;
    /* Local variables */
    real d__[4] /* was [2][2] */
    ;
    integer i__, j, k;
    real v[4] /* was [2][2] */
    , z__;
    integer j1, j2, n1, n2;
    real si, xj, sr, rec, eps, tjj, tmp;
    integer ierr;
    real smin;
    extern real sdot_(integer *, real *, integer *, real *, integer *);
    real xmax;
    extern /* Subroutine */
    int sscal_(integer *, real *, real *, integer *);
    integer jnext;
    extern real sasum_(integer *, real *, integer *);
    real sminw, xnorm;
    extern /* Subroutine */
    int saxpy_(integer *, real *, real *, integer *, real *, integer *), slaln2_(logical *, integer *, integer *, real *, real *, real *, integer *, real *, real *, real *, integer *, real *, real *, real *, integer *, real *, real *, integer *);
    real scaloc;
    extern real slamch_(char *), slange_(char *, integer *, integer *, real *, integer *, real *);
    real bignum;
    extern integer isamax_(integer *, real *, integer *);
    extern /* Subroutine */
    int sladiv_(real *, real *, real *, real *, real * , real *);
    logical notran;
    real smlnum;
    /* -- LAPACK auxiliary routine (version 3.4.2) -- */
    /* -- LAPACK is a software package provided by Univ. of Tennessee, -- */
    /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */
    /* September 2012 */
    /* .. Scalar Arguments .. */
    /* .. */
    /* .. Array Arguments .. */
    /* .. */
    /* ===================================================================== */
    /* .. Parameters .. */
    /* .. */
    /* .. Local Scalars .. */
    /* .. */
    /* .. Local Arrays .. */
    /* .. */
    /* .. External Functions .. */
    /* .. */
    /* .. External Subroutines .. */
    /* .. */
    /* .. Intrinsic Functions .. */
    /* .. */
    /* .. Executable Statements .. */
    /* Do not test the input parameters for errors */
    /* Parameter adjustments */
    t_dim1 = *ldt;
    t_offset = 1 + t_dim1;
    t -= t_offset;
    --b;
    --x;
    --work;
    /* Function Body */
    notran = ! (*ltran);
    *info = 0;
    /* Quick return if possible */
    if (*n == 0)
    {
        return 0;
    }
    /* Set constants to control overflow */
    eps = slamch_("P");
    smlnum = slamch_("S") / eps;
    bignum = 1.f / smlnum;
    xnorm = slange_("M", n, n, &t[t_offset], ldt, d__);
    if (! (*lreal))
    {
        /* Computing MAX */
        r__1 = xnorm, r__2 = abs(*w);
        r__1 = max(r__1,r__2);
        r__2 = slange_( "M", n, &c__1, &b[1], n, d__); // ; expr subst
        xnorm = max(r__1,r__2);
    }
    /* Computing MAX */
    r__1 = smlnum;
    r__2 = eps * xnorm; // , expr subst
    smin = max(r__1,r__2);
    /* Compute 1-norm of each column of strictly upper triangular */
    /* part of T to control overflow in triangular solver. */
    work[1] = 0.f;
    i__1 = *n;
    for (j = 2;
            j <= i__1;
            ++j)
    {
        i__2 = j - 1;
        work[j] = sasum_(&i__2, &t[j * t_dim1 + 1], &c__1);
        /* L10: */
    }
    if (! (*lreal))
    {
        i__1 = *n;
        for (i__ = 2;
                i__ <= i__1;
                ++i__)
        {
            work[i__] += (r__1 = b[i__], abs(r__1));
            /* L20: */
        }
    }
    n2 = *n << 1;
    n1 = *n;
    if (! (*lreal))
    {
        n1 = n2;
    }
    k = isamax_(&n1, &x[1], &c__1);
    xmax = (r__1 = x[k], abs(r__1));
    *scale = 1.f;
    if (xmax > bignum)
    {
        *scale = bignum / xmax;
        sscal_(&n1, scale, &x[1], &c__1);
        xmax = bignum;
    }
    if (*lreal)
    {
        if (notran)
        {
            /* Solve T*p = scale*c */
            jnext = *n;
            for (j = *n;
                    j >= 1;
                    --j)
            {
                if (j > jnext)
                {
                    goto L30;
                }
                j1 = j;
                j2 = j;
                jnext = j - 1;
                if (j > 1)
                {
                    if (t[j + (j - 1) * t_dim1] != 0.f)
                    {
                        j1 = j - 1;
                        jnext = j - 2;
                    }
                }
                if (j1 == j2)
                {
                    /* Meet 1 by 1 diagonal block */
                    /* Scale to avoid overflow when computing */
                    /* x(j) = b(j)/T(j,j) */
                    xj = (r__1 = x[j1], abs(r__1));
                    tjj = (r__1 = t[j1 + j1 * t_dim1], abs(r__1));
                    tmp = t[j1 + j1 * t_dim1];
                    if (tjj < smin)
                    {
                        tmp = smin;
                        tjj = smin;
                        *info = 1;
                    }
                    if (xj == 0.f)
                    {
                        goto L30;
                    }
                    if (tjj < 1.f)
                    {
                        if (xj > bignum * tjj)
                        {
                            rec = 1.f / xj;
                            sscal_(n, &rec, &x[1], &c__1);
                            *scale *= rec;
                            xmax *= rec;
                        }
                    }
                    x[j1] /= tmp;
                    xj = (r__1 = x[j1], abs(r__1));
                    /* Scale x if necessary to avoid overflow when adding a */
                    /* multiple of column j1 of T. */
                    if (xj > 1.f)
                    {
                        rec = 1.f / xj;
                        if (work[j1] > (bignum - xmax) * rec)
                        {
                            sscal_(n, &rec, &x[1], &c__1);
                            *scale *= rec;
                        }
                    }
                    if (j1 > 1)
                    {
                        i__1 = j1 - 1;
                        r__1 = -x[j1];
                        saxpy_(&i__1, &r__1, &t[j1 * t_dim1 + 1], &c__1, &x[1] , &c__1);
                        i__1 = j1 - 1;
                        k = isamax_(&i__1, &x[1], &c__1);
                        xmax = (r__1 = x[k], abs(r__1));
                    }
                }
                else
                {
                    /* Meet 2 by 2 diagonal block */
                    /* Call 2 by 2 linear system solve, to take */
                    /* care of possible overflow by scaling factor. */
                    d__[0] = x[j1];
                    d__[1] = x[j2];
                    slaln2_(&c_false, &c__2, &c__1, &smin, &c_b21, &t[j1 + j1 * t_dim1], ldt, &c_b21, &c_b21, d__, &c__2, & c_b25, &c_b25, v, &c__2, &scaloc, &xnorm, &ierr);
                    if (ierr != 0)
                    {
                        *info = 2;
                    }
                    if (scaloc != 1.f)
                    {
                        sscal_(n, &scaloc, &x[1], &c__1);
                        *scale *= scaloc;
                    }
                    x[j1] = v[0];
                    x[j2] = v[1];
                    /* Scale V(1,1) (= X(J1)) and/or V(2,1) (=X(J2)) */
                    /* to avoid overflow in updating right-hand side. */
                    /* Computing MAX */
                    r__1 = abs(v[0]);
                    r__2 = abs(v[1]); // , expr subst
                    xj = max(r__1,r__2);
                    if (xj > 1.f)
                    {
                        rec = 1.f / xj;
                        /* Computing MAX */
                        r__1 = work[j1];
                        r__2 = work[j2]; // , expr subst
                        if (max(r__1,r__2) > (bignum - xmax) * rec)
                        {
                            sscal_(n, &rec, &x[1], &c__1);
                            *scale *= rec;
                        }
                    }
                    /* Update right-hand side */
                    if (j1 > 1)
                    {
                        i__1 = j1 - 1;
                        r__1 = -x[j1];
                        saxpy_(&i__1, &r__1, &t[j1 * t_dim1 + 1], &c__1, &x[1] , &c__1);
                        i__1 = j1 - 1;
                        r__1 = -x[j2];
                        saxpy_(&i__1, &r__1, &t[j2 * t_dim1 + 1], &c__1, &x[1] , &c__1);
                        i__1 = j1 - 1;
                        k = isamax_(&i__1, &x[1], &c__1);
                        xmax = (r__1 = x[k], abs(r__1));
                    }
                }
L30:
                ;
            }
        }
        else
        {
            /* Solve T**T*p = scale*c */
            jnext = 1;
            i__1 = *n;
            for (j = 1;
                    j <= i__1;
                    ++j)
            {
                if (j < jnext)
                {
                    goto L40;
                }
                j1 = j;
                j2 = j;
                jnext = j + 1;
                if (j < *n)
                {
                    if (t[j + 1 + j * t_dim1] != 0.f)
                    {
                        j2 = j + 1;
                        jnext = j + 2;
                    }
                }
                if (j1 == j2)
                {
                    /* 1 by 1 diagonal block */
                    /* Scale if necessary to avoid overflow in forming the */
                    /* right-hand side element by inner product. */
                    xj = (r__1 = x[j1], abs(r__1));
                    if (xmax > 1.f)
                    {
                        rec = 1.f / xmax;
                        if (work[j1] > (bignum - xj) * rec)
                        {
                            sscal_(n, &rec, &x[1], &c__1);
                            *scale *= rec;
                            xmax *= rec;
                        }
                    }
                    i__2 = j1 - 1;
                    x[j1] -= sdot_(&i__2, &t[j1 * t_dim1 + 1], &c__1, &x[1], & c__1);
                    xj = (r__1 = x[j1], abs(r__1));
                    tjj = (r__1 = t[j1 + j1 * t_dim1], abs(r__1));
                    tmp = t[j1 + j1 * t_dim1];
                    if (tjj < smin)
                    {
                        tmp = smin;
                        tjj = smin;
                        *info = 1;
                    }
                    if (tjj < 1.f)
                    {
                        if (xj > bignum * tjj)
                        {
                            rec = 1.f / xj;
                            sscal_(n, &rec, &x[1], &c__1);
                            *scale *= rec;
                            xmax *= rec;
                        }
                    }
                    x[j1] /= tmp;
                    /* Computing MAX */
                    r__2 = xmax;
                    r__3 = (r__1 = x[j1], abs(r__1)); // , expr subst
                    xmax = max(r__2,r__3);
                }
                else
                {
                    /* 2 by 2 diagonal block */
                    /* Scale if necessary to avoid overflow in forming the */
                    /* right-hand side elements by inner product. */
                    /* Computing MAX */
                    r__3 = (r__1 = x[j1], abs(r__1));
                    r__4 = (r__2 = x[j2], abs(r__2)); // , expr subst
                    xj = max(r__3,r__4);
                    if (xmax > 1.f)
                    {
                        rec = 1.f / xmax;
                        /* Computing MAX */
                        r__1 = work[j2];
                        r__2 = work[j1]; // , expr subst
                        if (max(r__1,r__2) > (bignum - xj) * rec)
                        {
                            sscal_(n, &rec, &x[1], &c__1);
                            *scale *= rec;
                            xmax *= rec;
                        }
                    }
                    i__2 = j1 - 1;
                    d__[0] = x[j1] - sdot_(&i__2, &t[j1 * t_dim1 + 1], &c__1, &x[1], &c__1);
                    i__2 = j1 - 1;
                    d__[1] = x[j2] - sdot_(&i__2, &t[j2 * t_dim1 + 1], &c__1, &x[1], &c__1);
                    slaln2_(&c_true, &c__2, &c__1, &smin, &c_b21, &t[j1 + j1 * t_dim1], ldt, &c_b21, &c_b21, d__, &c__2, &c_b25, &c_b25, v, &c__2, &scaloc, &xnorm, &ierr);
                    if (ierr != 0)
                    {
                        *info = 2;
                    }
                    if (scaloc != 1.f)
                    {
                        sscal_(n, &scaloc, &x[1], &c__1);
                        *scale *= scaloc;
                    }
                    x[j1] = v[0];
                    x[j2] = v[1];
                    /* Computing MAX */
                    r__3 = (r__1 = x[j1], abs(r__1));
                    r__4 = (r__2 = x[j2], abs(r__2));
                    r__3 = max(r__3,r__4); // ; expr subst
                    xmax = max(r__3,xmax);
                }
L40:
                ;
            }
        }
    }
    else
    {
        /* Computing MAX */
        r__1 = eps * abs(*w);
        sminw = max(r__1,smin);
        if (notran)
        {
            /* Solve (T + iB)*(p+iq) = c+id */
            jnext = *n;
            for (j = *n;
                    j >= 1;
                    --j)
            {
                if (j > jnext)
                {
                    goto L70;
                }
                j1 = j;
                j2 = j;
                jnext = j - 1;
                if (j > 1)
                {
                    if (t[j + (j - 1) * t_dim1] != 0.f)
                    {
                        j1 = j - 1;
                        jnext = j - 2;
                    }
                }
                if (j1 == j2)
                {
                    /* 1 by 1 diagonal block */
                    /* Scale if necessary to avoid overflow in division */
                    z__ = *w;
                    if (j1 == 1)
                    {
                        z__ = b[1];
                    }
                    xj = (r__1 = x[j1], abs(r__1)) + (r__2 = x[*n + j1], abs( r__2));
                    tjj = (r__1 = t[j1 + j1 * t_dim1], abs(r__1)) + abs(z__);
                    tmp = t[j1 + j1 * t_dim1];
                    if (tjj < sminw)
                    {
                        tmp = sminw;
                        tjj = sminw;
                        *info = 1;
                    }
                    if (xj == 0.f)
                    {
                        goto L70;
                    }
                    if (tjj < 1.f)
                    {
                        if (xj > bignum * tjj)
                        {
                            rec = 1.f / xj;
                            sscal_(&n2, &rec, &x[1], &c__1);
                            *scale *= rec;
                            xmax *= rec;
                        }
                    }
                    sladiv_(&x[j1], &x[*n + j1], &tmp, &z__, &sr, &si);
                    x[j1] = sr;
                    x[*n + j1] = si;
                    xj = (r__1 = x[j1], abs(r__1)) + (r__2 = x[*n + j1], abs( r__2));
                    /* Scale x if necessary to avoid overflow when adding a */
                    /* multiple of column j1 of T. */
                    if (xj > 1.f)
                    {
                        rec = 1.f / xj;
                        if (work[j1] > (bignum - xmax) * rec)
                        {
                            sscal_(&n2, &rec, &x[1], &c__1);
                            *scale *= rec;
                        }
                    }
                    if (j1 > 1)
                    {
                        i__1 = j1 - 1;
                        r__1 = -x[j1];
                        saxpy_(&i__1, &r__1, &t[j1 * t_dim1 + 1], &c__1, &x[1] , &c__1);
                        i__1 = j1 - 1;
                        r__1 = -x[*n + j1];
                        saxpy_(&i__1, &r__1, &t[j1 * t_dim1 + 1], &c__1, &x[* n + 1], &c__1);
                        x[1] += b[j1] * x[*n + j1];
                        x[*n + 1] -= b[j1] * x[j1];
                        xmax = 0.f;
                        i__1 = j1 - 1;
                        for (k = 1;
                                k <= i__1;
                                ++k)
                        {
                            /* Computing MAX */
                            r__3 = xmax;
                            r__4 = (r__1 = x[k], abs(r__1)) + ( r__2 = x[k + *n], abs(r__2)); // , expr subst
                            xmax = max(r__3,r__4);
                            /* L50: */
                        }
                    }
                }
                else
                {
                    /* Meet 2 by 2 diagonal block */
                    d__[0] = x[j1];
                    d__[1] = x[j2];
                    d__[2] = x[*n + j1];
                    d__[3] = x[*n + j2];
                    r__1 = -(*w);
                    slaln2_(&c_false, &c__2, &c__2, &sminw, &c_b21, &t[j1 + j1 * t_dim1], ldt, &c_b21, &c_b21, d__, &c__2, & c_b25, &r__1, v, &c__2, &scaloc, &xnorm, &ierr);
                    if (ierr != 0)
                    {
                        *info = 2;
                    }
                    if (scaloc != 1.f)
                    {
                        i__1 = *n << 1;
                        sscal_(&i__1, &scaloc, &x[1], &c__1);
                        *scale = scaloc * *scale;
                    }
                    x[j1] = v[0];
                    x[j2] = v[1];
                    x[*n + j1] = v[2];
                    x[*n + j2] = v[3];
                    /* Scale X(J1), .... to avoid overflow in */
                    /* updating right hand side. */
                    /* Computing MAX */
                    r__1 = abs(v[0]) + abs(v[2]);
                    r__2 = abs(v[1]) + abs(v[3]) ; // , expr subst
                    xj = max(r__1,r__2);
                    if (xj > 1.f)
                    {
                        rec = 1.f / xj;
                        /* Computing MAX */
                        r__1 = work[j1];
                        r__2 = work[j2]; // , expr subst
                        if (max(r__1,r__2) > (bignum - xmax) * rec)
                        {
                            sscal_(&n2, &rec, &x[1], &c__1);
                            *scale *= rec;
                        }
                    }
                    /* Update the right-hand side. */
                    if (j1 > 1)
                    {
                        i__1 = j1 - 1;
                        r__1 = -x[j1];
                        saxpy_(&i__1, &r__1, &t[j1 * t_dim1 + 1], &c__1, &x[1] , &c__1);
                        i__1 = j1 - 1;
                        r__1 = -x[j2];
                        saxpy_(&i__1, &r__1, &t[j2 * t_dim1 + 1], &c__1, &x[1] , &c__1);
                        i__1 = j1 - 1;
                        r__1 = -x[*n + j1];
                        saxpy_(&i__1, &r__1, &t[j1 * t_dim1 + 1], &c__1, &x[* n + 1], &c__1);
                        i__1 = j1 - 1;
                        r__1 = -x[*n + j2];
                        saxpy_(&i__1, &r__1, &t[j2 * t_dim1 + 1], &c__1, &x[* n + 1], &c__1);
                        x[1] = x[1] + b[j1] * x[*n + j1] + b[j2] * x[*n + j2];
                        x[*n + 1] = x[*n + 1] - b[j1] * x[j1] - b[j2] * x[j2];
                        xmax = 0.f;
                        i__1 = j1 - 1;
                        for (k = 1;
                                k <= i__1;
                                ++k)
                        {
                            /* Computing MAX */
                            r__3 = (r__1 = x[k], abs(r__1)) + (r__2 = x[k + * n], abs(r__2));
                            xmax = max(r__3,xmax);
                            /* L60: */
                        }
                    }
                }
L70:
                ;
            }
        }
        else
        {
            /* Solve (T + iB)**T*(p+iq) = c+id */
            jnext = 1;
            i__1 = *n;
            for (j = 1;
                    j <= i__1;
                    ++j)
            {
                if (j < jnext)
                {
                    goto L80;
                }
                j1 = j;
                j2 = j;
                jnext = j + 1;
                if (j < *n)
                {
                    if (t[j + 1 + j * t_dim1] != 0.f)
                    {
                        j2 = j + 1;
                        jnext = j + 2;
                    }
                }
                if (j1 == j2)
                {
                    /* 1 by 1 diagonal block */
                    /* Scale if necessary to avoid overflow in forming the */
                    /* right-hand side element by inner product. */
                    xj = (r__1 = x[j1], abs(r__1)) + (r__2 = x[j1 + *n], abs( r__2));
                    if (xmax > 1.f)
                    {
                        rec = 1.f / xmax;
                        if (work[j1] > (bignum - xj) * rec)
                        {
                            sscal_(&n2, &rec, &x[1], &c__1);
                            *scale *= rec;
                            xmax *= rec;
                        }
                    }
                    i__2 = j1 - 1;
                    x[j1] -= sdot_(&i__2, &t[j1 * t_dim1 + 1], &c__1, &x[1], & c__1);
                    i__2 = j1 - 1;
                    x[*n + j1] -= sdot_(&i__2, &t[j1 * t_dim1 + 1], &c__1, &x[ *n + 1], &c__1);
                    if (j1 > 1)
                    {
                        x[j1] -= b[j1] * x[*n + 1];
                        x[*n + j1] += b[j1] * x[1];
                    }
                    xj = (r__1 = x[j1], abs(r__1)) + (r__2 = x[j1 + *n], abs( r__2));
                    z__ = *w;
                    if (j1 == 1)
                    {
                        z__ = b[1];
                    }
                    /* Scale if necessary to avoid overflow in */
                    /* complex division */
                    tjj = (r__1 = t[j1 + j1 * t_dim1], abs(r__1)) + abs(z__);
                    tmp = t[j1 + j1 * t_dim1];
                    if (tjj < sminw)
                    {
                        tmp = sminw;
                        tjj = sminw;
                        *info = 1;
                    }
                    if (tjj < 1.f)
                    {
                        if (xj > bignum * tjj)
                        {
                            rec = 1.f / xj;
                            sscal_(&n2, &rec, &x[1], &c__1);
                            *scale *= rec;
                            xmax *= rec;
                        }
                    }
                    r__1 = -z__;
                    sladiv_(&x[j1], &x[*n + j1], &tmp, &r__1, &sr, &si);
                    x[j1] = sr;
                    x[j1 + *n] = si;
                    /* Computing MAX */
                    r__3 = (r__1 = x[j1], abs(r__1)) + (r__2 = x[j1 + *n], abs(r__2));
                    xmax = max(r__3,xmax);
                }
                else
                {
                    /* 2 by 2 diagonal block */
                    /* Scale if necessary to avoid overflow in forming the */
                    /* right-hand side element by inner product. */
                    /* Computing MAX */
                    r__5 = (r__1 = x[j1], abs(r__1)) + (r__2 = x[*n + j1], abs(r__2));
                    r__6 = (r__3 = x[j2], abs(r__3)) + ( r__4 = x[*n + j2], abs(r__4)); // , expr subst
                    xj = max(r__5,r__6);
                    if (xmax > 1.f)
                    {
                        rec = 1.f / xmax;
                        /* Computing MAX */
                        r__1 = work[j1];
                        r__2 = work[j2]; // , expr subst
                        if (max(r__1,r__2) > (bignum - xj) / xmax)
                        {
                            sscal_(&n2, &rec, &x[1], &c__1);
                            *scale *= rec;
                            xmax *= rec;
                        }
                    }
                    i__2 = j1 - 1;
                    d__[0] = x[j1] - sdot_(&i__2, &t[j1 * t_dim1 + 1], &c__1, &x[1], &c__1);
                    i__2 = j1 - 1;
                    d__[1] = x[j2] - sdot_(&i__2, &t[j2 * t_dim1 + 1], &c__1, &x[1], &c__1);
                    i__2 = j1 - 1;
                    d__[2] = x[*n + j1] - sdot_(&i__2, &t[j1 * t_dim1 + 1], & c__1, &x[*n + 1], &c__1);
                    i__2 = j1 - 1;
                    d__[3] = x[*n + j2] - sdot_(&i__2, &t[j2 * t_dim1 + 1], & c__1, &x[*n + 1], &c__1);
                    d__[0] -= b[j1] * x[*n + 1];
                    d__[1] -= b[j2] * x[*n + 1];
                    d__[2] += b[j1] * x[1];
                    d__[3] += b[j2] * x[1];
                    slaln2_(&c_true, &c__2, &c__2, &sminw, &c_b21, &t[j1 + j1 * t_dim1], ldt, &c_b21, &c_b21, d__, &c__2, & c_b25, w, v, &c__2, &scaloc, &xnorm, &ierr);
                    if (ierr != 0)
                    {
                        *info = 2;
                    }
                    if (scaloc != 1.f)
                    {
                        sscal_(&n2, &scaloc, &x[1], &c__1);
                        *scale = scaloc * *scale;
                    }
                    x[j1] = v[0];
                    x[j2] = v[1];
                    x[*n + j1] = v[2];
                    x[*n + j2] = v[3];
                    /* Computing MAX */
                    r__5 = (r__1 = x[j1], abs(r__1)) + (r__2 = x[*n + j1], abs(r__2));
                    r__6 = (r__3 = x[j2], abs(r__3)) + ( r__4 = x[*n + j2], abs(r__4));
                    r__5 = max(r__5, r__6); // ; expr subst
                    xmax = max(r__5,xmax);
                }
L80:
                ;
            }
        }
    }
    return 0;
    /* End of SLAQTR */
}