slag2.c
Go to the documentation of this file.
00001 /* slag2.f -- translated by f2c (version 20061008).
00002    You must link the resulting object file with libf2c:
00003         on Microsoft Windows system, link with libf2c.lib;
00004         on Linux or Unix systems, link with .../path/to/libf2c.a -lm
00005         or, if you install libf2c.a in a standard place, with -lf2c -lm
00006         -- in that order, at the end of the command line, as in
00007                 cc *.o -lf2c -lm
00008         Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,
00009 
00010                 http://www.netlib.org/f2c/libf2c.zip
00011 */
00012 
00013 #include "f2c.h"
00014 #include "blaswrap.h"
00015 
00016 /* Subroutine */ int slag2_(real *a, integer *lda, real *b, integer *ldb, 
00017         real *safmin, real *scale1, real *scale2, real *wr1, real *wr2, real *
00018         wi)
00019 {
00020     /* System generated locals */
00021     integer a_dim1, a_offset, b_dim1, b_offset;
00022     real r__1, r__2, r__3, r__4, r__5, r__6;
00023 
00024     /* Builtin functions */
00025     double sqrt(doublereal), r_sign(real *, real *);
00026 
00027     /* Local variables */
00028     real r__, c1, c2, c3, c4, c5, s1, s2, a11, a12, a21, a22, b11, b12, b22, 
00029             pp, qq, ss, as11, as12, as22, sum, abi22, diff, bmin, wbig, wabs, 
00030             wdet, binv11, binv22, discr, anorm, bnorm, bsize, shift, rtmin, 
00031             rtmax, wsize, ascale, bscale, wscale, safmax, wsmall;
00032 
00033 
00034 /*  -- LAPACK auxiliary routine (version 3.2) -- */
00035 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00036 /*     November 2006 */
00037 
00038 /*     .. Scalar Arguments .. */
00039 /*     .. */
00040 /*     .. Array Arguments .. */
00041 /*     .. */
00042 
00043 /*  Purpose */
00044 /*  ======= */
00045 
00046 /*  SLAG2 computes the eigenvalues of a 2 x 2 generalized eigenvalue */
00047 /*  problem  A - w B, with scaling as necessary to avoid over-/underflow. */
00048 
00049 /*  The scaling factor "s" results in a modified eigenvalue equation */
00050 
00051 /*      s A - w B */
00052 
00053 /*  where  s  is a non-negative scaling factor chosen so that  w,  w B, */
00054 /*  and  s A  do not overflow and, if possible, do not underflow, either. */
00055 
00056 /*  Arguments */
00057 /*  ========= */
00058 
00059 /*  A       (input) REAL array, dimension (LDA, 2) */
00060 /*          On entry, the 2 x 2 matrix A.  It is assumed that its 1-norm */
00061 /*          is less than 1/SAFMIN.  Entries less than */
00062 /*          sqrt(SAFMIN)*norm(A) are subject to being treated as zero. */
00063 
00064 /*  LDA     (input) INTEGER */
00065 /*          The leading dimension of the array A.  LDA >= 2. */
00066 
00067 /*  B       (input) REAL array, dimension (LDB, 2) */
00068 /*          On entry, the 2 x 2 upper triangular matrix B.  It is */
00069 /*          assumed that the one-norm of B is less than 1/SAFMIN.  The */
00070 /*          diagonals should be at least sqrt(SAFMIN) times the largest */
00071 /*          element of B (in absolute value); if a diagonal is smaller */
00072 /*          than that, then  +/- sqrt(SAFMIN) will be used instead of */
00073 /*          that diagonal. */
00074 
00075 /*  LDB     (input) INTEGER */
00076 /*          The leading dimension of the array B.  LDB >= 2. */
00077 
00078 /*  SAFMIN  (input) REAL */
00079 /*          The smallest positive number s.t. 1/SAFMIN does not */
00080 /*          overflow.  (This should always be SLAMCH('S') -- it is an */
00081 /*          argument in order to avoid having to call SLAMCH frequently.) */
00082 
00083 /*  SCALE1  (output) REAL */
00084 /*          A scaling factor used to avoid over-/underflow in the */
00085 /*          eigenvalue equation which defines the first eigenvalue.  If */
00086 /*          the eigenvalues are complex, then the eigenvalues are */
00087 /*          ( WR1  +/-  WI i ) / SCALE1  (which may lie outside the */
00088 /*          exponent range of the machine), SCALE1=SCALE2, and SCALE1 */
00089 /*          will always be positive.  If the eigenvalues are real, then */
00090 /*          the first (real) eigenvalue is  WR1 / SCALE1 , but this may */
00091 /*          overflow or underflow, and in fact, SCALE1 may be zero or */
00092 /*          less than the underflow threshhold if the exact eigenvalue */
00093 /*          is sufficiently large. */
00094 
00095 /*  SCALE2  (output) REAL */
00096 /*          A scaling factor used to avoid over-/underflow in the */
00097 /*          eigenvalue equation which defines the second eigenvalue.  If */
00098 /*          the eigenvalues are complex, then SCALE2=SCALE1.  If the */
00099 /*          eigenvalues are real, then the second (real) eigenvalue is */
00100 /*          WR2 / SCALE2 , but this may overflow or underflow, and in */
00101 /*          fact, SCALE2 may be zero or less than the underflow */
00102 /*          threshhold if the exact eigenvalue is sufficiently large. */
00103 
00104 /*  WR1     (output) REAL */
00105 /*          If the eigenvalue is real, then WR1 is SCALE1 times the */
00106 /*          eigenvalue closest to the (2,2) element of A B**(-1).  If the */
00107 /*          eigenvalue is complex, then WR1=WR2 is SCALE1 times the real */
00108 /*          part of the eigenvalues. */
00109 
00110 /*  WR2     (output) REAL */
00111 /*          If the eigenvalue is real, then WR2 is SCALE2 times the */
00112 /*          other eigenvalue.  If the eigenvalue is complex, then */
00113 /*          WR1=WR2 is SCALE1 times the real part of the eigenvalues. */
00114 
00115 /*  WI      (output) REAL */
00116 /*          If the eigenvalue is real, then WI is zero.  If the */
00117 /*          eigenvalue is complex, then WI is SCALE1 times the imaginary */
00118 /*          part of the eigenvalues.  WI will always be non-negative. */
00119 
00120 /*  ===================================================================== */
00121 
00122 /*     .. Parameters .. */
00123 /*     .. */
00124 /*     .. Local Scalars .. */
00125 /*     .. */
00126 /*     .. Intrinsic Functions .. */
00127 /*     .. */
00128 /*     .. Executable Statements .. */
00129 
00130     /* Parameter adjustments */
00131     a_dim1 = *lda;
00132     a_offset = 1 + a_dim1;
00133     a -= a_offset;
00134     b_dim1 = *ldb;
00135     b_offset = 1 + b_dim1;
00136     b -= b_offset;
00137 
00138     /* Function Body */
00139     rtmin = sqrt(*safmin);
00140     rtmax = 1.f / rtmin;
00141     safmax = 1.f / *safmin;
00142 
00143 /*     Scale A */
00144 
00145 /* Computing MAX */
00146     r__5 = (r__1 = a[a_dim1 + 1], dabs(r__1)) + (r__2 = a[a_dim1 + 2], dabs(
00147             r__2)), r__6 = (r__3 = a[(a_dim1 << 1) + 1], dabs(r__3)) + (r__4 =
00148              a[(a_dim1 << 1) + 2], dabs(r__4)), r__5 = max(r__5,r__6);
00149     anorm = dmax(r__5,*safmin);
00150     ascale = 1.f / anorm;
00151     a11 = ascale * a[a_dim1 + 1];
00152     a21 = ascale * a[a_dim1 + 2];
00153     a12 = ascale * a[(a_dim1 << 1) + 1];
00154     a22 = ascale * a[(a_dim1 << 1) + 2];
00155 
00156 /*     Perturb B if necessary to insure non-singularity */
00157 
00158     b11 = b[b_dim1 + 1];
00159     b12 = b[(b_dim1 << 1) + 1];
00160     b22 = b[(b_dim1 << 1) + 2];
00161 /* Computing MAX */
00162     r__1 = dabs(b11), r__2 = dabs(b12), r__1 = max(r__1,r__2), r__2 = dabs(
00163             b22), r__1 = max(r__1,r__2);
00164     bmin = rtmin * dmax(r__1,rtmin);
00165     if (dabs(b11) < bmin) {
00166         b11 = r_sign(&bmin, &b11);
00167     }
00168     if (dabs(b22) < bmin) {
00169         b22 = r_sign(&bmin, &b22);
00170     }
00171 
00172 /*     Scale B */
00173 
00174 /* Computing MAX */
00175     r__1 = dabs(b11), r__2 = dabs(b12) + dabs(b22), r__1 = max(r__1,r__2);
00176     bnorm = dmax(r__1,*safmin);
00177 /* Computing MAX */
00178     r__1 = dabs(b11), r__2 = dabs(b22);
00179     bsize = dmax(r__1,r__2);
00180     bscale = 1.f / bsize;
00181     b11 *= bscale;
00182     b12 *= bscale;
00183     b22 *= bscale;
00184 
00185 /*     Compute larger eigenvalue by method described by C. van Loan */
00186 
00187 /*     ( AS is A shifted by -SHIFT*B ) */
00188 
00189     binv11 = 1.f / b11;
00190     binv22 = 1.f / b22;
00191     s1 = a11 * binv11;
00192     s2 = a22 * binv22;
00193     if (dabs(s1) <= dabs(s2)) {
00194         as12 = a12 - s1 * b12;
00195         as22 = a22 - s1 * b22;
00196         ss = a21 * (binv11 * binv22);
00197         abi22 = as22 * binv22 - ss * b12;
00198         pp = abi22 * .5f;
00199         shift = s1;
00200     } else {
00201         as12 = a12 - s2 * b12;
00202         as11 = a11 - s2 * b11;
00203         ss = a21 * (binv11 * binv22);
00204         abi22 = -ss * b12;
00205         pp = (as11 * binv11 + abi22) * .5f;
00206         shift = s2;
00207     }
00208     qq = ss * as12;
00209     if ((r__1 = pp * rtmin, dabs(r__1)) >= 1.f) {
00210 /* Computing 2nd power */
00211         r__1 = rtmin * pp;
00212         discr = r__1 * r__1 + qq * *safmin;
00213         r__ = sqrt((dabs(discr))) * rtmax;
00214     } else {
00215 /* Computing 2nd power */
00216         r__1 = pp;
00217         if (r__1 * r__1 + dabs(qq) <= *safmin) {
00218 /* Computing 2nd power */
00219             r__1 = rtmax * pp;
00220             discr = r__1 * r__1 + qq * safmax;
00221             r__ = sqrt((dabs(discr))) * rtmin;
00222         } else {
00223 /* Computing 2nd power */
00224             r__1 = pp;
00225             discr = r__1 * r__1 + qq;
00226             r__ = sqrt((dabs(discr)));
00227         }
00228     }
00229 
00230 /*     Note: the test of R in the following IF is to cover the case when */
00231 /*           DISCR is small and negative and is flushed to zero during */
00232 /*           the calculation of R.  On machines which have a consistent */
00233 /*           flush-to-zero threshhold and handle numbers above that */
00234 /*           threshhold correctly, it would not be necessary. */
00235 
00236     if (discr >= 0.f || r__ == 0.f) {
00237         sum = pp + r_sign(&r__, &pp);
00238         diff = pp - r_sign(&r__, &pp);
00239         wbig = shift + sum;
00240 
00241 /*        Compute smaller eigenvalue */
00242 
00243         wsmall = shift + diff;
00244 /* Computing MAX */
00245         r__1 = dabs(wsmall);
00246         if (dabs(wbig) * .5f > dmax(r__1,*safmin)) {
00247             wdet = (a11 * a22 - a12 * a21) * (binv11 * binv22);
00248             wsmall = wdet / wbig;
00249         }
00250 
00251 /*        Choose (real) eigenvalue closest to 2,2 element of A*B**(-1) */
00252 /*        for WR1. */
00253 
00254         if (pp > abi22) {
00255             *wr1 = dmin(wbig,wsmall);
00256             *wr2 = dmax(wbig,wsmall);
00257         } else {
00258             *wr1 = dmax(wbig,wsmall);
00259             *wr2 = dmin(wbig,wsmall);
00260         }
00261         *wi = 0.f;
00262     } else {
00263 
00264 /*        Complex eigenvalues */
00265 
00266         *wr1 = shift + pp;
00267         *wr2 = *wr1;
00268         *wi = r__;
00269     }
00270 
00271 /*     Further scaling to avoid underflow and overflow in computing */
00272 /*     SCALE1 and overflow in computing w*B. */
00273 
00274 /*     This scale factor (WSCALE) is bounded from above using C1 and C2, */
00275 /*     and from below using C3 and C4. */
00276 /*        C1 implements the condition  s A  must never overflow. */
00277 /*        C2 implements the condition  w B  must never overflow. */
00278 /*        C3, with C2, */
00279 /*           implement the condition that s A - w B must never overflow. */
00280 /*        C4 implements the condition  s    should not underflow. */
00281 /*        C5 implements the condition  max(s,|w|) should be at least 2. */
00282 
00283     c1 = bsize * (*safmin * dmax(1.f,ascale));
00284     c2 = *safmin * dmax(1.f,bnorm);
00285     c3 = bsize * *safmin;
00286     if (ascale <= 1.f && bsize <= 1.f) {
00287 /* Computing MIN */
00288         r__1 = 1.f, r__2 = ascale / *safmin * bsize;
00289         c4 = dmin(r__1,r__2);
00290     } else {
00291         c4 = 1.f;
00292     }
00293     if (ascale <= 1.f || bsize <= 1.f) {
00294 /* Computing MIN */
00295         r__1 = 1.f, r__2 = ascale * bsize;
00296         c5 = dmin(r__1,r__2);
00297     } else {
00298         c5 = 1.f;
00299     }
00300 
00301 /*     Scale first eigenvalue */
00302 
00303     wabs = dabs(*wr1) + dabs(*wi);
00304 /* Computing MAX */
00305 /* Computing MIN */
00306     r__3 = c4, r__4 = dmax(wabs,c5) * .5f;
00307     r__1 = max(*safmin,c1), r__2 = (wabs * c2 + c3) * 1.0000100000000001f, 
00308             r__1 = max(r__1,r__2), r__2 = dmin(r__3,r__4);
00309     wsize = dmax(r__1,r__2);
00310     if (wsize != 1.f) {
00311         wscale = 1.f / wsize;
00312         if (wsize > 1.f) {
00313             *scale1 = dmax(ascale,bsize) * wscale * dmin(ascale,bsize);
00314         } else {
00315             *scale1 = dmin(ascale,bsize) * wscale * dmax(ascale,bsize);
00316         }
00317         *wr1 *= wscale;
00318         if (*wi != 0.f) {
00319             *wi *= wscale;
00320             *wr2 = *wr1;
00321             *scale2 = *scale1;
00322         }
00323     } else {
00324         *scale1 = ascale * bsize;
00325         *scale2 = *scale1;
00326     }
00327 
00328 /*     Scale second eigenvalue (if real) */
00329 
00330     if (*wi == 0.f) {
00331 /* Computing MAX */
00332 /* Computing MIN */
00333 /* Computing MAX */
00334         r__5 = dabs(*wr2);
00335         r__3 = c4, r__4 = dmax(r__5,c5) * .5f;
00336         r__1 = max(*safmin,c1), r__2 = (dabs(*wr2) * c2 + c3) * 
00337                 1.0000100000000001f, r__1 = max(r__1,r__2), r__2 = dmin(r__3,
00338                 r__4);
00339         wsize = dmax(r__1,r__2);
00340         if (wsize != 1.f) {
00341             wscale = 1.f / wsize;
00342             if (wsize > 1.f) {
00343                 *scale2 = dmax(ascale,bsize) * wscale * dmin(ascale,bsize);
00344             } else {
00345                 *scale2 = dmin(ascale,bsize) * wscale * dmax(ascale,bsize);
00346             }
00347             *wr2 *= wscale;
00348         } else {
00349             *scale2 = ascale * bsize;
00350         }
00351     }
00352 
00353 /*     End of SLAG2 */
00354 
00355     return 0;
00356 } /* slag2_ */


swiftnav
Author(s):
autogenerated on Sat Jun 8 2019 18:56:10