zgelsx.c
Go to the documentation of this file.
00001 /* zgelsx.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 doublecomplex c_b1 = {0.,0.};
00019 static doublecomplex c_b2 = {1.,0.};
00020 static integer c__0 = 0;
00021 static integer c__2 = 2;
00022 static integer c__1 = 1;
00023 
00024 /* Subroutine */ int zgelsx_(integer *m, integer *n, integer *nrhs, 
00025         doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
00026         integer *jpvt, doublereal *rcond, integer *rank, doublecomplex *work, 
00027         doublereal *rwork, integer *info)
00028 {
00029     /* System generated locals */
00030     integer a_dim1, a_offset, b_dim1, b_offset, i__1, i__2, i__3;
00031     doublecomplex z__1;
00032 
00033     /* Builtin functions */
00034     double z_abs(doublecomplex *);
00035     void d_cnjg(doublecomplex *, doublecomplex *);
00036 
00037     /* Local variables */
00038     integer i__, j, k;
00039     doublecomplex c1, c2, s1, s2, t1, t2;
00040     integer mn;
00041     doublereal anrm, bnrm, smin, smax;
00042     integer iascl, ibscl, ismin, ismax;
00043     extern /* Subroutine */ int ztrsm_(char *, char *, char *, char *, 
00044             integer *, integer *, doublecomplex *, doublecomplex *, integer *, 
00045              doublecomplex *, integer *), 
00046             zlaic1_(integer *, integer *, doublecomplex *, doublereal *, 
00047             doublecomplex *, doublecomplex *, doublereal *, doublecomplex *, 
00048             doublecomplex *), dlabad_(doublereal *, doublereal *);
00049     extern doublereal dlamch_(char *);
00050     extern /* Subroutine */ int zunm2r_(char *, char *, integer *, integer *, 
00051             integer *, doublecomplex *, integer *, doublecomplex *, 
00052             doublecomplex *, integer *, doublecomplex *, integer *), xerbla_(char *, integer *);
00053     extern doublereal zlange_(char *, integer *, integer *, doublecomplex *, 
00054             integer *, doublereal *);
00055     doublereal bignum;
00056     extern /* Subroutine */ int zlascl_(char *, integer *, integer *, 
00057             doublereal *, doublereal *, integer *, integer *, doublecomplex *, 
00058              integer *, integer *), zgeqpf_(integer *, integer *, 
00059             doublecomplex *, integer *, integer *, doublecomplex *, 
00060             doublecomplex *, doublereal *, integer *), zlaset_(char *, 
00061             integer *, integer *, doublecomplex *, doublecomplex *, 
00062             doublecomplex *, integer *);
00063     doublereal sminpr, smaxpr, smlnum;
00064     extern /* Subroutine */ int zlatzm_(char *, integer *, integer *, 
00065             doublecomplex *, integer *, doublecomplex *, doublecomplex *, 
00066             doublecomplex *, integer *, doublecomplex *), ztzrqf_(
00067             integer *, integer *, doublecomplex *, integer *, doublecomplex *, 
00068              integer *);
00069 
00070 
00071 /*  -- LAPACK driver routine (version 3.2) -- */
00072 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00073 /*     November 2006 */
00074 
00075 /*     .. Scalar Arguments .. */
00076 /*     .. */
00077 /*     .. Array Arguments .. */
00078 /*     .. */
00079 
00080 /*  Purpose */
00081 /*  ======= */
00082 
00083 /*  This routine is deprecated and has been replaced by routine ZGELSY. */
00084 
00085 /*  ZGELSX computes the minimum-norm solution to a complex linear least */
00086 /*  squares problem: */
00087 /*      minimize || A * X - B || */
00088 /*  using a complete orthogonal factorization of A.  A is an M-by-N */
00089 /*  matrix which may be rank-deficient. */
00090 
00091 /*  Several right hand side vectors b and solution vectors x can be */
00092 /*  handled in a single call; they are stored as the columns of the */
00093 /*  M-by-NRHS right hand side matrix B and the N-by-NRHS solution */
00094 /*  matrix X. */
00095 
00096 /*  The routine first computes a QR factorization with column pivoting: */
00097 /*      A * P = Q * [ R11 R12 ] */
00098 /*                  [  0  R22 ] */
00099 /*  with R11 defined as the largest leading submatrix whose estimated */
00100 /*  condition number is less than 1/RCOND.  The order of R11, RANK, */
00101 /*  is the effective rank of A. */
00102 
00103 /*  Then, R22 is considered to be negligible, and R12 is annihilated */
00104 /*  by unitary transformations from the right, arriving at the */
00105 /*  complete orthogonal factorization: */
00106 /*     A * P = Q * [ T11 0 ] * Z */
00107 /*                 [  0  0 ] */
00108 /*  The minimum-norm solution is then */
00109 /*     X = P * Z' [ inv(T11)*Q1'*B ] */
00110 /*                [        0       ] */
00111 /*  where Q1 consists of the first RANK columns of Q. */
00112 
00113 /*  Arguments */
00114 /*  ========= */
00115 
00116 /*  M       (input) INTEGER */
00117 /*          The number of rows of the matrix A.  M >= 0. */
00118 
00119 /*  N       (input) INTEGER */
00120 /*          The number of columns of the matrix A.  N >= 0. */
00121 
00122 /*  NRHS    (input) INTEGER */
00123 /*          The number of right hand sides, i.e., the number of */
00124 /*          columns of matrices B and X. NRHS >= 0. */
00125 
00126 /*  A       (input/output) COMPLEX*16 array, dimension (LDA,N) */
00127 /*          On entry, the M-by-N matrix A. */
00128 /*          On exit, A has been overwritten by details of its */
00129 /*          complete orthogonal factorization. */
00130 
00131 /*  LDA     (input) INTEGER */
00132 /*          The leading dimension of the array A.  LDA >= max(1,M). */
00133 
00134 /*  B       (input/output) COMPLEX*16 array, dimension (LDB,NRHS) */
00135 /*          On entry, the M-by-NRHS right hand side matrix B. */
00136 /*          On exit, the N-by-NRHS solution matrix X. */
00137 /*          If m >= n and RANK = n, the residual sum-of-squares for */
00138 /*          the solution in the i-th column is given by the sum of */
00139 /*          squares of elements N+1:M in that column. */
00140 
00141 /*  LDB     (input) INTEGER */
00142 /*          The leading dimension of the array B. LDB >= max(1,M,N). */
00143 
00144 /*  JPVT    (input/output) INTEGER array, dimension (N) */
00145 /*          On entry, if JPVT(i) .ne. 0, the i-th column of A is an */
00146 /*          initial column, otherwise it is a free column.  Before */
00147 /*          the QR factorization of A, all initial columns are */
00148 /*          permuted to the leading positions; only the remaining */
00149 /*          free columns are moved as a result of column pivoting */
00150 /*          during the factorization. */
00151 /*          On exit, if JPVT(i) = k, then the i-th column of A*P */
00152 /*          was the k-th column of A. */
00153 
00154 /*  RCOND   (input) DOUBLE PRECISION */
00155 /*          RCOND is used to determine the effective rank of A, which */
00156 /*          is defined as the order of the largest leading triangular */
00157 /*          submatrix R11 in the QR factorization with pivoting of A, */
00158 /*          whose estimated condition number < 1/RCOND. */
00159 
00160 /*  RANK    (output) INTEGER */
00161 /*          The effective rank of A, i.e., the order of the submatrix */
00162 /*          R11.  This is the same as the order of the submatrix T11 */
00163 /*          in the complete orthogonal factorization of A. */
00164 
00165 /*  WORK    (workspace) COMPLEX*16 array, dimension */
00166 /*                      (min(M,N) + max( N, 2*min(M,N)+NRHS )), */
00167 
00168 /*  RWORK   (workspace) DOUBLE PRECISION array, dimension (2*N) */
00169 
00170 /*  INFO    (output) INTEGER */
00171 /*          = 0:  successful exit */
00172 /*          < 0:  if INFO = -i, the i-th argument had an illegal value */
00173 
00174 /*  ===================================================================== */
00175 
00176 /*     .. Parameters .. */
00177 /*     .. */
00178 /*     .. Local Scalars .. */
00179 /*     .. */
00180 /*     .. External Subroutines .. */
00181 /*     .. */
00182 /*     .. External Functions .. */
00183 /*     .. */
00184 /*     .. Intrinsic Functions .. */
00185 /*     .. */
00186 /*     .. Executable Statements .. */
00187 
00188     /* Parameter adjustments */
00189     a_dim1 = *lda;
00190     a_offset = 1 + a_dim1;
00191     a -= a_offset;
00192     b_dim1 = *ldb;
00193     b_offset = 1 + b_dim1;
00194     b -= b_offset;
00195     --jpvt;
00196     --work;
00197     --rwork;
00198 
00199     /* Function Body */
00200     mn = min(*m,*n);
00201     ismin = mn + 1;
00202     ismax = (mn << 1) + 1;
00203 
00204 /*     Test the input arguments. */
00205 
00206     *info = 0;
00207     if (*m < 0) {
00208         *info = -1;
00209     } else if (*n < 0) {
00210         *info = -2;
00211     } else if (*nrhs < 0) {
00212         *info = -3;
00213     } else if (*lda < max(1,*m)) {
00214         *info = -5;
00215     } else /* if(complicated condition) */ {
00216 /* Computing MAX */
00217         i__1 = max(1,*m);
00218         if (*ldb < max(i__1,*n)) {
00219             *info = -7;
00220         }
00221     }
00222 
00223     if (*info != 0) {
00224         i__1 = -(*info);
00225         xerbla_("ZGELSX", &i__1);
00226         return 0;
00227     }
00228 
00229 /*     Quick return if possible */
00230 
00231 /* Computing MIN */
00232     i__1 = min(*m,*n);
00233     if (min(i__1,*nrhs) == 0) {
00234         *rank = 0;
00235         return 0;
00236     }
00237 
00238 /*     Get machine parameters */
00239 
00240     smlnum = dlamch_("S") / dlamch_("P");
00241     bignum = 1. / smlnum;
00242     dlabad_(&smlnum, &bignum);
00243 
00244 /*     Scale A, B if max elements outside range [SMLNUM,BIGNUM] */
00245 
00246     anrm = zlange_("M", m, n, &a[a_offset], lda, &rwork[1]);
00247     iascl = 0;
00248     if (anrm > 0. && anrm < smlnum) {
00249 
00250 /*        Scale matrix norm up to SMLNUM */
00251 
00252         zlascl_("G", &c__0, &c__0, &anrm, &smlnum, m, n, &a[a_offset], lda, 
00253                 info);
00254         iascl = 1;
00255     } else if (anrm > bignum) {
00256 
00257 /*        Scale matrix norm down to BIGNUM */
00258 
00259         zlascl_("G", &c__0, &c__0, &anrm, &bignum, m, n, &a[a_offset], lda, 
00260                 info);
00261         iascl = 2;
00262     } else if (anrm == 0.) {
00263 
00264 /*        Matrix all zero. Return zero solution. */
00265 
00266         i__1 = max(*m,*n);
00267         zlaset_("F", &i__1, nrhs, &c_b1, &c_b1, &b[b_offset], ldb);
00268         *rank = 0;
00269         goto L100;
00270     }
00271 
00272     bnrm = zlange_("M", m, nrhs, &b[b_offset], ldb, &rwork[1]);
00273     ibscl = 0;
00274     if (bnrm > 0. && bnrm < smlnum) {
00275 
00276 /*        Scale matrix norm up to SMLNUM */
00277 
00278         zlascl_("G", &c__0, &c__0, &bnrm, &smlnum, m, nrhs, &b[b_offset], ldb, 
00279                  info);
00280         ibscl = 1;
00281     } else if (bnrm > bignum) {
00282 
00283 /*        Scale matrix norm down to BIGNUM */
00284 
00285         zlascl_("G", &c__0, &c__0, &bnrm, &bignum, m, nrhs, &b[b_offset], ldb, 
00286                  info);
00287         ibscl = 2;
00288     }
00289 
00290 /*     Compute QR factorization with column pivoting of A: */
00291 /*        A * P = Q * R */
00292 
00293     zgeqpf_(m, n, &a[a_offset], lda, &jpvt[1], &work[1], &work[mn + 1], &
00294             rwork[1], info);
00295 
00296 /*     complex workspace MN+N. Real workspace 2*N. Details of Householder */
00297 /*     rotations stored in WORK(1:MN). */
00298 
00299 /*     Determine RANK using incremental condition estimation */
00300 
00301     i__1 = ismin;
00302     work[i__1].r = 1., work[i__1].i = 0.;
00303     i__1 = ismax;
00304     work[i__1].r = 1., work[i__1].i = 0.;
00305     smax = z_abs(&a[a_dim1 + 1]);
00306     smin = smax;
00307     if (z_abs(&a[a_dim1 + 1]) == 0.) {
00308         *rank = 0;
00309         i__1 = max(*m,*n);
00310         zlaset_("F", &i__1, nrhs, &c_b1, &c_b1, &b[b_offset], ldb);
00311         goto L100;
00312     } else {
00313         *rank = 1;
00314     }
00315 
00316 L10:
00317     if (*rank < mn) {
00318         i__ = *rank + 1;
00319         zlaic1_(&c__2, rank, &work[ismin], &smin, &a[i__ * a_dim1 + 1], &a[
00320                 i__ + i__ * a_dim1], &sminpr, &s1, &c1);
00321         zlaic1_(&c__1, rank, &work[ismax], &smax, &a[i__ * a_dim1 + 1], &a[
00322                 i__ + i__ * a_dim1], &smaxpr, &s2, &c2);
00323 
00324         if (smaxpr * *rcond <= sminpr) {
00325             i__1 = *rank;
00326             for (i__ = 1; i__ <= i__1; ++i__) {
00327                 i__2 = ismin + i__ - 1;
00328                 i__3 = ismin + i__ - 1;
00329                 z__1.r = s1.r * work[i__3].r - s1.i * work[i__3].i, z__1.i = 
00330                         s1.r * work[i__3].i + s1.i * work[i__3].r;
00331                 work[i__2].r = z__1.r, work[i__2].i = z__1.i;
00332                 i__2 = ismax + i__ - 1;
00333                 i__3 = ismax + i__ - 1;
00334                 z__1.r = s2.r * work[i__3].r - s2.i * work[i__3].i, z__1.i = 
00335                         s2.r * work[i__3].i + s2.i * work[i__3].r;
00336                 work[i__2].r = z__1.r, work[i__2].i = z__1.i;
00337 /* L20: */
00338             }
00339             i__1 = ismin + *rank;
00340             work[i__1].r = c1.r, work[i__1].i = c1.i;
00341             i__1 = ismax + *rank;
00342             work[i__1].r = c2.r, work[i__1].i = c2.i;
00343             smin = sminpr;
00344             smax = smaxpr;
00345             ++(*rank);
00346             goto L10;
00347         }
00348     }
00349 
00350 /*     Logically partition R = [ R11 R12 ] */
00351 /*                             [  0  R22 ] */
00352 /*     where R11 = R(1:RANK,1:RANK) */
00353 
00354 /*     [R11,R12] = [ T11, 0 ] * Y */
00355 
00356     if (*rank < *n) {
00357         ztzrqf_(rank, n, &a[a_offset], lda, &work[mn + 1], info);
00358     }
00359 
00360 /*     Details of Householder rotations stored in WORK(MN+1:2*MN) */
00361 
00362 /*     B(1:M,1:NRHS) := Q' * B(1:M,1:NRHS) */
00363 
00364     zunm2r_("Left", "Conjugate transpose", m, nrhs, &mn, &a[a_offset], lda, &
00365             work[1], &b[b_offset], ldb, &work[(mn << 1) + 1], info);
00366 
00367 /*     workspace NRHS */
00368 
00369 /*      B(1:RANK,1:NRHS) := inv(T11) * B(1:RANK,1:NRHS) */
00370 
00371     ztrsm_("Left", "Upper", "No transpose", "Non-unit", rank, nrhs, &c_b2, &a[
00372             a_offset], lda, &b[b_offset], ldb);
00373 
00374     i__1 = *n;
00375     for (i__ = *rank + 1; i__ <= i__1; ++i__) {
00376         i__2 = *nrhs;
00377         for (j = 1; j <= i__2; ++j) {
00378             i__3 = i__ + j * b_dim1;
00379             b[i__3].r = 0., b[i__3].i = 0.;
00380 /* L30: */
00381         }
00382 /* L40: */
00383     }
00384 
00385 /*     B(1:N,1:NRHS) := Y' * B(1:N,1:NRHS) */
00386 
00387     if (*rank < *n) {
00388         i__1 = *rank;
00389         for (i__ = 1; i__ <= i__1; ++i__) {
00390             i__2 = *n - *rank + 1;
00391             d_cnjg(&z__1, &work[mn + i__]);
00392             zlatzm_("Left", &i__2, nrhs, &a[i__ + (*rank + 1) * a_dim1], lda, 
00393                     &z__1, &b[i__ + b_dim1], &b[*rank + 1 + b_dim1], ldb, &
00394                     work[(mn << 1) + 1]);
00395 /* L50: */
00396         }
00397     }
00398 
00399 /*     workspace NRHS */
00400 
00401 /*     B(1:N,1:NRHS) := P * B(1:N,1:NRHS) */
00402 
00403     i__1 = *nrhs;
00404     for (j = 1; j <= i__1; ++j) {
00405         i__2 = *n;
00406         for (i__ = 1; i__ <= i__2; ++i__) {
00407             i__3 = (mn << 1) + i__;
00408             work[i__3].r = 1., work[i__3].i = 0.;
00409 /* L60: */
00410         }
00411         i__2 = *n;
00412         for (i__ = 1; i__ <= i__2; ++i__) {
00413             i__3 = (mn << 1) + i__;
00414             if (work[i__3].r == 1. && work[i__3].i == 0.) {
00415                 if (jpvt[i__] != i__) {
00416                     k = i__;
00417                     i__3 = k + j * b_dim1;
00418                     t1.r = b[i__3].r, t1.i = b[i__3].i;
00419                     i__3 = jpvt[k] + j * b_dim1;
00420                     t2.r = b[i__3].r, t2.i = b[i__3].i;
00421 L70:
00422                     i__3 = jpvt[k] + j * b_dim1;
00423                     b[i__3].r = t1.r, b[i__3].i = t1.i;
00424                     i__3 = (mn << 1) + k;
00425                     work[i__3].r = 0., work[i__3].i = 0.;
00426                     t1.r = t2.r, t1.i = t2.i;
00427                     k = jpvt[k];
00428                     i__3 = jpvt[k] + j * b_dim1;
00429                     t2.r = b[i__3].r, t2.i = b[i__3].i;
00430                     if (jpvt[k] != i__) {
00431                         goto L70;
00432                     }
00433                     i__3 = i__ + j * b_dim1;
00434                     b[i__3].r = t1.r, b[i__3].i = t1.i;
00435                     i__3 = (mn << 1) + k;
00436                     work[i__3].r = 0., work[i__3].i = 0.;
00437                 }
00438             }
00439 /* L80: */
00440         }
00441 /* L90: */
00442     }
00443 
00444 /*     Undo scaling */
00445 
00446     if (iascl == 1) {
00447         zlascl_("G", &c__0, &c__0, &anrm, &smlnum, n, nrhs, &b[b_offset], ldb, 
00448                  info);
00449         zlascl_("U", &c__0, &c__0, &smlnum, &anrm, rank, rank, &a[a_offset], 
00450                 lda, info);
00451     } else if (iascl == 2) {
00452         zlascl_("G", &c__0, &c__0, &anrm, &bignum, n, nrhs, &b[b_offset], ldb, 
00453                  info);
00454         zlascl_("U", &c__0, &c__0, &bignum, &anrm, rank, rank, &a[a_offset], 
00455                 lda, info);
00456     }
00457     if (ibscl == 1) {
00458         zlascl_("G", &c__0, &c__0, &smlnum, &bnrm, n, nrhs, &b[b_offset], ldb, 
00459                  info);
00460     } else if (ibscl == 2) {
00461         zlascl_("G", &c__0, &c__0, &bignum, &bnrm, n, nrhs, &b[b_offset], ldb, 
00462                  info);
00463     }
00464 
00465 L100:
00466 
00467     return 0;
00468 
00469 /*     End of ZGELSX */
00470 
00471 } /* zgelsx_ */


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