00001 /* dpftri.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 doublereal c_b11 = 1.; 00019 00020 /* Subroutine */ int dpftri_(char *transr, char *uplo, integer *n, doublereal 00021 *a, integer *info) 00022 { 00023 /* System generated locals */ 00024 integer i__1, i__2; 00025 00026 /* Local variables */ 00027 integer k, n1, n2; 00028 logical normaltransr; 00029 extern logical lsame_(char *, char *); 00030 extern /* Subroutine */ int dtrmm_(char *, char *, char *, char *, 00031 integer *, integer *, doublereal *, doublereal *, integer *, 00032 doublereal *, integer *); 00033 logical lower; 00034 extern /* Subroutine */ int dsyrk_(char *, char *, integer *, integer *, 00035 doublereal *, doublereal *, integer *, doublereal *, doublereal *, 00036 integer *), xerbla_(char *, integer *); 00037 logical nisodd; 00038 extern /* Subroutine */ int dlauum_(char *, integer *, doublereal *, 00039 integer *, integer *), dtftri_(char *, char *, char *, 00040 integer *, doublereal *, integer *); 00041 00042 00043 /* -- LAPACK routine (version 3.2) -- */ 00044 00045 /* -- Contributed by Fred Gustavson of the IBM Watson Research Center -- */ 00046 /* -- November 2008 -- */ 00047 00048 /* -- LAPACK is a software package provided by Univ. of Tennessee, -- */ 00049 /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */ 00050 00051 /* .. Scalar Arguments .. */ 00052 /* .. Array Arguments .. */ 00053 /* .. */ 00054 00055 /* Purpose */ 00056 /* ======= */ 00057 00058 /* DPFTRI computes the inverse of a (real) symmetric positive definite */ 00059 /* matrix A using the Cholesky factorization A = U**T*U or A = L*L**T */ 00060 /* computed by DPFTRF. */ 00061 00062 /* Arguments */ 00063 /* ========= */ 00064 00065 /* TRANSR (input) CHARACTER */ 00066 /* = 'N': The Normal TRANSR of RFP A is stored; */ 00067 /* = 'T': The Transpose TRANSR of RFP A is stored. */ 00068 00069 /* UPLO (input) CHARACTER */ 00070 /* = 'U': Upper triangle of A is stored; */ 00071 /* = 'L': Lower triangle of A is stored. */ 00072 00073 /* N (input) INTEGER */ 00074 /* The order of the matrix A. N >= 0. */ 00075 00076 /* A (input/output) DOUBLE PRECISION array, dimension ( N*(N+1)/2 ) */ 00077 /* On entry, the symmetric matrix A in RFP format. RFP format is */ 00078 /* described by TRANSR, UPLO, and N as follows: If TRANSR = 'N' */ 00079 /* then RFP A is (0:N,0:k-1) when N is even; k=N/2. RFP A is */ 00080 /* (0:N-1,0:k) when N is odd; k=N/2. IF TRANSR = 'T' then RFP is */ 00081 /* the transpose of RFP A as defined when */ 00082 /* TRANSR = 'N'. The contents of RFP A are defined by UPLO as */ 00083 /* follows: If UPLO = 'U' the RFP A contains the nt elements of */ 00084 /* upper packed A. If UPLO = 'L' the RFP A contains the elements */ 00085 /* of lower packed A. The LDA of RFP A is (N+1)/2 when TRANSR = */ 00086 /* 'T'. When TRANSR is 'N' the LDA is N+1 when N is even and N */ 00087 /* is odd. See the Note below for more details. */ 00088 00089 /* On exit, the symmetric inverse of the original matrix, in the */ 00090 /* same storage format. */ 00091 00092 /* INFO (output) INTEGER */ 00093 /* = 0: successful exit */ 00094 /* < 0: if INFO = -i, the i-th argument had an illegal value */ 00095 /* > 0: if INFO = i, the (i,i) element of the factor U or L is */ 00096 /* zero, and the inverse could not be computed. */ 00097 00098 /* Notes */ 00099 /* ===== */ 00100 00101 /* We first consider Rectangular Full Packed (RFP) Format when N is */ 00102 /* even. We give an example where N = 6. */ 00103 00104 /* AP is Upper AP is Lower */ 00105 00106 /* 00 01 02 03 04 05 00 */ 00107 /* 11 12 13 14 15 10 11 */ 00108 /* 22 23 24 25 20 21 22 */ 00109 /* 33 34 35 30 31 32 33 */ 00110 /* 44 45 40 41 42 43 44 */ 00111 /* 55 50 51 52 53 54 55 */ 00112 00113 00114 /* Let TRANSR = 'N'. RFP holds AP as follows: */ 00115 /* For UPLO = 'U' the upper trapezoid A(0:5,0:2) consists of the last */ 00116 /* three columns of AP upper. The lower triangle A(4:6,0:2) consists of */ 00117 /* the transpose of the first three columns of AP upper. */ 00118 /* For UPLO = 'L' the lower trapezoid A(1:6,0:2) consists of the first */ 00119 /* three columns of AP lower. The upper triangle A(0:2,0:2) consists of */ 00120 /* the transpose of the last three columns of AP lower. */ 00121 /* This covers the case N even and TRANSR = 'N'. */ 00122 00123 /* RFP A RFP A */ 00124 00125 /* 03 04 05 33 43 53 */ 00126 /* 13 14 15 00 44 54 */ 00127 /* 23 24 25 10 11 55 */ 00128 /* 33 34 35 20 21 22 */ 00129 /* 00 44 45 30 31 32 */ 00130 /* 01 11 55 40 41 42 */ 00131 /* 02 12 22 50 51 52 */ 00132 00133 /* Now let TRANSR = 'T'. RFP A in both UPLO cases is just the */ 00134 /* transpose of RFP A above. One therefore gets: */ 00135 00136 00137 /* RFP A RFP A */ 00138 00139 /* 03 13 23 33 00 01 02 33 00 10 20 30 40 50 */ 00140 /* 04 14 24 34 44 11 12 43 44 11 21 31 41 51 */ 00141 /* 05 15 25 35 45 55 22 53 54 55 22 32 42 52 */ 00142 00143 00144 /* We first consider Rectangular Full Packed (RFP) Format when N is */ 00145 /* odd. We give an example where N = 5. */ 00146 00147 /* AP is Upper AP is Lower */ 00148 00149 /* 00 01 02 03 04 00 */ 00150 /* 11 12 13 14 10 11 */ 00151 /* 22 23 24 20 21 22 */ 00152 /* 33 34 30 31 32 33 */ 00153 /* 44 40 41 42 43 44 */ 00154 00155 00156 /* Let TRANSR = 'N'. RFP holds AP as follows: */ 00157 /* For UPLO = 'U' the upper trapezoid A(0:4,0:2) consists of the last */ 00158 /* three columns of AP upper. The lower triangle A(3:4,0:1) consists of */ 00159 /* the transpose of the first two columns of AP upper. */ 00160 /* For UPLO = 'L' the lower trapezoid A(0:4,0:2) consists of the first */ 00161 /* three columns of AP lower. The upper triangle A(0:1,1:2) consists of */ 00162 /* the transpose of the last two columns of AP lower. */ 00163 /* This covers the case N odd and TRANSR = 'N'. */ 00164 00165 /* RFP A RFP A */ 00166 00167 /* 02 03 04 00 33 43 */ 00168 /* 12 13 14 10 11 44 */ 00169 /* 22 23 24 20 21 22 */ 00170 /* 00 33 34 30 31 32 */ 00171 /* 01 11 44 40 41 42 */ 00172 00173 /* Now let TRANSR = 'T'. RFP A in both UPLO cases is just the */ 00174 /* transpose of RFP A above. One therefore gets: */ 00175 00176 /* RFP A RFP A */ 00177 00178 /* 02 12 22 00 01 00 10 20 30 40 50 */ 00179 /* 03 13 23 33 11 33 11 21 31 41 51 */ 00180 /* 04 14 24 34 44 43 44 22 32 42 52 */ 00181 00182 /* ===================================================================== */ 00183 00184 /* .. Parameters .. */ 00185 /* .. */ 00186 /* .. Local Scalars .. */ 00187 /* .. */ 00188 /* .. External Functions .. */ 00189 /* .. */ 00190 /* .. External Subroutines .. */ 00191 /* .. */ 00192 /* .. Intrinsic Functions .. */ 00193 /* .. */ 00194 /* .. Executable Statements .. */ 00195 00196 /* Test the input parameters. */ 00197 00198 *info = 0; 00199 normaltransr = lsame_(transr, "N"); 00200 lower = lsame_(uplo, "L"); 00201 if (! normaltransr && ! lsame_(transr, "T")) { 00202 *info = -1; 00203 } else if (! lower && ! lsame_(uplo, "U")) { 00204 *info = -2; 00205 } else if (*n < 0) { 00206 *info = -3; 00207 } 00208 if (*info != 0) { 00209 i__1 = -(*info); 00210 xerbla_("DPFTRI", &i__1); 00211 return 0; 00212 } 00213 00214 /* Quick return if possible */ 00215 00216 if (*n == 0) { 00217 return 0; 00218 } 00219 00220 /* Invert the triangular Cholesky factor U or L. */ 00221 00222 dtftri_(transr, uplo, "N", n, a, info); 00223 if (*info > 0) { 00224 return 0; 00225 } 00226 00227 /* If N is odd, set NISODD = .TRUE. */ 00228 /* If N is even, set K = N/2 and NISODD = .FALSE. */ 00229 00230 if (*n % 2 == 0) { 00231 k = *n / 2; 00232 nisodd = FALSE_; 00233 } else { 00234 nisodd = TRUE_; 00235 } 00236 00237 /* Set N1 and N2 depending on LOWER */ 00238 00239 if (lower) { 00240 n2 = *n / 2; 00241 n1 = *n - n2; 00242 } else { 00243 n1 = *n / 2; 00244 n2 = *n - n1; 00245 } 00246 00247 /* Start execution of triangular matrix multiply: inv(U)*inv(U)^C or */ 00248 /* inv(L)^C*inv(L). There are eight cases. */ 00249 00250 if (nisodd) { 00251 00252 /* N is odd */ 00253 00254 if (normaltransr) { 00255 00256 /* N is odd and TRANSR = 'N' */ 00257 00258 if (lower) { 00259 00260 /* SRPA for LOWER, NORMAL and N is odd ( a(0:n-1,0:N1-1) ) */ 00261 /* T1 -> a(0,0), T2 -> a(0,1), S -> a(N1,0) */ 00262 /* T1 -> a(0), T2 -> a(n), S -> a(N1) */ 00263 00264 dlauum_("L", &n1, a, n, info); 00265 dsyrk_("L", "T", &n1, &n2, &c_b11, &a[n1], n, &c_b11, a, n); 00266 dtrmm_("L", "U", "N", "N", &n2, &n1, &c_b11, &a[*n], n, &a[n1] 00267 , n); 00268 dlauum_("U", &n2, &a[*n], n, info); 00269 00270 } else { 00271 00272 /* SRPA for UPPER, NORMAL and N is odd ( a(0:n-1,0:N2-1) */ 00273 /* T1 -> a(N1+1,0), T2 -> a(N1,0), S -> a(0,0) */ 00274 /* T1 -> a(N2), T2 -> a(N1), S -> a(0) */ 00275 00276 dlauum_("L", &n1, &a[n2], n, info); 00277 dsyrk_("L", "N", &n1, &n2, &c_b11, a, n, &c_b11, &a[n2], n); 00278 dtrmm_("R", "U", "T", "N", &n1, &n2, &c_b11, &a[n1], n, a, n); 00279 dlauum_("U", &n2, &a[n1], n, info); 00280 00281 } 00282 00283 } else { 00284 00285 /* N is odd and TRANSR = 'T' */ 00286 00287 if (lower) { 00288 00289 /* SRPA for LOWER, TRANSPOSE, and N is odd */ 00290 /* T1 -> a(0), T2 -> a(1), S -> a(0+N1*N1) */ 00291 00292 dlauum_("U", &n1, a, &n1, info); 00293 dsyrk_("U", "N", &n1, &n2, &c_b11, &a[n1 * n1], &n1, &c_b11, 00294 a, &n1); 00295 dtrmm_("R", "L", "N", "N", &n1, &n2, &c_b11, &a[1], &n1, &a[ 00296 n1 * n1], &n1); 00297 dlauum_("L", &n2, &a[1], &n1, info); 00298 00299 } else { 00300 00301 /* SRPA for UPPER, TRANSPOSE, and N is odd */ 00302 /* T1 -> a(0+N2*N2), T2 -> a(0+N1*N2), S -> a(0) */ 00303 00304 dlauum_("U", &n1, &a[n2 * n2], &n2, info); 00305 dsyrk_("U", "T", &n1, &n2, &c_b11, a, &n2, &c_b11, &a[n2 * n2] 00306 , &n2); 00307 dtrmm_("L", "L", "T", "N", &n2, &n1, &c_b11, &a[n1 * n2], &n2, 00308 a, &n2); 00309 dlauum_("L", &n2, &a[n1 * n2], &n2, info); 00310 00311 } 00312 00313 } 00314 00315 } else { 00316 00317 /* N is even */ 00318 00319 if (normaltransr) { 00320 00321 /* N is even and TRANSR = 'N' */ 00322 00323 if (lower) { 00324 00325 /* SRPA for LOWER, NORMAL, and N is even ( a(0:n,0:k-1) ) */ 00326 /* T1 -> a(1,0), T2 -> a(0,0), S -> a(k+1,0) */ 00327 /* T1 -> a(1), T2 -> a(0), S -> a(k+1) */ 00328 00329 i__1 = *n + 1; 00330 dlauum_("L", &k, &a[1], &i__1, info); 00331 i__1 = *n + 1; 00332 i__2 = *n + 1; 00333 dsyrk_("L", "T", &k, &k, &c_b11, &a[k + 1], &i__1, &c_b11, &a[ 00334 1], &i__2); 00335 i__1 = *n + 1; 00336 i__2 = *n + 1; 00337 dtrmm_("L", "U", "N", "N", &k, &k, &c_b11, a, &i__1, &a[k + 1] 00338 , &i__2); 00339 i__1 = *n + 1; 00340 dlauum_("U", &k, a, &i__1, info); 00341 00342 } else { 00343 00344 /* SRPA for UPPER, NORMAL, and N is even ( a(0:n,0:k-1) ) */ 00345 /* T1 -> a(k+1,0) , T2 -> a(k,0), S -> a(0,0) */ 00346 /* T1 -> a(k+1), T2 -> a(k), S -> a(0) */ 00347 00348 i__1 = *n + 1; 00349 dlauum_("L", &k, &a[k + 1], &i__1, info); 00350 i__1 = *n + 1; 00351 i__2 = *n + 1; 00352 dsyrk_("L", "N", &k, &k, &c_b11, a, &i__1, &c_b11, &a[k + 1], 00353 &i__2); 00354 i__1 = *n + 1; 00355 i__2 = *n + 1; 00356 dtrmm_("R", "U", "T", "N", &k, &k, &c_b11, &a[k], &i__1, a, & 00357 i__2); 00358 i__1 = *n + 1; 00359 dlauum_("U", &k, &a[k], &i__1, info); 00360 00361 } 00362 00363 } else { 00364 00365 /* N is even and TRANSR = 'T' */ 00366 00367 if (lower) { 00368 00369 /* SRPA for LOWER, TRANSPOSE, and N is even (see paper) */ 00370 /* T1 -> B(0,1), T2 -> B(0,0), S -> B(0,k+1), */ 00371 /* T1 -> a(0+k), T2 -> a(0+0), S -> a(0+k*(k+1)); lda=k */ 00372 00373 dlauum_("U", &k, &a[k], &k, info); 00374 dsyrk_("U", "N", &k, &k, &c_b11, &a[k * (k + 1)], &k, &c_b11, 00375 &a[k], &k); 00376 dtrmm_("R", "L", "N", "N", &k, &k, &c_b11, a, &k, &a[k * (k + 00377 1)], &k); 00378 dlauum_("L", &k, a, &k, info); 00379 00380 } else { 00381 00382 /* SRPA for UPPER, TRANSPOSE, and N is even (see paper) */ 00383 /* T1 -> B(0,k+1), T2 -> B(0,k), S -> B(0,0), */ 00384 /* T1 -> a(0+k*(k+1)), T2 -> a(0+k*k), S -> a(0+0)); lda=k */ 00385 00386 dlauum_("U", &k, &a[k * (k + 1)], &k, info); 00387 dsyrk_("U", "T", &k, &k, &c_b11, a, &k, &c_b11, &a[k * (k + 1) 00388 ], &k); 00389 dtrmm_("L", "L", "T", "N", &k, &k, &c_b11, &a[k * k], &k, a, & 00390 k); 00391 dlauum_("L", &k, &a[k * k], &k, info); 00392 00393 } 00394 00395 } 00396 00397 } 00398 00399 return 0; 00400 00401 /* End of DPFTRI */ 00402 00403 } /* dpftri_ */