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


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