Lots of trailing whitespaces in the files of Syd. Cleaning this. No big deal.
[platform/upstream/lapack.git] / SRC / chetri_rook.f
1 *> \brief \b CHETRI_ROOK computes the inverse of HE matrix using the factorization obtained with the bounded Bunch-Kaufman ("rook") diagonal pivoting method.
2 *
3 *  =========== DOCUMENTATION ===========
4 *
5 * Online html documentation available at
6 *            http://www.netlib.org/lapack/explore-html/
7 *
8 *> \htmlonly
9 *> Download CHETRI_ROOK + dependencies
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/chetri_rook.f">
11 *> [TGZ]</a>
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/chetri_rook.f">
13 *> [ZIP]</a>
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chetri_rook.f">
15 *> [TXT]</a>
16 *> \endhtmlonly
17 *
18 *  Definition:
19 *  ===========
20 *
21 *       SUBROUTINE CHETRI_ROOK( UPLO, N, A, LDA, IPIV, WORK, INFO )
22 *
23 *       .. Scalar Arguments ..
24 *       CHARACTER          UPLO
25 *       INTEGER            INFO, LDA, N
26 *       ..
27 *       .. Array Arguments ..
28 *       INTEGER            IPIV( * )
29 *       COMPLEX            A( LDA, * ), WORK( * )
30 *       ..
31 *
32 *
33 *> \par Purpose:
34 *  =============
35 *>
36 *> \verbatim
37 *>
38 *> CHETRI_ROOK computes the inverse of a complex Hermitian indefinite matrix
39 *> A using the factorization A = U*D*U**H or A = L*D*L**H computed by
40 *> CHETRF_ROOK.
41 *> \endverbatim
42 *
43 *  Arguments:
44 *  ==========
45 *
46 *> \param[in] UPLO
47 *> \verbatim
48 *>          UPLO is CHARACTER*1
49 *>          Specifies whether the details of the factorization are stored
50 *>          as an upper or lower triangular matrix.
51 *>          = 'U':  Upper triangular, form is A = U*D*U**H;
52 *>          = 'L':  Lower triangular, form is A = L*D*L**H.
53 *> \endverbatim
54 *>
55 *> \param[in] N
56 *> \verbatim
57 *>          N is INTEGER
58 *>          The order of the matrix A.  N >= 0.
59 *> \endverbatim
60 *>
61 *> \param[in,out] A
62 *> \verbatim
63 *>          A is COMPLEX array, dimension (LDA,N)
64 *>          On entry, the block diagonal matrix D and the multipliers
65 *>          used to obtain the factor U or L as computed by CHETRF_ROOK.
66 *>
67 *>          On exit, if INFO = 0, the (Hermitian) inverse of the original
68 *>          matrix.  If UPLO = 'U', the upper triangular part of the
69 *>          inverse is formed and the part of A below the diagonal is not
70 *>          referenced; if UPLO = 'L' the lower triangular part of the
71 *>          inverse is formed and the part of A above the diagonal is
72 *>          not referenced.
73 *> \endverbatim
74 *>
75 *> \param[in] LDA
76 *> \verbatim
77 *>          LDA is INTEGER
78 *>          The leading dimension of the array A.  LDA >= max(1,N).
79 *> \endverbatim
80 *>
81 *> \param[in] IPIV
82 *> \verbatim
83 *>          IPIV is INTEGER array, dimension (N)
84 *>          Details of the interchanges and the block structure of D
85 *>          as determined by CHETRF_ROOK.
86 *> \endverbatim
87 *>
88 *> \param[out] WORK
89 *> \verbatim
90 *>          WORK is COMPLEX array, dimension (N)
91 *> \endverbatim
92 *>
93 *> \param[out] INFO
94 *> \verbatim
95 *>          INFO is INTEGER
96 *>          = 0: successful exit
97 *>          < 0: if INFO = -i, the i-th argument had an illegal value
98 *>          > 0: if INFO = i, D(i,i) = 0; the matrix is singular and its
99 *>               inverse could not be computed.
100 *> \endverbatim
101 *
102 *  Authors:
103 *  ========
104 *
105 *> \author Univ. of Tennessee
106 *> \author Univ. of California Berkeley
107 *> \author Univ. of Colorado Denver
108 *> \author NAG Ltd.
109 *
110 *> \date November 2013
111 *
112 *> \ingroup complexHEcomputational
113 *
114 *> \par Contributors:
115 *  ==================
116 *>
117 *> \verbatim
118 *>
119 *>  November 2013,  Igor Kozachenko,
120 *>                  Computer Science Division,
121 *>                  University of California, Berkeley
122 *>
123 *>  September 2007, Sven Hammarling, Nicholas J. Higham, Craig Lucas,
124 *>                  School of Mathematics,
125 *>                  University of Manchester
126 *> \endverbatim
127 *
128 *  =====================================================================
129       SUBROUTINE CHETRI_ROOK( UPLO, N, A, LDA, IPIV, WORK, INFO )
130 *
131 *  -- LAPACK computational routine (version 3.5.0) --
132 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
133 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
134 *     November 2013
135 *
136 *     .. Scalar Arguments ..
137       CHARACTER          UPLO
138       INTEGER            INFO, LDA, N
139 *     ..
140 *     .. Array Arguments ..
141       INTEGER            IPIV( * )
142       COMPLEX            A( LDA, * ), WORK( * )
143 *     ..
144 *
145 *  =====================================================================
146 *
147 *     .. Parameters ..
148       REAL               ONE
149       COMPLEX            CONE, CZERO
150       PARAMETER          ( ONE = 1.0E+0, CONE = ( 1.0E+0, 0.0E+0 ),
151      $                   CZERO = ( 0.0E+0, 0.0E+0 ) )
152 *     ..
153 *     .. Local Scalars ..
154       LOGICAL            UPPER
155       INTEGER            J, K, KP, KSTEP
156       REAL               AK, AKP1, D, T
157       COMPLEX            AKKP1, TEMP
158 *     ..
159 *     .. External Functions ..
160       LOGICAL            LSAME
161       COMPLEX            CDOTC
162       EXTERNAL           LSAME, CDOTC
163 *     ..
164 *     .. External Subroutines ..
165       EXTERNAL           CCOPY, CHEMV, CSWAP, XERBLA
166 *     ..
167 *     .. Intrinsic Functions ..
168       INTRINSIC          ABS, CONJG, MAX, REAL
169 *     ..
170 *     .. Executable Statements ..
171 *
172 *     Test the input parameters.
173 *
174       INFO = 0
175       UPPER = LSAME( UPLO, 'U' )
176       IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
177          INFO = -1
178       ELSE IF( N.LT.0 ) THEN
179          INFO = -2
180       ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
181          INFO = -4
182       END IF
183       IF( INFO.NE.0 ) THEN
184          CALL XERBLA( 'CHETRI_ROOK', -INFO )
185          RETURN
186       END IF
187 *
188 *     Quick return if possible
189 *
190       IF( N.EQ.0 )
191      $   RETURN
192 *
193 *     Check that the diagonal matrix D is nonsingular.
194 *
195       IF( UPPER ) THEN
196 *
197 *        Upper triangular storage: examine D from bottom to top
198 *
199          DO 10 INFO = N, 1, -1
200             IF( IPIV( INFO ).GT.0 .AND. A( INFO, INFO ).EQ.CZERO )
201      $         RETURN
202    10    CONTINUE
203       ELSE
204 *
205 *        Lower triangular storage: examine D from top to bottom.
206 *
207          DO 20 INFO = 1, N
208             IF( IPIV( INFO ).GT.0 .AND. A( INFO, INFO ).EQ.CZERO )
209      $         RETURN
210    20    CONTINUE
211       END IF
212       INFO = 0
213 *
214       IF( UPPER ) THEN
215 *
216 *        Compute inv(A) from the factorization A = U*D*U**H.
217 *
218 *        K is the main loop index, increasing from 1 to N in steps of
219 *        1 or 2, depending on the size of the diagonal blocks.
220 *
221          K = 1
222    30    CONTINUE
223 *
224 *        If K > N, exit from loop.
225 *
226          IF( K.GT.N )
227      $      GO TO 70
228 *
229          IF( IPIV( K ).GT.0 ) THEN
230 *
231 *           1 x 1 diagonal block
232 *
233 *           Invert the diagonal block.
234 *
235             A( K, K ) = ONE / REAL( A( K, K ) )
236 *
237 *           Compute column K of the inverse.
238 *
239             IF( K.GT.1 ) THEN
240                CALL CCOPY( K-1, A( 1, K ), 1, WORK, 1 )
241                CALL CHEMV( UPLO, K-1, -CONE, A, LDA, WORK, 1, CZERO,
242      $                     A( 1, K ), 1 )
243                A( K, K ) = A( K, K ) - REAL( CDOTC( K-1, WORK, 1, A( 1,
244      $                     K ), 1 ) )
245             END IF
246             KSTEP = 1
247          ELSE
248 *
249 *           2 x 2 diagonal block
250 *
251 *           Invert the diagonal block.
252 *
253             T = ABS( A( K, K+1 ) )
254             AK = REAL( A( K, K ) ) / T
255             AKP1 = REAL( A( K+1, K+1 ) ) / T
256             AKKP1 = A( K, K+1 ) / T
257             D = T*( AK*AKP1-ONE )
258             A( K, K ) = AKP1 / D
259             A( K+1, K+1 ) = AK / D
260             A( K, K+1 ) = -AKKP1 / D
261 *
262 *           Compute columns K and K+1 of the inverse.
263 *
264             IF( K.GT.1 ) THEN
265                CALL CCOPY( K-1, A( 1, K ), 1, WORK, 1 )
266                CALL CHEMV( UPLO, K-1, -CONE, A, LDA, WORK, 1, CZERO,
267      $                     A( 1, K ), 1 )
268                A( K, K ) = A( K, K ) - REAL( CDOTC( K-1, WORK, 1, A( 1,
269      $                     K ), 1 ) )
270                A( K, K+1 ) = A( K, K+1 ) -
271      $                       CDOTC( K-1, A( 1, K ), 1, A( 1, K+1 ), 1 )
272                CALL CCOPY( K-1, A( 1, K+1 ), 1, WORK, 1 )
273                CALL CHEMV( UPLO, K-1, -CONE, A, LDA, WORK, 1, CZERO,
274      $                     A( 1, K+1 ), 1 )
275                A( K+1, K+1 ) = A( K+1, K+1 ) -
276      $                         REAL( CDOTC( K-1, WORK, 1, A( 1, K+1 ),
277      $                         1 ) )
278             END IF
279             KSTEP = 2
280          END IF
281 *
282          IF( KSTEP.EQ.1 ) THEN
283 *
284 *           Interchange rows and columns K and IPIV(K) in the leading
285 *           submatrix A(1:k,1:k)
286 *
287             KP = IPIV( K )
288             IF( KP.NE.K ) THEN
289 *
290                IF( KP.GT.1 )
291      $            CALL CSWAP( KP-1, A( 1, K ), 1, A( 1, KP ), 1 )
292 *
293                DO 40 J = KP + 1, K - 1
294                   TEMP = CONJG( A( J, K ) )
295                   A( J, K ) = CONJG( A( KP, J ) )
296                   A( KP, J ) = TEMP
297    40          CONTINUE
298 *
299                A( KP, K ) = CONJG( A( KP, K ) )
300 *
301                TEMP = A( K, K )
302                A( K, K ) = A( KP, KP )
303                A( KP, KP ) = TEMP
304             END IF
305          ELSE
306 *
307 *           Interchange rows and columns K and K+1 with -IPIV(K) and
308 *           -IPIV(K+1) in the leading submatrix A(k+1:n,k+1:n)
309 *
310 *           (1) Interchange rows and columns K and -IPIV(K)
311 *
312             KP = -IPIV( K )
313             IF( KP.NE.K ) THEN
314 *
315                IF( KP.GT.1 )
316      $            CALL CSWAP( KP-1, A( 1, K ), 1, A( 1, KP ), 1 )
317 *
318                DO 50 J = KP + 1, K - 1
319                   TEMP = CONJG( A( J, K ) )
320                   A( J, K ) = CONJG( A( KP, J ) )
321                   A( KP, J ) = TEMP
322    50          CONTINUE
323 *
324                A( KP, K ) = CONJG( A( KP, K ) )
325 *
326                TEMP = A( K, K )
327                A( K, K ) = A( KP, KP )
328                A( KP, KP ) = TEMP
329 *
330                TEMP = A( K, K+1 )
331                A( K, K+1 ) = A( KP, K+1 )
332                A( KP, K+1 ) = TEMP
333             END IF
334 *
335 *           (2) Interchange rows and columns K+1 and -IPIV(K+1)
336 *
337             K = K + 1
338             KP = -IPIV( K )
339             IF( KP.NE.K ) THEN
340 *
341                IF( KP.GT.1 )
342      $            CALL CSWAP( KP-1, A( 1, K ), 1, A( 1, KP ), 1 )
343 *
344                DO 60 J = KP + 1, K - 1
345                   TEMP = CONJG( A( J, K ) )
346                   A( J, K ) = CONJG( A( KP, J ) )
347                   A( KP, J ) = TEMP
348    60          CONTINUE
349 *
350                A( KP, K ) = CONJG( A( KP, K ) )
351 *
352                TEMP = A( K, K )
353                A( K, K ) = A( KP, KP )
354                A( KP, KP ) = TEMP
355             END IF
356          END IF
357 *
358          K = K + 1
359          GO TO 30
360    70    CONTINUE
361 *
362       ELSE
363 *
364 *        Compute inv(A) from the factorization A = L*D*L**H.
365 *
366 *        K is the main loop index, decreasing from N to 1 in steps of
367 *        1 or 2, depending on the size of the diagonal blocks.
368 *
369          K = N
370    80    CONTINUE
371 *
372 *        If K < 1, exit from loop.
373 *
374          IF( K.LT.1 )
375      $      GO TO 120
376 *
377          IF( IPIV( K ).GT.0 ) THEN
378 *
379 *           1 x 1 diagonal block
380 *
381 *           Invert the diagonal block.
382 *
383             A( K, K ) = ONE / REAL( A( K, K ) )
384 *
385 *           Compute column K of the inverse.
386 *
387             IF( K.LT.N ) THEN
388                CALL CCOPY( N-K, A( K+1, K ), 1, WORK, 1 )
389                CALL CHEMV( UPLO, N-K, -CONE, A( K+1, K+1 ), LDA, WORK,
390      $                     1, CZERO, A( K+1, K ), 1 )
391                A( K, K ) = A( K, K ) - REAL( CDOTC( N-K, WORK, 1,
392      $                     A( K+1, K ), 1 ) )
393             END IF
394             KSTEP = 1
395          ELSE
396 *
397 *           2 x 2 diagonal block
398 *
399 *           Invert the diagonal block.
400 *
401             T = ABS( A( K, K-1 ) )
402             AK = REAL( A( K-1, K-1 ) ) / T
403             AKP1 = REAL( A( K, K ) ) / T
404             AKKP1 = A( K, K-1 ) / T
405             D = T*( AK*AKP1-ONE )
406             A( K-1, K-1 ) = AKP1 / D
407             A( K, K ) = AK / D
408             A( K, K-1 ) = -AKKP1 / D
409 *
410 *           Compute columns K-1 and K of the inverse.
411 *
412             IF( K.LT.N ) THEN
413                CALL CCOPY( N-K, A( K+1, K ), 1, WORK, 1 )
414                CALL CHEMV( UPLO, N-K, -CONE, A( K+1, K+1 ), LDA, WORK,
415      $                     1, CZERO, A( K+1, K ), 1 )
416                A( K, K ) = A( K, K ) - REAL( CDOTC( N-K, WORK, 1,
417      $                     A( K+1, K ), 1 ) )
418                A( K, K-1 ) = A( K, K-1 ) -
419      $                       CDOTC( N-K, A( K+1, K ), 1, A( K+1, K-1 ),
420      $                       1 )
421                CALL CCOPY( N-K, A( K+1, K-1 ), 1, WORK, 1 )
422                CALL CHEMV( UPLO, N-K, -CONE, A( K+1, K+1 ), LDA, WORK,
423      $                     1, CZERO, A( K+1, K-1 ), 1 )
424                A( K-1, K-1 ) = A( K-1, K-1 ) -
425      $                         REAL( CDOTC( N-K, WORK, 1, A( K+1, K-1 ),
426      $                         1 ) )
427             END IF
428             KSTEP = 2
429          END IF
430 *
431          IF( KSTEP.EQ.1 ) THEN
432 *
433 *           Interchange rows and columns K and IPIV(K) in the trailing
434 *           submatrix A(k:n,k:n)
435 *
436             KP = IPIV( K )
437             IF( KP.NE.K ) THEN
438 *
439                IF( KP.LT.N )
440      $            CALL CSWAP( N-KP, A( KP+1, K ), 1, A( KP+1, KP ), 1 )
441 *
442                DO 90 J = K + 1, KP - 1
443                   TEMP = CONJG( A( J, K ) )
444                   A( J, K ) = CONJG( A( KP, J ) )
445                   A( KP, J ) = TEMP
446    90          CONTINUE
447 *
448                A( KP, K ) = CONJG( A( KP, K ) )
449 *
450                TEMP = A( K, K )
451                A( K, K ) = A( KP, KP )
452                A( KP, KP ) = TEMP
453             END IF
454          ELSE
455 *
456 *           Interchange rows and columns K and K-1 with -IPIV(K) and
457 *           -IPIV(K-1) in the trailing submatrix A(k-1:n,k-1:n)
458 *
459 *           (1) Interchange rows and columns K and -IPIV(K)
460 *
461             KP = -IPIV( K )
462             IF( KP.NE.K ) THEN
463 *
464                IF( KP.LT.N )
465      $            CALL CSWAP( N-KP, A( KP+1, K ), 1, A( KP+1, KP ), 1 )
466 *
467                DO 100 J = K + 1, KP - 1
468                   TEMP = CONJG( A( J, K ) )
469                   A( J, K ) = CONJG( A( KP, J ) )
470                   A( KP, J ) = TEMP
471   100         CONTINUE
472 *
473                A( KP, K ) = CONJG( A( KP, K ) )
474 *
475                TEMP = A( K, K )
476                A( K, K ) = A( KP, KP )
477                A( KP, KP ) = TEMP
478 *
479                TEMP = A( K, K-1 )
480                A( K, K-1 ) = A( KP, K-1 )
481                A( KP, K-1 ) = TEMP
482             END IF
483 *
484 *           (2) Interchange rows and columns K-1 and -IPIV(K-1)
485 *
486             K = K - 1
487             KP = -IPIV( K )
488             IF( KP.NE.K ) THEN
489 *
490                IF( KP.LT.N )
491      $            CALL CSWAP( N-KP, A( KP+1, K ), 1, A( KP+1, KP ), 1 )
492 *
493                DO 110 J = K + 1, KP - 1
494                   TEMP = CONJG( A( J, K ) )
495                   A( J, K ) = CONJG( A( KP, J ) )
496                   A( KP, J ) = TEMP
497   110         CONTINUE
498 *
499                A( KP, K ) = CONJG( A( KP, K ) )
500 *
501                TEMP = A( K, K )
502                A( K, K ) = A( KP, KP )
503                A( KP, KP ) = TEMP
504             END IF
505          END IF
506 *
507          K = K - 1
508          GO TO 80
509   120    CONTINUE
510       END IF
511 *
512       RETURN
513 *
514 *     End of CHETRI_ROOK
515 *
516       END