zpstf2.c
Go to the documentation of this file.
00001 /* zpstf2.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 = {1.,0.};
00019 static integer c__1 = 1;
00020 
00021 /* Subroutine */ int zpstf2_(char *uplo, integer *n, doublecomplex *a, 
00022         integer *lda, integer *piv, integer *rank, doublereal *tol, 
00023         doublereal *work, integer *info)
00024 {
00025     /* System generated locals */
00026     integer a_dim1, a_offset, i__1, i__2, i__3;
00027     doublereal d__1;
00028     doublecomplex z__1, z__2;
00029 
00030     /* Builtin functions */
00031     void d_cnjg(doublecomplex *, doublecomplex *);
00032     double sqrt(doublereal);
00033 
00034     /* Local variables */
00035     integer i__, j, maxlocval;
00036     doublereal ajj;
00037     integer pvt;
00038     extern logical lsame_(char *, char *);
00039     doublereal dtemp;
00040     integer itemp;
00041     extern /* Subroutine */ int zgemv_(char *, integer *, integer *, 
00042             doublecomplex *, doublecomplex *, integer *, doublecomplex *, 
00043             integer *, doublecomplex *, doublecomplex *, integer *);
00044     doublereal dstop;
00045     logical upper;
00046     doublecomplex ztemp;
00047     extern /* Subroutine */ int zswap_(integer *, doublecomplex *, integer *, 
00048             doublecomplex *, integer *);
00049     extern doublereal dlamch_(char *);
00050     extern logical disnan_(doublereal *);
00051     extern /* Subroutine */ int xerbla_(char *, integer *), zdscal_(
00052             integer *, doublereal *, doublecomplex *, integer *), zlacgv_(
00053             integer *, doublecomplex *, integer *);
00054     extern integer dmaxloc_(doublereal *, integer *);
00055 
00056 
00057 /*  -- LAPACK PROTOTYPE routine (version 3.2) -- */
00058 /*     Craig Lucas, University of Manchester / NAG Ltd. */
00059 /*     October, 2008 */
00060 
00061 /*     .. Scalar Arguments .. */
00062 /*     .. */
00063 /*     .. Array Arguments .. */
00064 /*     .. */
00065 
00066 /*  Purpose */
00067 /*  ======= */
00068 
00069 /*  ZPSTF2 computes the Cholesky factorization with complete */
00070 /*  pivoting of a complex Hermitian positive semidefinite matrix A. */
00071 
00072 /*  The factorization has the form */
00073 /*     P' * A * P = U' * U ,  if UPLO = 'U', */
00074 /*     P' * A * P = L  * L',  if UPLO = 'L', */
00075 /*  where U is an upper triangular matrix and L is lower triangular, and */
00076 /*  P is stored as vector PIV. */
00077 
00078 /*  This algorithm does not attempt to check that A is positive */
00079 /*  semidefinite. This version of the algorithm calls level 2 BLAS. */
00080 
00081 /*  Arguments */
00082 /*  ========= */
00083 
00084 /*  UPLO    (input) CHARACTER*1 */
00085 /*          Specifies whether the upper or lower triangular part of the */
00086 /*          symmetric matrix A is stored. */
00087 /*          = 'U':  Upper triangular */
00088 /*          = 'L':  Lower triangular */
00089 
00090 /*  N       (input) INTEGER */
00091 /*          The order of the matrix A.  N >= 0. */
00092 
00093 /*  A       (input/output) COMPLEX*16 array, dimension (LDA,N) */
00094 /*          On entry, the symmetric matrix A.  If UPLO = 'U', the leading */
00095 /*          n by n upper triangular part of A contains the upper */
00096 /*          triangular part of the matrix A, and the strictly lower */
00097 /*          triangular part of A is not referenced.  If UPLO = 'L', the */
00098 /*          leading n by n lower triangular part of A contains the lower */
00099 /*          triangular part of the matrix A, and the strictly upper */
00100 /*          triangular part of A is not referenced. */
00101 
00102 /*          On exit, if INFO = 0, the factor U or L from the Cholesky */
00103 /*          factorization as above. */
00104 
00105 /*  PIV     (output) INTEGER array, dimension (N) */
00106 /*          PIV is such that the nonzero entries are P( PIV(K), K ) = 1. */
00107 
00108 /*  RANK    (output) INTEGER */
00109 /*          The rank of A given by the number of steps the algorithm */
00110 /*          completed. */
00111 
00112 /*  TOL     (input) DOUBLE PRECISION */
00113 /*          User defined tolerance. If TOL < 0, then N*U*MAX( A( K,K ) ) */
00114 /*          will be used. The algorithm terminates at the (K-1)st step */
00115 /*          if the pivot <= TOL. */
00116 
00117 /*  LDA     (input) INTEGER */
00118 /*          The leading dimension of the array A.  LDA >= max(1,N). */
00119 
00120 /*  WORK    DOUBLE PRECISION array, dimension (2*N) */
00121 /*          Work space. */
00122 
00123 /*  INFO    (output) INTEGER */
00124 /*          < 0: If INFO = -K, the K-th argument had an illegal value, */
00125 /*          = 0: algorithm completed successfully, and */
00126 /*          > 0: the matrix A is either rank deficient with computed rank */
00127 /*               as returned in RANK, or is indefinite.  See Section 7 of */
00128 /*               LAPACK Working Note #161 for further information. */
00129 
00130 /*  ===================================================================== */
00131 
00132 /*     .. Parameters .. */
00133 /*     .. */
00134 /*     .. Local Scalars .. */
00135 /*     .. */
00136 /*     .. External Functions .. */
00137 /*     .. */
00138 /*     .. External Subroutines .. */
00139 /*     .. */
00140 /*     .. Intrinsic Functions .. */
00141 /*     .. */
00142 /*     .. Executable Statements .. */
00143 
00144 /*     Test the input parameters */
00145 
00146     /* Parameter adjustments */
00147     --work;
00148     --piv;
00149     a_dim1 = *lda;
00150     a_offset = 1 + a_dim1;
00151     a -= a_offset;
00152 
00153     /* Function Body */
00154     *info = 0;
00155     upper = lsame_(uplo, "U");
00156     if (! upper && ! lsame_(uplo, "L")) {
00157         *info = -1;
00158     } else if (*n < 0) {
00159         *info = -2;
00160     } else if (*lda < max(1,*n)) {
00161         *info = -4;
00162     }
00163     if (*info != 0) {
00164         i__1 = -(*info);
00165         xerbla_("ZPSTF2", &i__1);
00166         return 0;
00167     }
00168 
00169 /*     Quick return if possible */
00170 
00171     if (*n == 0) {
00172         return 0;
00173     }
00174 
00175 /*     Initialize PIV */
00176 
00177     i__1 = *n;
00178     for (i__ = 1; i__ <= i__1; ++i__) {
00179         piv[i__] = i__;
00180 /* L100: */
00181     }
00182 
00183 /*     Compute stopping value */
00184 
00185     i__1 = *n;
00186     for (i__ = 1; i__ <= i__1; ++i__) {
00187         i__2 = i__ + i__ * a_dim1;
00188         work[i__] = a[i__2].r;
00189 /* L110: */
00190     }
00191     pvt = dmaxloc_(&work[1], n);
00192     i__1 = pvt + pvt * a_dim1;
00193     ajj = a[i__1].r;
00194     if (ajj == 0. || disnan_(&ajj)) {
00195         *rank = 0;
00196         *info = 1;
00197         goto L200;
00198     }
00199 
00200 /*     Compute stopping value if not supplied */
00201 
00202     if (*tol < 0.) {
00203         dstop = *n * dlamch_("Epsilon") * ajj;
00204     } else {
00205         dstop = *tol;
00206     }
00207 
00208 /*     Set first half of WORK to zero, holds dot products */
00209 
00210     i__1 = *n;
00211     for (i__ = 1; i__ <= i__1; ++i__) {
00212         work[i__] = 0.;
00213 /* L120: */
00214     }
00215 
00216     if (upper) {
00217 
00218 /*        Compute the Cholesky factorization P' * A * P = U' * U */
00219 
00220         i__1 = *n;
00221         for (j = 1; j <= i__1; ++j) {
00222 
00223 /*        Find pivot, test for exit, else swap rows and columns */
00224 /*        Update dot products, compute possible pivots which are */
00225 /*        stored in the second half of WORK */
00226 
00227             i__2 = *n;
00228             for (i__ = j; i__ <= i__2; ++i__) {
00229 
00230                 if (j > 1) {
00231                     d_cnjg(&z__2, &a[j - 1 + i__ * a_dim1]);
00232                     i__3 = j - 1 + i__ * a_dim1;
00233                     z__1.r = z__2.r * a[i__3].r - z__2.i * a[i__3].i, z__1.i =
00234                              z__2.r * a[i__3].i + z__2.i * a[i__3].r;
00235                     work[i__] += z__1.r;
00236                 }
00237                 i__3 = i__ + i__ * a_dim1;
00238                 work[*n + i__] = a[i__3].r - work[i__];
00239 
00240 /* L130: */
00241             }
00242 
00243             if (j > 1) {
00244                 maxlocval = (*n << 1) - (*n + j) + 1;
00245                 itemp = dmaxloc_(&work[*n + j], &maxlocval);
00246                 pvt = itemp + j - 1;
00247                 ajj = work[*n + pvt];
00248                 if (ajj <= dstop || disnan_(&ajj)) {
00249                     i__2 = j + j * a_dim1;
00250                     a[i__2].r = ajj, a[i__2].i = 0.;
00251                     goto L190;
00252                 }
00253             }
00254 
00255             if (j != pvt) {
00256 
00257 /*              Pivot OK, so can now swap pivot rows and columns */
00258 
00259                 i__2 = pvt + pvt * a_dim1;
00260                 i__3 = j + j * a_dim1;
00261                 a[i__2].r = a[i__3].r, a[i__2].i = a[i__3].i;
00262                 i__2 = j - 1;
00263                 zswap_(&i__2, &a[j * a_dim1 + 1], &c__1, &a[pvt * a_dim1 + 1], 
00264                          &c__1);
00265                 if (pvt < *n) {
00266                     i__2 = *n - pvt;
00267                     zswap_(&i__2, &a[j + (pvt + 1) * a_dim1], lda, &a[pvt + (
00268                             pvt + 1) * a_dim1], lda);
00269                 }
00270                 i__2 = pvt - 1;
00271                 for (i__ = j + 1; i__ <= i__2; ++i__) {
00272                     d_cnjg(&z__1, &a[j + i__ * a_dim1]);
00273                     ztemp.r = z__1.r, ztemp.i = z__1.i;
00274                     i__3 = j + i__ * a_dim1;
00275                     d_cnjg(&z__1, &a[i__ + pvt * a_dim1]);
00276                     a[i__3].r = z__1.r, a[i__3].i = z__1.i;
00277                     i__3 = i__ + pvt * a_dim1;
00278                     a[i__3].r = ztemp.r, a[i__3].i = ztemp.i;
00279 /* L140: */
00280                 }
00281                 i__2 = j + pvt * a_dim1;
00282                 d_cnjg(&z__1, &a[j + pvt * a_dim1]);
00283                 a[i__2].r = z__1.r, a[i__2].i = z__1.i;
00284 
00285 /*              Swap dot products and PIV */
00286 
00287                 dtemp = work[j];
00288                 work[j] = work[pvt];
00289                 work[pvt] = dtemp;
00290                 itemp = piv[pvt];
00291                 piv[pvt] = piv[j];
00292                 piv[j] = itemp;
00293             }
00294 
00295             ajj = sqrt(ajj);
00296             i__2 = j + j * a_dim1;
00297             a[i__2].r = ajj, a[i__2].i = 0.;
00298 
00299 /*           Compute elements J+1:N of row J */
00300 
00301             if (j < *n) {
00302                 i__2 = j - 1;
00303                 zlacgv_(&i__2, &a[j * a_dim1 + 1], &c__1);
00304                 i__2 = j - 1;
00305                 i__3 = *n - j;
00306                 z__1.r = -1., z__1.i = -0.;
00307                 zgemv_("Trans", &i__2, &i__3, &z__1, &a[(j + 1) * a_dim1 + 1], 
00308                          lda, &a[j * a_dim1 + 1], &c__1, &c_b1, &a[j + (j + 1)
00309                          * a_dim1], lda);
00310                 i__2 = j - 1;
00311                 zlacgv_(&i__2, &a[j * a_dim1 + 1], &c__1);
00312                 i__2 = *n - j;
00313                 d__1 = 1. / ajj;
00314                 zdscal_(&i__2, &d__1, &a[j + (j + 1) * a_dim1], lda);
00315             }
00316 
00317 /* L150: */
00318         }
00319 
00320     } else {
00321 
00322 /*        Compute the Cholesky factorization P' * A * P = L * L' */
00323 
00324         i__1 = *n;
00325         for (j = 1; j <= i__1; ++j) {
00326 
00327 /*        Find pivot, test for exit, else swap rows and columns */
00328 /*        Update dot products, compute possible pivots which are */
00329 /*        stored in the second half of WORK */
00330 
00331             i__2 = *n;
00332             for (i__ = j; i__ <= i__2; ++i__) {
00333 
00334                 if (j > 1) {
00335                     d_cnjg(&z__2, &a[i__ + (j - 1) * a_dim1]);
00336                     i__3 = i__ + (j - 1) * a_dim1;
00337                     z__1.r = z__2.r * a[i__3].r - z__2.i * a[i__3].i, z__1.i =
00338                              z__2.r * a[i__3].i + z__2.i * a[i__3].r;
00339                     work[i__] += z__1.r;
00340                 }
00341                 i__3 = i__ + i__ * a_dim1;
00342                 work[*n + i__] = a[i__3].r - work[i__];
00343 
00344 /* L160: */
00345             }
00346 
00347             if (j > 1) {
00348                 maxlocval = (*n << 1) - (*n + j) + 1;
00349                 itemp = dmaxloc_(&work[*n + j], &maxlocval);
00350                 pvt = itemp + j - 1;
00351                 ajj = work[*n + pvt];
00352                 if (ajj <= dstop || disnan_(&ajj)) {
00353                     i__2 = j + j * a_dim1;
00354                     a[i__2].r = ajj, a[i__2].i = 0.;
00355                     goto L190;
00356                 }
00357             }
00358 
00359             if (j != pvt) {
00360 
00361 /*              Pivot OK, so can now swap pivot rows and columns */
00362 
00363                 i__2 = pvt + pvt * a_dim1;
00364                 i__3 = j + j * a_dim1;
00365                 a[i__2].r = a[i__3].r, a[i__2].i = a[i__3].i;
00366                 i__2 = j - 1;
00367                 zswap_(&i__2, &a[j + a_dim1], lda, &a[pvt + a_dim1], lda);
00368                 if (pvt < *n) {
00369                     i__2 = *n - pvt;
00370                     zswap_(&i__2, &a[pvt + 1 + j * a_dim1], &c__1, &a[pvt + 1 
00371                             + pvt * a_dim1], &c__1);
00372                 }
00373                 i__2 = pvt - 1;
00374                 for (i__ = j + 1; i__ <= i__2; ++i__) {
00375                     d_cnjg(&z__1, &a[i__ + j * a_dim1]);
00376                     ztemp.r = z__1.r, ztemp.i = z__1.i;
00377                     i__3 = i__ + j * a_dim1;
00378                     d_cnjg(&z__1, &a[pvt + i__ * a_dim1]);
00379                     a[i__3].r = z__1.r, a[i__3].i = z__1.i;
00380                     i__3 = pvt + i__ * a_dim1;
00381                     a[i__3].r = ztemp.r, a[i__3].i = ztemp.i;
00382 /* L170: */
00383                 }
00384                 i__2 = pvt + j * a_dim1;
00385                 d_cnjg(&z__1, &a[pvt + j * a_dim1]);
00386                 a[i__2].r = z__1.r, a[i__2].i = z__1.i;
00387 
00388 /*              Swap dot products and PIV */
00389 
00390                 dtemp = work[j];
00391                 work[j] = work[pvt];
00392                 work[pvt] = dtemp;
00393                 itemp = piv[pvt];
00394                 piv[pvt] = piv[j];
00395                 piv[j] = itemp;
00396             }
00397 
00398             ajj = sqrt(ajj);
00399             i__2 = j + j * a_dim1;
00400             a[i__2].r = ajj, a[i__2].i = 0.;
00401 
00402 /*           Compute elements J+1:N of column J */
00403 
00404             if (j < *n) {
00405                 i__2 = j - 1;
00406                 zlacgv_(&i__2, &a[j + a_dim1], lda);
00407                 i__2 = *n - j;
00408                 i__3 = j - 1;
00409                 z__1.r = -1., z__1.i = -0.;
00410                 zgemv_("No Trans", &i__2, &i__3, &z__1, &a[j + 1 + a_dim1], 
00411                         lda, &a[j + a_dim1], lda, &c_b1, &a[j + 1 + j * 
00412                         a_dim1], &c__1);
00413                 i__2 = j - 1;
00414                 zlacgv_(&i__2, &a[j + a_dim1], lda);
00415                 i__2 = *n - j;
00416                 d__1 = 1. / ajj;
00417                 zdscal_(&i__2, &d__1, &a[j + 1 + j * a_dim1], &c__1);
00418             }
00419 
00420 /* L180: */
00421         }
00422 
00423     }
00424 
00425 /*     Ran to completion, A has full rank */
00426 
00427     *rank = *n;
00428 
00429     goto L200;
00430 L190:
00431 
00432 /*     Rank is number of steps completed.  Set INFO = 1 to signal */
00433 /*     that the factorization cannot be used to solve a system. */
00434 
00435     *rank = j - 1;
00436     *info = 1;
00437 
00438 L200:
00439     return 0;
00440 
00441 /*     End of ZPSTF2 */
00442 
00443 } /* zpstf2_ */


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