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


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