dsptri.c
Go to the documentation of this file.
00001 /* dsptri.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_b11 = -1.;
00020 static doublereal c_b13 = 0.;
00021 
00022 /* Subroutine */ int dsptri_(char *uplo, integer *n, doublereal *ap, integer *
00023         ipiv, doublereal *work, integer *info)
00024 {
00025     /* System generated locals */
00026     integer i__1;
00027     doublereal d__1;
00028 
00029     /* Local variables */
00030     doublereal d__;
00031     integer j, k;
00032     doublereal t, ak;
00033     integer kc, kp, kx, kpc, npp;
00034     doublereal akp1;
00035     extern doublereal ddot_(integer *, doublereal *, integer *, doublereal *, 
00036             integer *);
00037     doublereal temp, akkp1;
00038     extern logical lsame_(char *, char *);
00039     extern /* Subroutine */ int dcopy_(integer *, doublereal *, integer *, 
00040             doublereal *, integer *), dswap_(integer *, doublereal *, integer 
00041             *, doublereal *, integer *);
00042     integer kstep;
00043     extern /* Subroutine */ int dspmv_(char *, integer *, doublereal *, 
00044             doublereal *, doublereal *, integer *, doublereal *, doublereal *, 
00045              integer *);
00046     logical upper;
00047     extern /* Subroutine */ int xerbla_(char *, integer *);
00048     integer kcnext;
00049 
00050 
00051 /*  -- LAPACK routine (version 3.2) -- */
00052 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00053 /*     November 2006 */
00054 
00055 /*     .. Scalar Arguments .. */
00056 /*     .. */
00057 /*     .. Array Arguments .. */
00058 /*     .. */
00059 
00060 /*  Purpose */
00061 /*  ======= */
00062 
00063 /*  DSPTRI computes the inverse of a real symmetric indefinite matrix */
00064 /*  A in packed storage using the factorization A = U*D*U**T or */
00065 /*  A = L*D*L**T computed by DSPTRF. */
00066 
00067 /*  Arguments */
00068 /*  ========= */
00069 
00070 /*  UPLO    (input) CHARACTER*1 */
00071 /*          Specifies whether the details of the factorization are stored */
00072 /*          as an upper or lower triangular matrix. */
00073 /*          = 'U':  Upper triangular, form is A = U*D*U**T; */
00074 /*          = 'L':  Lower triangular, form is A = L*D*L**T. */
00075 
00076 /*  N       (input) INTEGER */
00077 /*          The order of the matrix A.  N >= 0. */
00078 
00079 /*  AP      (input/output) DOUBLE PRECISION array, dimension (N*(N+1)/2) */
00080 /*          On entry, the block diagonal matrix D and the multipliers */
00081 /*          used to obtain the factor U or L as computed by DSPTRF, */
00082 /*          stored as a packed triangular matrix. */
00083 
00084 /*          On exit, if INFO = 0, the (symmetric) inverse of the original */
00085 /*          matrix, stored as a packed triangular matrix. The j-th column */
00086 /*          of inv(A) is stored in the array AP as follows: */
00087 /*          if UPLO = 'U', AP(i + (j-1)*j/2) = inv(A)(i,j) for 1<=i<=j; */
00088 /*          if UPLO = 'L', */
00089 /*             AP(i + (j-1)*(2n-j)/2) = inv(A)(i,j) for j<=i<=n. */
00090 
00091 /*  IPIV    (input) INTEGER array, dimension (N) */
00092 /*          Details of the interchanges and the block structure of D */
00093 /*          as determined by DSPTRF. */
00094 
00095 /*  WORK    (workspace) DOUBLE PRECISION array, dimension (N) */
00096 
00097 /*  INFO    (output) INTEGER */
00098 /*          = 0: successful exit */
00099 /*          < 0: if INFO = -i, the i-th argument had an illegal value */
00100 /*          > 0: if INFO = i, D(i,i) = 0; the matrix is singular and its */
00101 /*               inverse could not be computed. */
00102 
00103 /*  ===================================================================== */
00104 
00105 /*     .. Parameters .. */
00106 /*     .. */
00107 /*     .. Local Scalars .. */
00108 /*     .. */
00109 /*     .. External Functions .. */
00110 /*     .. */
00111 /*     .. External Subroutines .. */
00112 /*     .. */
00113 /*     .. Intrinsic Functions .. */
00114 /*     .. */
00115 /*     .. Executable Statements .. */
00116 
00117 /*     Test the input parameters. */
00118 
00119     /* Parameter adjustments */
00120     --work;
00121     --ipiv;
00122     --ap;
00123 
00124     /* Function Body */
00125     *info = 0;
00126     upper = lsame_(uplo, "U");
00127     if (! upper && ! lsame_(uplo, "L")) {
00128         *info = -1;
00129     } else if (*n < 0) {
00130         *info = -2;
00131     }
00132     if (*info != 0) {
00133         i__1 = -(*info);
00134         xerbla_("DSPTRI", &i__1);
00135         return 0;
00136     }
00137 
00138 /*     Quick return if possible */
00139 
00140     if (*n == 0) {
00141         return 0;
00142     }
00143 
00144 /*     Check that the diagonal matrix D is nonsingular. */
00145 
00146     if (upper) {
00147 
00148 /*        Upper triangular storage: examine D from bottom to top */
00149 
00150         kp = *n * (*n + 1) / 2;
00151         for (*info = *n; *info >= 1; --(*info)) {
00152             if (ipiv[*info] > 0 && ap[kp] == 0.) {
00153                 return 0;
00154             }
00155             kp -= *info;
00156 /* L10: */
00157         }
00158     } else {
00159 
00160 /*        Lower triangular storage: examine D from top to bottom. */
00161 
00162         kp = 1;
00163         i__1 = *n;
00164         for (*info = 1; *info <= i__1; ++(*info)) {
00165             if (ipiv[*info] > 0 && ap[kp] == 0.) {
00166                 return 0;
00167             }
00168             kp = kp + *n - *info + 1;
00169 /* L20: */
00170         }
00171     }
00172     *info = 0;
00173 
00174     if (upper) {
00175 
00176 /*        Compute inv(A) from the factorization A = U*D*U'. */
00177 
00178 /*        K is the main loop index, increasing from 1 to N in steps of */
00179 /*        1 or 2, depending on the size of the diagonal blocks. */
00180 
00181         k = 1;
00182         kc = 1;
00183 L30:
00184 
00185 /*        If K > N, exit from loop. */
00186 
00187         if (k > *n) {
00188             goto L50;
00189         }
00190 
00191         kcnext = kc + k;
00192         if (ipiv[k] > 0) {
00193 
00194 /*           1 x 1 diagonal block */
00195 
00196 /*           Invert the diagonal block. */
00197 
00198             ap[kc + k - 1] = 1. / ap[kc + k - 1];
00199 
00200 /*           Compute column K of the inverse. */
00201 
00202             if (k > 1) {
00203                 i__1 = k - 1;
00204                 dcopy_(&i__1, &ap[kc], &c__1, &work[1], &c__1);
00205                 i__1 = k - 1;
00206                 dspmv_(uplo, &i__1, &c_b11, &ap[1], &work[1], &c__1, &c_b13, &
00207                         ap[kc], &c__1);
00208                 i__1 = k - 1;
00209                 ap[kc + k - 1] -= ddot_(&i__1, &work[1], &c__1, &ap[kc], &
00210                         c__1);
00211             }
00212             kstep = 1;
00213         } else {
00214 
00215 /*           2 x 2 diagonal block */
00216 
00217 /*           Invert the diagonal block. */
00218 
00219             t = (d__1 = ap[kcnext + k - 1], abs(d__1));
00220             ak = ap[kc + k - 1] / t;
00221             akp1 = ap[kcnext + k] / t;
00222             akkp1 = ap[kcnext + k - 1] / t;
00223             d__ = t * (ak * akp1 - 1.);
00224             ap[kc + k - 1] = akp1 / d__;
00225             ap[kcnext + k] = ak / d__;
00226             ap[kcnext + k - 1] = -akkp1 / d__;
00227 
00228 /*           Compute columns K and K+1 of the inverse. */
00229 
00230             if (k > 1) {
00231                 i__1 = k - 1;
00232                 dcopy_(&i__1, &ap[kc], &c__1, &work[1], &c__1);
00233                 i__1 = k - 1;
00234                 dspmv_(uplo, &i__1, &c_b11, &ap[1], &work[1], &c__1, &c_b13, &
00235                         ap[kc], &c__1);
00236                 i__1 = k - 1;
00237                 ap[kc + k - 1] -= ddot_(&i__1, &work[1], &c__1, &ap[kc], &
00238                         c__1);
00239                 i__1 = k - 1;
00240                 ap[kcnext + k - 1] -= ddot_(&i__1, &ap[kc], &c__1, &ap[kcnext]
00241 , &c__1);
00242                 i__1 = k - 1;
00243                 dcopy_(&i__1, &ap[kcnext], &c__1, &work[1], &c__1);
00244                 i__1 = k - 1;
00245                 dspmv_(uplo, &i__1, &c_b11, &ap[1], &work[1], &c__1, &c_b13, &
00246                         ap[kcnext], &c__1);
00247                 i__1 = k - 1;
00248                 ap[kcnext + k] -= ddot_(&i__1, &work[1], &c__1, &ap[kcnext], &
00249                         c__1);
00250             }
00251             kstep = 2;
00252             kcnext = kcnext + k + 1;
00253         }
00254 
00255         kp = (i__1 = ipiv[k], abs(i__1));
00256         if (kp != k) {
00257 
00258 /*           Interchange rows and columns K and KP in the leading */
00259 /*           submatrix A(1:k+1,1:k+1) */
00260 
00261             kpc = (kp - 1) * kp / 2 + 1;
00262             i__1 = kp - 1;
00263             dswap_(&i__1, &ap[kc], &c__1, &ap[kpc], &c__1);
00264             kx = kpc + kp - 1;
00265             i__1 = k - 1;
00266             for (j = kp + 1; j <= i__1; ++j) {
00267                 kx = kx + j - 1;
00268                 temp = ap[kc + j - 1];
00269                 ap[kc + j - 1] = ap[kx];
00270                 ap[kx] = temp;
00271 /* L40: */
00272             }
00273             temp = ap[kc + k - 1];
00274             ap[kc + k - 1] = ap[kpc + kp - 1];
00275             ap[kpc + kp - 1] = temp;
00276             if (kstep == 2) {
00277                 temp = ap[kc + k + k - 1];
00278                 ap[kc + k + k - 1] = ap[kc + k + kp - 1];
00279                 ap[kc + k + kp - 1] = temp;
00280             }
00281         }
00282 
00283         k += kstep;
00284         kc = kcnext;
00285         goto L30;
00286 L50:
00287 
00288         ;
00289     } else {
00290 
00291 /*        Compute inv(A) from the factorization A = L*D*L'. */
00292 
00293 /*        K is the main loop index, increasing from 1 to N in steps of */
00294 /*        1 or 2, depending on the size of the diagonal blocks. */
00295 
00296         npp = *n * (*n + 1) / 2;
00297         k = *n;
00298         kc = npp;
00299 L60:
00300 
00301 /*        If K < 1, exit from loop. */
00302 
00303         if (k < 1) {
00304             goto L80;
00305         }
00306 
00307         kcnext = kc - (*n - k + 2);
00308         if (ipiv[k] > 0) {
00309 
00310 /*           1 x 1 diagonal block */
00311 
00312 /*           Invert the diagonal block. */
00313 
00314             ap[kc] = 1. / ap[kc];
00315 
00316 /*           Compute column K of the inverse. */
00317 
00318             if (k < *n) {
00319                 i__1 = *n - k;
00320                 dcopy_(&i__1, &ap[kc + 1], &c__1, &work[1], &c__1);
00321                 i__1 = *n - k;
00322                 dspmv_(uplo, &i__1, &c_b11, &ap[kc + *n - k + 1], &work[1], &
00323                         c__1, &c_b13, &ap[kc + 1], &c__1);
00324                 i__1 = *n - k;
00325                 ap[kc] -= ddot_(&i__1, &work[1], &c__1, &ap[kc + 1], &c__1);
00326             }
00327             kstep = 1;
00328         } else {
00329 
00330 /*           2 x 2 diagonal block */
00331 
00332 /*           Invert the diagonal block. */
00333 
00334             t = (d__1 = ap[kcnext + 1], abs(d__1));
00335             ak = ap[kcnext] / t;
00336             akp1 = ap[kc] / t;
00337             akkp1 = ap[kcnext + 1] / t;
00338             d__ = t * (ak * akp1 - 1.);
00339             ap[kcnext] = akp1 / d__;
00340             ap[kc] = ak / d__;
00341             ap[kcnext + 1] = -akkp1 / d__;
00342 
00343 /*           Compute columns K-1 and K of the inverse. */
00344 
00345             if (k < *n) {
00346                 i__1 = *n - k;
00347                 dcopy_(&i__1, &ap[kc + 1], &c__1, &work[1], &c__1);
00348                 i__1 = *n - k;
00349                 dspmv_(uplo, &i__1, &c_b11, &ap[kc + (*n - k + 1)], &work[1], 
00350                         &c__1, &c_b13, &ap[kc + 1], &c__1);
00351                 i__1 = *n - k;
00352                 ap[kc] -= ddot_(&i__1, &work[1], &c__1, &ap[kc + 1], &c__1);
00353                 i__1 = *n - k;
00354                 ap[kcnext + 1] -= ddot_(&i__1, &ap[kc + 1], &c__1, &ap[kcnext 
00355                         + 2], &c__1);
00356                 i__1 = *n - k;
00357                 dcopy_(&i__1, &ap[kcnext + 2], &c__1, &work[1], &c__1);
00358                 i__1 = *n - k;
00359                 dspmv_(uplo, &i__1, &c_b11, &ap[kc + (*n - k + 1)], &work[1], 
00360                         &c__1, &c_b13, &ap[kcnext + 2], &c__1);
00361                 i__1 = *n - k;
00362                 ap[kcnext] -= ddot_(&i__1, &work[1], &c__1, &ap[kcnext + 2], &
00363                         c__1);
00364             }
00365             kstep = 2;
00366             kcnext -= *n - k + 3;
00367         }
00368 
00369         kp = (i__1 = ipiv[k], abs(i__1));
00370         if (kp != k) {
00371 
00372 /*           Interchange rows and columns K and KP in the trailing */
00373 /*           submatrix A(k-1:n,k-1:n) */
00374 
00375             kpc = npp - (*n - kp + 1) * (*n - kp + 2) / 2 + 1;
00376             if (kp < *n) {
00377                 i__1 = *n - kp;
00378                 dswap_(&i__1, &ap[kc + kp - k + 1], &c__1, &ap[kpc + 1], &
00379                         c__1);
00380             }
00381             kx = kc + kp - k;
00382             i__1 = kp - 1;
00383             for (j = k + 1; j <= i__1; ++j) {
00384                 kx = kx + *n - j + 1;
00385                 temp = ap[kc + j - k];
00386                 ap[kc + j - k] = ap[kx];
00387                 ap[kx] = temp;
00388 /* L70: */
00389             }
00390             temp = ap[kc];
00391             ap[kc] = ap[kpc];
00392             ap[kpc] = temp;
00393             if (kstep == 2) {
00394                 temp = ap[kc - *n + k - 1];
00395                 ap[kc - *n + k - 1] = ap[kc - *n + kp - 1];
00396                 ap[kc - *n + kp - 1] = temp;
00397             }
00398         }
00399 
00400         k -= kstep;
00401         kc = kcnext;
00402         goto L60;
00403 L80:
00404         ;
00405     }
00406 
00407     return 0;
00408 
00409 /*     End of DSPTRI */
00410 
00411 } /* dsptri_ */


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