dlaic1.c
Go to the documentation of this file.
00001 /* dlaic1.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 /* Table of constant values */
00017 
00018 static integer c__1 = 1;
00019 static doublereal c_b5 = 1.;
00020 
00021 /* Subroutine */ int dlaic1_(integer *job, integer *j, doublereal *x, 
00022         doublereal *sest, doublereal *w, doublereal *gamma, doublereal *
00023         sestpr, doublereal *s, doublereal *c__)
00024 {
00025     /* System generated locals */
00026     doublereal d__1, d__2, d__3, d__4;
00027 
00028     /* Builtin functions */
00029     double sqrt(doublereal), d_sign(doublereal *, doublereal *);
00030 
00031     /* Local variables */
00032     doublereal b, t, s1, s2, eps, tmp;
00033     extern doublereal ddot_(integer *, doublereal *, integer *, doublereal *, 
00034             integer *);
00035     doublereal sine, test, zeta1, zeta2, alpha, norma;
00036     extern doublereal dlamch_(char *);
00037     doublereal absgam, absalp, cosine, absest;
00038 
00039 
00040 /*  -- LAPACK auxiliary routine (version 3.2) -- */
00041 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00042 /*     November 2006 */
00043 
00044 /*     .. Scalar Arguments .. */
00045 /*     .. */
00046 /*     .. Array Arguments .. */
00047 /*     .. */
00048 
00049 /*  Purpose */
00050 /*  ======= */
00051 
00052 /*  DLAIC1 applies one step of incremental condition estimation in */
00053 /*  its simplest version: */
00054 
00055 /*  Let x, twonorm(x) = 1, be an approximate singular vector of an j-by-j */
00056 /*  lower triangular matrix L, such that */
00057 /*           twonorm(L*x) = sest */
00058 /*  Then DLAIC1 computes sestpr, s, c such that */
00059 /*  the vector */
00060 /*                  [ s*x ] */
00061 /*           xhat = [  c  ] */
00062 /*  is an approximate singular vector of */
00063 /*                  [ L     0  ] */
00064 /*           Lhat = [ w' gamma ] */
00065 /*  in the sense that */
00066 /*           twonorm(Lhat*xhat) = sestpr. */
00067 
00068 /*  Depending on JOB, an estimate for the largest or smallest singular */
00069 /*  value is computed. */
00070 
00071 /*  Note that [s c]' and sestpr**2 is an eigenpair of the system */
00072 
00073 /*      diag(sest*sest, 0) + [alpha  gamma] * [ alpha ] */
00074 /*                                            [ gamma ] */
00075 
00076 /*  where  alpha =  x'*w. */
00077 
00078 /*  Arguments */
00079 /*  ========= */
00080 
00081 /*  JOB     (input) INTEGER */
00082 /*          = 1: an estimate for the largest singular value is computed. */
00083 /*          = 2: an estimate for the smallest singular value is computed. */
00084 
00085 /*  J       (input) INTEGER */
00086 /*          Length of X and W */
00087 
00088 /*  X       (input) DOUBLE PRECISION array, dimension (J) */
00089 /*          The j-vector x. */
00090 
00091 /*  SEST    (input) DOUBLE PRECISION */
00092 /*          Estimated singular value of j by j matrix L */
00093 
00094 /*  W       (input) DOUBLE PRECISION array, dimension (J) */
00095 /*          The j-vector w. */
00096 
00097 /*  GAMMA   (input) DOUBLE PRECISION */
00098 /*          The diagonal element gamma. */
00099 
00100 /*  SESTPR  (output) DOUBLE PRECISION */
00101 /*          Estimated singular value of (j+1) by (j+1) matrix Lhat. */
00102 
00103 /*  S       (output) DOUBLE PRECISION */
00104 /*          Sine needed in forming xhat. */
00105 
00106 /*  C       (output) DOUBLE PRECISION */
00107 /*          Cosine needed in forming xhat. */
00108 
00109 /*  ===================================================================== */
00110 
00111 /*     .. Parameters .. */
00112 /*     .. */
00113 /*     .. Local Scalars .. */
00114 /*     .. */
00115 /*     .. Intrinsic Functions .. */
00116 /*     .. */
00117 /*     .. External Functions .. */
00118 /*     .. */
00119 /*     .. Executable Statements .. */
00120 
00121     /* Parameter adjustments */
00122     --w;
00123     --x;
00124 
00125     /* Function Body */
00126     eps = dlamch_("Epsilon");
00127     alpha = ddot_(j, &x[1], &c__1, &w[1], &c__1);
00128 
00129     absalp = abs(alpha);
00130     absgam = abs(*gamma);
00131     absest = abs(*sest);
00132 
00133     if (*job == 1) {
00134 
00135 /*        Estimating largest singular value */
00136 
00137 /*        special cases */
00138 
00139         if (*sest == 0.) {
00140             s1 = max(absgam,absalp);
00141             if (s1 == 0.) {
00142                 *s = 0.;
00143                 *c__ = 1.;
00144                 *sestpr = 0.;
00145             } else {
00146                 *s = alpha / s1;
00147                 *c__ = *gamma / s1;
00148                 tmp = sqrt(*s * *s + *c__ * *c__);
00149                 *s /= tmp;
00150                 *c__ /= tmp;
00151                 *sestpr = s1 * tmp;
00152             }
00153             return 0;
00154         } else if (absgam <= eps * absest) {
00155             *s = 1.;
00156             *c__ = 0.;
00157             tmp = max(absest,absalp);
00158             s1 = absest / tmp;
00159             s2 = absalp / tmp;
00160             *sestpr = tmp * sqrt(s1 * s1 + s2 * s2);
00161             return 0;
00162         } else if (absalp <= eps * absest) {
00163             s1 = absgam;
00164             s2 = absest;
00165             if (s1 <= s2) {
00166                 *s = 1.;
00167                 *c__ = 0.;
00168                 *sestpr = s2;
00169             } else {
00170                 *s = 0.;
00171                 *c__ = 1.;
00172                 *sestpr = s1;
00173             }
00174             return 0;
00175         } else if (absest <= eps * absalp || absest <= eps * absgam) {
00176             s1 = absgam;
00177             s2 = absalp;
00178             if (s1 <= s2) {
00179                 tmp = s1 / s2;
00180                 *s = sqrt(tmp * tmp + 1.);
00181                 *sestpr = s2 * *s;
00182                 *c__ = *gamma / s2 / *s;
00183                 *s = d_sign(&c_b5, &alpha) / *s;
00184             } else {
00185                 tmp = s2 / s1;
00186                 *c__ = sqrt(tmp * tmp + 1.);
00187                 *sestpr = s1 * *c__;
00188                 *s = alpha / s1 / *c__;
00189                 *c__ = d_sign(&c_b5, gamma) / *c__;
00190             }
00191             return 0;
00192         } else {
00193 
00194 /*           normal case */
00195 
00196             zeta1 = alpha / absest;
00197             zeta2 = *gamma / absest;
00198 
00199             b = (1. - zeta1 * zeta1 - zeta2 * zeta2) * .5;
00200             *c__ = zeta1 * zeta1;
00201             if (b > 0.) {
00202                 t = *c__ / (b + sqrt(b * b + *c__));
00203             } else {
00204                 t = sqrt(b * b + *c__) - b;
00205             }
00206 
00207             sine = -zeta1 / t;
00208             cosine = -zeta2 / (t + 1.);
00209             tmp = sqrt(sine * sine + cosine * cosine);
00210             *s = sine / tmp;
00211             *c__ = cosine / tmp;
00212             *sestpr = sqrt(t + 1.) * absest;
00213             return 0;
00214         }
00215 
00216     } else if (*job == 2) {
00217 
00218 /*        Estimating smallest singular value */
00219 
00220 /*        special cases */
00221 
00222         if (*sest == 0.) {
00223             *sestpr = 0.;
00224             if (max(absgam,absalp) == 0.) {
00225                 sine = 1.;
00226                 cosine = 0.;
00227             } else {
00228                 sine = -(*gamma);
00229                 cosine = alpha;
00230             }
00231 /* Computing MAX */
00232             d__1 = abs(sine), d__2 = abs(cosine);
00233             s1 = max(d__1,d__2);
00234             *s = sine / s1;
00235             *c__ = cosine / s1;
00236             tmp = sqrt(*s * *s + *c__ * *c__);
00237             *s /= tmp;
00238             *c__ /= tmp;
00239             return 0;
00240         } else if (absgam <= eps * absest) {
00241             *s = 0.;
00242             *c__ = 1.;
00243             *sestpr = absgam;
00244             return 0;
00245         } else if (absalp <= eps * absest) {
00246             s1 = absgam;
00247             s2 = absest;
00248             if (s1 <= s2) {
00249                 *s = 0.;
00250                 *c__ = 1.;
00251                 *sestpr = s1;
00252             } else {
00253                 *s = 1.;
00254                 *c__ = 0.;
00255                 *sestpr = s2;
00256             }
00257             return 0;
00258         } else if (absest <= eps * absalp || absest <= eps * absgam) {
00259             s1 = absgam;
00260             s2 = absalp;
00261             if (s1 <= s2) {
00262                 tmp = s1 / s2;
00263                 *c__ = sqrt(tmp * tmp + 1.);
00264                 *sestpr = absest * (tmp / *c__);
00265                 *s = -(*gamma / s2) / *c__;
00266                 *c__ = d_sign(&c_b5, &alpha) / *c__;
00267             } else {
00268                 tmp = s2 / s1;
00269                 *s = sqrt(tmp * tmp + 1.);
00270                 *sestpr = absest / *s;
00271                 *c__ = alpha / s1 / *s;
00272                 *s = -d_sign(&c_b5, gamma) / *s;
00273             }
00274             return 0;
00275         } else {
00276 
00277 /*           normal case */
00278 
00279             zeta1 = alpha / absest;
00280             zeta2 = *gamma / absest;
00281 
00282 /* Computing MAX */
00283             d__3 = zeta1 * zeta1 + 1. + (d__1 = zeta1 * zeta2, abs(d__1)), 
00284                     d__4 = (d__2 = zeta1 * zeta2, abs(d__2)) + zeta2 * zeta2;
00285             norma = max(d__3,d__4);
00286 
00287 /*           See if root is closer to zero or to ONE */
00288 
00289             test = (zeta1 - zeta2) * 2. * (zeta1 + zeta2) + 1.;
00290             if (test >= 0.) {
00291 
00292 /*              root is close to zero, compute directly */
00293 
00294                 b = (zeta1 * zeta1 + zeta2 * zeta2 + 1.) * .5;
00295                 *c__ = zeta2 * zeta2;
00296                 t = *c__ / (b + sqrt((d__1 = b * b - *c__, abs(d__1))));
00297                 sine = zeta1 / (1. - t);
00298                 cosine = -zeta2 / t;
00299                 *sestpr = sqrt(t + eps * 4. * eps * norma) * absest;
00300             } else {
00301 
00302 /*              root is closer to ONE, shift by that amount */
00303 
00304                 b = (zeta2 * zeta2 + zeta1 * zeta1 - 1.) * .5;
00305                 *c__ = zeta1 * zeta1;
00306                 if (b >= 0.) {
00307                     t = -(*c__) / (b + sqrt(b * b + *c__));
00308                 } else {
00309                     t = b - sqrt(b * b + *c__);
00310                 }
00311                 sine = -zeta1 / t;
00312                 cosine = -zeta2 / (t + 1.);
00313                 *sestpr = sqrt(t + 1. + eps * 4. * eps * norma) * absest;
00314             }
00315             tmp = sqrt(sine * sine + cosine * cosine);
00316             *s = sine / tmp;
00317             *c__ = cosine / tmp;
00318             return 0;
00319 
00320         }
00321     }
00322     return 0;
00323 
00324 /*     End of DLAIC1 */
00325 
00326 } /* dlaic1_ */


swiftnav
Author(s):
autogenerated on Sat Jun 8 2019 18:55:46