c@427
|
1 /* dgetri.f -- translated by f2c (version 20061008).
|
c@427
|
2 You must link the resulting object file with libf2c:
|
c@427
|
3 on Microsoft Windows system, link with libf2c.lib;
|
c@427
|
4 on Linux or Unix systems, link with .../path/to/libf2c.a -lm
|
c@427
|
5 or, if you install libf2c.a in a standard place, with -lf2c -lm
|
c@427
|
6 -- in that order, at the end of the command line, as in
|
c@427
|
7 cc *.o -lf2c -lm
|
c@427
|
8 Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,
|
c@427
|
9
|
c@427
|
10 http://www.netlib.org/f2c/libf2c.zip
|
c@427
|
11 */
|
c@427
|
12
|
c@427
|
13 #include "f2c.h"
|
c@427
|
14 #include "blaswrap.h"
|
c@427
|
15
|
c@427
|
16 /* Table of constant values */
|
c@427
|
17
|
c@427
|
18 static integer c__1 = 1;
|
c@427
|
19 static integer c_n1 = -1;
|
c@427
|
20 static integer c__2 = 2;
|
c@427
|
21 static doublereal c_b20 = -1.;
|
c@427
|
22 static doublereal c_b22 = 1.;
|
c@427
|
23
|
c@427
|
24 /* Subroutine */ int dgetri_(integer *n, doublereal *a, integer *lda, integer
|
c@427
|
25 *ipiv, doublereal *work, integer *lwork, integer *info)
|
c@427
|
26 {
|
c@427
|
27 /* System generated locals */
|
c@427
|
28 integer a_dim1, a_offset, i__1, i__2, i__3;
|
c@427
|
29
|
c@427
|
30 /* Local variables */
|
c@427
|
31 integer i__, j, jb, nb, jj, jp, nn, iws;
|
c@427
|
32 extern /* Subroutine */ int dgemm_(char *, char *, integer *, integer *,
|
c@427
|
33 integer *, doublereal *, doublereal *, integer *, doublereal *,
|
c@427
|
34 integer *, doublereal *, doublereal *, integer *),
|
c@427
|
35 dgemv_(char *, integer *, integer *, doublereal *, doublereal *,
|
c@427
|
36 integer *, doublereal *, integer *, doublereal *, doublereal *,
|
c@427
|
37 integer *);
|
c@427
|
38 integer nbmin;
|
c@427
|
39 extern /* Subroutine */ int dswap_(integer *, doublereal *, integer *,
|
c@427
|
40 doublereal *, integer *), dtrsm_(char *, char *, char *, char *,
|
c@427
|
41 integer *, integer *, doublereal *, doublereal *, integer *,
|
c@427
|
42 doublereal *, integer *), xerbla_(
|
c@427
|
43 char *, integer *);
|
c@427
|
44 extern integer ilaenv_(integer *, char *, char *, integer *, integer *,
|
c@427
|
45 integer *, integer *);
|
c@427
|
46 integer ldwork;
|
c@427
|
47 extern /* Subroutine */ int dtrtri_(char *, char *, integer *, doublereal
|
c@427
|
48 *, integer *, integer *);
|
c@427
|
49 integer lwkopt;
|
c@427
|
50 logical lquery;
|
c@427
|
51
|
c@427
|
52
|
c@427
|
53 /* -- LAPACK routine (version 3.2) -- */
|
c@427
|
54 /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
|
c@427
|
55 /* November 2006 */
|
c@427
|
56
|
c@427
|
57 /* .. Scalar Arguments .. */
|
c@427
|
58 /* .. */
|
c@427
|
59 /* .. Array Arguments .. */
|
c@427
|
60 /* .. */
|
c@427
|
61
|
c@427
|
62 /* Purpose */
|
c@427
|
63 /* ======= */
|
c@427
|
64
|
c@427
|
65 /* DGETRI computes the inverse of a matrix using the LU factorization */
|
c@427
|
66 /* computed by DGETRF. */
|
c@427
|
67
|
c@427
|
68 /* This method inverts U and then computes inv(A) by solving the system */
|
c@427
|
69 /* inv(A)*L = inv(U) for inv(A). */
|
c@427
|
70
|
c@427
|
71 /* Arguments */
|
c@427
|
72 /* ========= */
|
c@427
|
73
|
c@427
|
74 /* N (input) INTEGER */
|
c@427
|
75 /* The order of the matrix A. N >= 0. */
|
c@427
|
76
|
c@427
|
77 /* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) */
|
c@427
|
78 /* On entry, the factors L and U from the factorization */
|
c@427
|
79 /* A = P*L*U as computed by DGETRF. */
|
c@427
|
80 /* On exit, if INFO = 0, the inverse of the original matrix A. */
|
c@427
|
81
|
c@427
|
82 /* LDA (input) INTEGER */
|
c@427
|
83 /* The leading dimension of the array A. LDA >= max(1,N). */
|
c@427
|
84
|
c@427
|
85 /* IPIV (input) INTEGER array, dimension (N) */
|
c@427
|
86 /* The pivot indices from DGETRF; for 1<=i<=N, row i of the */
|
c@427
|
87 /* matrix was interchanged with row IPIV(i). */
|
c@427
|
88
|
c@427
|
89 /* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) */
|
c@427
|
90 /* On exit, if INFO=0, then WORK(1) returns the optimal LWORK. */
|
c@427
|
91
|
c@427
|
92 /* LWORK (input) INTEGER */
|
c@427
|
93 /* The dimension of the array WORK. LWORK >= max(1,N). */
|
c@427
|
94 /* For optimal performance LWORK >= N*NB, where NB is */
|
c@427
|
95 /* the optimal blocksize returned by ILAENV. */
|
c@427
|
96
|
c@427
|
97 /* If LWORK = -1, then a workspace query is assumed; the routine */
|
c@427
|
98 /* only calculates the optimal size of the WORK array, returns */
|
c@427
|
99 /* this value as the first entry of the WORK array, and no error */
|
c@427
|
100 /* message related to LWORK is issued by XERBLA. */
|
c@427
|
101
|
c@427
|
102 /* INFO (output) INTEGER */
|
c@427
|
103 /* = 0: successful exit */
|
c@427
|
104 /* < 0: if INFO = -i, the i-th argument had an illegal value */
|
c@427
|
105 /* > 0: if INFO = i, U(i,i) is exactly zero; the matrix is */
|
c@427
|
106 /* singular and its inverse could not be computed. */
|
c@427
|
107
|
c@427
|
108 /* ===================================================================== */
|
c@427
|
109
|
c@427
|
110 /* .. Parameters .. */
|
c@427
|
111 /* .. */
|
c@427
|
112 /* .. Local Scalars .. */
|
c@427
|
113 /* .. */
|
c@427
|
114 /* .. External Functions .. */
|
c@427
|
115 /* .. */
|
c@427
|
116 /* .. External Subroutines .. */
|
c@427
|
117 /* .. */
|
c@427
|
118 /* .. Intrinsic Functions .. */
|
c@427
|
119 /* .. */
|
c@427
|
120 /* .. Executable Statements .. */
|
c@427
|
121
|
c@427
|
122 /* Test the input parameters. */
|
c@427
|
123
|
c@427
|
124 /* Parameter adjustments */
|
c@427
|
125 a_dim1 = *lda;
|
c@427
|
126 a_offset = 1 + a_dim1;
|
c@427
|
127 a -= a_offset;
|
c@427
|
128 --ipiv;
|
c@427
|
129 --work;
|
c@427
|
130
|
c@427
|
131 /* Function Body */
|
c@427
|
132 *info = 0;
|
c@427
|
133 nb = ilaenv_(&c__1, "DGETRI", " ", n, &c_n1, &c_n1, &c_n1);
|
c@427
|
134 lwkopt = *n * nb;
|
c@427
|
135 work[1] = (doublereal) lwkopt;
|
c@427
|
136 lquery = *lwork == -1;
|
c@427
|
137 if (*n < 0) {
|
c@427
|
138 *info = -1;
|
c@427
|
139 } else if (*lda < max(1,*n)) {
|
c@427
|
140 *info = -3;
|
c@427
|
141 } else if (*lwork < max(1,*n) && ! lquery) {
|
c@427
|
142 *info = -6;
|
c@427
|
143 }
|
c@427
|
144 if (*info != 0) {
|
c@427
|
145 i__1 = -(*info);
|
c@427
|
146 xerbla_("DGETRI", &i__1);
|
c@427
|
147 return 0;
|
c@427
|
148 } else if (lquery) {
|
c@427
|
149 return 0;
|
c@427
|
150 }
|
c@427
|
151
|
c@427
|
152 /* Quick return if possible */
|
c@427
|
153
|
c@427
|
154 if (*n == 0) {
|
c@427
|
155 return 0;
|
c@427
|
156 }
|
c@427
|
157
|
c@427
|
158 /* Form inv(U). If INFO > 0 from DTRTRI, then U is singular, */
|
c@427
|
159 /* and the inverse is not computed. */
|
c@427
|
160
|
c@427
|
161 dtrtri_("Upper", "Non-unit", n, &a[a_offset], lda, info);
|
c@427
|
162 if (*info > 0) {
|
c@427
|
163 return 0;
|
c@427
|
164 }
|
c@427
|
165
|
c@427
|
166 nbmin = 2;
|
c@427
|
167 ldwork = *n;
|
c@427
|
168 if (nb > 1 && nb < *n) {
|
c@427
|
169 /* Computing MAX */
|
c@427
|
170 i__1 = ldwork * nb;
|
c@427
|
171 iws = max(i__1,1);
|
c@427
|
172 if (*lwork < iws) {
|
c@427
|
173 nb = *lwork / ldwork;
|
c@427
|
174 /* Computing MAX */
|
c@427
|
175 i__1 = 2, i__2 = ilaenv_(&c__2, "DGETRI", " ", n, &c_n1, &c_n1, &
|
c@427
|
176 c_n1);
|
c@427
|
177 nbmin = max(i__1,i__2);
|
c@427
|
178 }
|
c@427
|
179 } else {
|
c@427
|
180 iws = *n;
|
c@427
|
181 }
|
c@427
|
182
|
c@427
|
183 /* Solve the equation inv(A)*L = inv(U) for inv(A). */
|
c@427
|
184
|
c@427
|
185 if (nb < nbmin || nb >= *n) {
|
c@427
|
186
|
c@427
|
187 /* Use unblocked code. */
|
c@427
|
188
|
c@427
|
189 for (j = *n; j >= 1; --j) {
|
c@427
|
190
|
c@427
|
191 /* Copy current column of L to WORK and replace with zeros. */
|
c@427
|
192
|
c@427
|
193 i__1 = *n;
|
c@427
|
194 for (i__ = j + 1; i__ <= i__1; ++i__) {
|
c@427
|
195 work[i__] = a[i__ + j * a_dim1];
|
c@427
|
196 a[i__ + j * a_dim1] = 0.;
|
c@427
|
197 /* L10: */
|
c@427
|
198 }
|
c@427
|
199
|
c@427
|
200 /* Compute current column of inv(A). */
|
c@427
|
201
|
c@427
|
202 if (j < *n) {
|
c@427
|
203 i__1 = *n - j;
|
c@427
|
204 dgemv_("No transpose", n, &i__1, &c_b20, &a[(j + 1) * a_dim1
|
c@427
|
205 + 1], lda, &work[j + 1], &c__1, &c_b22, &a[j * a_dim1
|
c@427
|
206 + 1], &c__1);
|
c@427
|
207 }
|
c@427
|
208 /* L20: */
|
c@427
|
209 }
|
c@427
|
210 } else {
|
c@427
|
211
|
c@427
|
212 /* Use blocked code. */
|
c@427
|
213
|
c@427
|
214 nn = (*n - 1) / nb * nb + 1;
|
c@427
|
215 i__1 = -nb;
|
c@427
|
216 for (j = nn; i__1 < 0 ? j >= 1 : j <= 1; j += i__1) {
|
c@427
|
217 /* Computing MIN */
|
c@427
|
218 i__2 = nb, i__3 = *n - j + 1;
|
c@427
|
219 jb = min(i__2,i__3);
|
c@427
|
220
|
c@427
|
221 /* Copy current block column of L to WORK and replace with */
|
c@427
|
222 /* zeros. */
|
c@427
|
223
|
c@427
|
224 i__2 = j + jb - 1;
|
c@427
|
225 for (jj = j; jj <= i__2; ++jj) {
|
c@427
|
226 i__3 = *n;
|
c@427
|
227 for (i__ = jj + 1; i__ <= i__3; ++i__) {
|
c@427
|
228 work[i__ + (jj - j) * ldwork] = a[i__ + jj * a_dim1];
|
c@427
|
229 a[i__ + jj * a_dim1] = 0.;
|
c@427
|
230 /* L30: */
|
c@427
|
231 }
|
c@427
|
232 /* L40: */
|
c@427
|
233 }
|
c@427
|
234
|
c@427
|
235 /* Compute current block column of inv(A). */
|
c@427
|
236
|
c@427
|
237 if (j + jb <= *n) {
|
c@427
|
238 i__2 = *n - j - jb + 1;
|
c@427
|
239 dgemm_("No transpose", "No transpose", n, &jb, &i__2, &c_b20,
|
c@427
|
240 &a[(j + jb) * a_dim1 + 1], lda, &work[j + jb], &
|
c@427
|
241 ldwork, &c_b22, &a[j * a_dim1 + 1], lda);
|
c@427
|
242 }
|
c@427
|
243 dtrsm_("Right", "Lower", "No transpose", "Unit", n, &jb, &c_b22, &
|
c@427
|
244 work[j], &ldwork, &a[j * a_dim1 + 1], lda);
|
c@427
|
245 /* L50: */
|
c@427
|
246 }
|
c@427
|
247 }
|
c@427
|
248
|
c@427
|
249 /* Apply column interchanges. */
|
c@427
|
250
|
c@427
|
251 for (j = *n - 1; j >= 1; --j) {
|
c@427
|
252 jp = ipiv[j];
|
c@427
|
253 if (jp != j) {
|
c@427
|
254 dswap_(n, &a[j * a_dim1 + 1], &c__1, &a[jp * a_dim1 + 1], &c__1);
|
c@427
|
255 }
|
c@427
|
256 /* L60: */
|
c@427
|
257 }
|
c@427
|
258
|
c@427
|
259 work[1] = (doublereal) iws;
|
c@427
|
260 return 0;
|
c@427
|
261
|
c@427
|
262 /* End of DGETRI */
|
c@427
|
263
|
c@427
|
264 } /* dgetri_ */
|