1*> \brief \b CLAVHE_ROOK
2*
3*  =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6*            http://www.netlib.org/lapack/explore-html/
7*
8*  Definition:
9*  ===========
10*
11*       SUBROUTINE CLAVHE_ROOK( UPLO, TRANS, DIAG, N, NRHS, A, LDA, IPIV, B,
12*                               LDB, INFO )
13*
14*       .. Scalar Arguments ..
15*       CHARACTER          DIAG, TRANS, UPLO
16*       INTEGER            INFO, LDA, LDB, N, NRHS
17*       ..
18*       .. Array Arguments ..
19*       INTEGER            IPIV( * )
20*       COMPLEX            A( LDA, * ), B( LDB, * )
21*       ..
22*
23*
24*> \par Purpose:
25*  =============
26*>
27*> \verbatim
28*>
29*> CLAVHE_ROOK performs one of the matrix-vector operations
30*>    x := A*x  or  x := A^H*x,
31*> where x is an N element vector and  A is one of the factors
32*> from the block U*D*U' or L*D*L' factorization computed by CHETRF_ROOK.
33*>
34*> If TRANS = 'N', multiplies by U  or U * D  (or L  or L * D)
35*> If TRANS = 'C', multiplies by U' or D * U' (or L' or D * L')
36*> \endverbatim
37*
38*  Arguments:
39*  ==========
40*
41*> \param[in] UPLO
42*> \verbatim
43*>          UPLO is CHARACTER*1
44*>          Specifies whether the factor stored in A is upper or lower
45*>          triangular.
46*>          = 'U':  Upper triangular
47*>          = 'L':  Lower triangular
48*> \endverbatim
49*>
50*> \param[in] TRANS
51*> \verbatim
52*>          TRANS is CHARACTER*1
53*>          Specifies the operation to be performed:
54*>          = 'N':  x := A*x
55*>          = 'C':   x := A^H*x
56*> \endverbatim
57*>
58*> \param[in] DIAG
59*> \verbatim
60*>          DIAG is CHARACTER*1
61*>          Specifies whether or not the diagonal blocks are unit
62*>          matrices.  If the diagonal blocks are assumed to be unit,
63*>          then A = U or A = L, otherwise A = U*D or A = L*D.
64*>          = 'U':  Diagonal blocks are assumed to be unit matrices.
65*>          = 'N':  Diagonal blocks are assumed to be non-unit matrices.
66*> \endverbatim
67*>
68*> \param[in] N
69*> \verbatim
70*>          N is INTEGER
71*>          The number of rows and columns of the matrix A.  N >= 0.
72*> \endverbatim
73*>
74*> \param[in] NRHS
75*> \verbatim
76*>          NRHS is INTEGER
77*>          The number of right hand sides, i.e., the number of vectors
78*>          x to be multiplied by A.  NRHS >= 0.
79*> \endverbatim
80*>
81*> \param[in] A
82*> \verbatim
83*>          A is COMPLEX array, dimension (LDA,N)
84*>          The block diagonal matrix D and the multipliers used to
85*>          obtain the factor U or L as computed by CHETRF_ROOK.
86*>          Stored as a 2-D triangular matrix.
87*> \endverbatim
88*>
89*> \param[in] LDA
90*> \verbatim
91*>          LDA is INTEGER
92*>          The leading dimension of the array A.  LDA >= max(1,N).
93*> \endverbatim
94*>
95*> \param[out] IPIV
96*> \verbatim
97*>          IPIV is INTEGER array, dimension (N)
98*>          Details of the interchanges and the block structure of D,
99*>          as determined by CHETRF_ROOK.
100*>          If UPLO = 'U':
101*>             Only the last KB elements of IPIV are set.
102*>
103*>             If IPIV(k) > 0, then rows and columns k and IPIV(k) were
104*>             interchanged and D(k,k) is a 1-by-1 diagonal block.
105*>
106*>             If IPIV(k) < 0 and IPIV(k-1) < 0, then rows and
107*>             columns k and -IPIV(k) were interchanged and rows and
108*>             columns k-1 and -IPIV(k-1) were inerchaged,
109*>             D(k-1:k,k-1:k) is a 2-by-2 diagonal block.
110*>
111*>          If UPLO = 'L':
112*>             Only the first KB elements of IPIV are set.
113*>
114*>             If IPIV(k) > 0, then rows and columns k and IPIV(k)
115*>             were interchanged and D(k,k) is a 1-by-1 diagonal block.
116*>
117*>             If IPIV(k) < 0 and IPIV(k+1) < 0, then rows and
118*>             columns k and -IPIV(k) were interchanged and rows and
119*>             columns k+1 and -IPIV(k+1) were inerchaged,
120*>             D(k:k+1,k:k+1) is a 2-by-2 diagonal block.
121*> \endverbatim
122*>
123*> \param[in,out] B
124*> \verbatim
125*>          B is COMPLEX array, dimension (LDB,NRHS)
126*>          On entry, B contains NRHS vectors of length N.
127*>          On exit, B is overwritten with the product A * B.
128*> \endverbatim
129*>
130*> \param[in] LDB
131*> \verbatim
132*>          LDB is INTEGER
133*>          The leading dimension of the array B.  LDB >= max(1,N).
134*> \endverbatim
135*>
136*> \param[out] INFO
137*> \verbatim
138*>          INFO is INTEGER
139*>          = 0: successful exit
140*>          < 0: if INFO = -k, the k-th argument had an illegal value
141*> \endverbatim
142*
143*  Authors:
144*  ========
145*
146*> \author Univ. of Tennessee
147*> \author Univ. of California Berkeley
148*> \author Univ. of Colorado Denver
149*> \author NAG Ltd.
150*
151*> \date November 2013
152*
153*> \ingroup complex_lin
154*
155*  =====================================================================
156      SUBROUTINE CLAVHE_ROOK( UPLO, TRANS, DIAG, N, NRHS, A, LDA, IPIV,
157     $                        B, LDB, INFO )
158*
159*  -- LAPACK test routine (version 3.5.0) --
160*  -- LAPACK is a software package provided by Univ. of Tennessee,    --
161*  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
162*     November 2013
163*
164*     .. Scalar Arguments ..
165      CHARACTER          DIAG, TRANS, UPLO
166      INTEGER            INFO, LDA, LDB, N, NRHS
167*     ..
168*     .. Array Arguments ..
169      INTEGER            IPIV( * )
170      COMPLEX            A( LDA, * ), B( LDB, * )
171*     ..
172*
173*  =====================================================================
174*
175*     .. Parameters ..
176      COMPLEX            CONE
177      PARAMETER          ( CONE = ( 1.0E+0, 0.0E+0 ) )
178*     ..
179*     .. Local Scalars ..
180      LOGICAL            NOUNIT
181      INTEGER            J, K, KP
182      COMPLEX            D11, D12, D21, D22, T1, T2
183*     ..
184*     .. External Functions ..
185      LOGICAL            LSAME
186      EXTERNAL           LSAME
187*     ..
188*     .. External Subroutines ..
189      EXTERNAL           CGEMV, CGERU, CLACGV, CSCAL, CSWAP, XERBLA
190*     ..
191*     .. Intrinsic Functions ..
192      INTRINSIC          ABS, CONJG, MAX
193*     ..
194*     .. Executable Statements ..
195*
196*     Test the input parameters.
197*
198      INFO = 0
199      IF( .NOT.LSAME( UPLO, 'U' ) .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
200         INFO = -1
201      ELSE IF( .NOT.LSAME( TRANS, 'N' ) .AND. .NOT.LSAME( TRANS, 'C' ) )
202     $          THEN
203         INFO = -2
204      ELSE IF( .NOT.LSAME( DIAG, 'U' ) .AND. .NOT.LSAME( DIAG, 'N' ) )
205     $          THEN
206         INFO = -3
207      ELSE IF( N.LT.0 ) THEN
208         INFO = -4
209      ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
210         INFO = -6
211      ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
212         INFO = -9
213      END IF
214      IF( INFO.NE.0 ) THEN
215         CALL XERBLA( 'CLAVHE_ROOK ', -INFO )
216         RETURN
217      END IF
218*
219*     Quick return if possible.
220*
221      IF( N.EQ.0 )
222     $   RETURN
223*
224      NOUNIT = LSAME( DIAG, 'N' )
225*------------------------------------------
226*
227*     Compute  B := A * B  (No transpose)
228*
229*------------------------------------------
230      IF( LSAME( TRANS, 'N' ) ) THEN
231*
232*        Compute  B := U*B
233*        where U = P(m)*inv(U(m))* ... *P(1)*inv(U(1))
234*
235         IF( LSAME( UPLO, 'U' ) ) THEN
236*
237*        Loop forward applying the transformations.
238*
239            K = 1
240   10       CONTINUE
241            IF( K.GT.N )
242     $         GO TO 30
243            IF( IPIV( K ).GT.0 ) THEN
244*
245*              1 x 1 pivot block
246*
247*              Multiply by the diagonal element if forming U * D.
248*
249               IF( NOUNIT )
250     $            CALL CSCAL( NRHS, A( K, K ), B( K, 1 ), LDB )
251*
252*              Multiply by  P(K) * inv(U(K))  if K > 1.
253*
254               IF( K.GT.1 ) THEN
255*
256*                 Apply the transformation.
257*
258                  CALL CGERU( K-1, NRHS, CONE, A( 1, K ), 1, B( K, 1 ),
259     $                        LDB, B( 1, 1 ), LDB )
260*
261*                 Interchange if P(K) != I.
262*
263                  KP = IPIV( K )
264                  IF( KP.NE.K )
265     $               CALL CSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
266               END IF
267               K = K + 1
268            ELSE
269*
270*              2 x 2 pivot block
271*
272*              Multiply by the diagonal block if forming U * D.
273*
274               IF( NOUNIT ) THEN
275                  D11 = A( K, K )
276                  D22 = A( K+1, K+1 )
277                  D12 = A( K, K+1 )
278                  D21 = CONJG( D12 )
279                  DO 20 J = 1, NRHS
280                     T1 = B( K, J )
281                     T2 = B( K+1, J )
282                     B( K, J ) = D11*T1 + D12*T2
283                     B( K+1, J ) = D21*T1 + D22*T2
284   20             CONTINUE
285               END IF
286*
287*              Multiply by  P(K) * inv(U(K))  if K > 1.
288*
289               IF( K.GT.1 ) THEN
290*
291*                 Apply the transformations.
292*
293                  CALL CGERU( K-1, NRHS, CONE, A( 1, K ), 1, B( K, 1 ),
294     $                        LDB, B( 1, 1 ), LDB )
295                  CALL CGERU( K-1, NRHS, CONE, A( 1, K+1 ), 1,
296     $                        B( K+1, 1 ), LDB, B( 1, 1 ), LDB )
297*
298*                 Interchange if a permutation was applied at the
299*                 K-th step of the factorization.
300*
301*                 Swap the first of pair with IMAXth
302*
303                  KP = ABS( IPIV( K ) )
304                  IF( KP.NE.K )
305     $               CALL CSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
306*
307*                 NOW swap the first of pair with Pth
308*
309                  KP = ABS( IPIV( K+1 ) )
310                  IF( KP.NE.K+1 )
311     $               CALL CSWAP( NRHS, B( K+1, 1 ), LDB, B( KP, 1 ),
312     $                           LDB )
313               END IF
314               K = K + 2
315            END IF
316            GO TO 10
317   30       CONTINUE
318*
319*        Compute  B := L*B
320*        where L = P(1)*inv(L(1))* ... *P(m)*inv(L(m)) .
321*
322         ELSE
323*
324*           Loop backward applying the transformations to B.
325*
326            K = N
327   40       CONTINUE
328            IF( K.LT.1 )
329     $         GO TO 60
330*
331*           Test the pivot index.  If greater than zero, a 1 x 1
332*           pivot was used, otherwise a 2 x 2 pivot was used.
333*
334            IF( IPIV( K ).GT.0 ) THEN
335*
336*              1 x 1 pivot block:
337*
338*              Multiply by the diagonal element if forming L * D.
339*
340               IF( NOUNIT )
341     $            CALL CSCAL( NRHS, A( K, K ), B( K, 1 ), LDB )
342*
343*              Multiply by  P(K) * inv(L(K))  if K < N.
344*
345               IF( K.NE.N ) THEN
346                  KP = IPIV( K )
347*
348*                 Apply the transformation.
349*
350                  CALL CGERU( N-K, NRHS, CONE, A( K+1, K ), 1,
351     $                        B( K, 1 ), LDB, B( K+1, 1 ), LDB )
352*
353*                 Interchange if a permutation was applied at the
354*                 K-th step of the factorization.
355*
356                  IF( KP.NE.K )
357     $               CALL CSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
358               END IF
359               K = K - 1
360*
361            ELSE
362*
363*              2 x 2 pivot block:
364*
365*              Multiply by the diagonal block if forming L * D.
366*
367               IF( NOUNIT ) THEN
368                  D11 = A( K-1, K-1 )
369                  D22 = A( K, K )
370                  D21 = A( K, K-1 )
371                  D12 = CONJG( D21 )
372                  DO 50 J = 1, NRHS
373                     T1 = B( K-1, J )
374                     T2 = B( K, J )
375                     B( K-1, J ) = D11*T1 + D12*T2
376                     B( K, J ) = D21*T1 + D22*T2
377   50             CONTINUE
378               END IF
379*
380*              Multiply by  P(K) * inv(L(K))  if K < N.
381*
382               IF( K.NE.N ) THEN
383*
384*                 Apply the transformation.
385*
386                  CALL CGERU( N-K, NRHS, CONE, A( K+1, K ), 1,
387     $                        B( K, 1 ), LDB, B( K+1, 1 ), LDB )
388                  CALL CGERU( N-K, NRHS, CONE, A( K+1, K-1 ), 1,
389     $                        B( K-1, 1 ), LDB, B( K+1, 1 ), LDB )
390*
391*                 Interchange if a permutation was applied at the
392*                 K-th step of the factorization.
393*
394*
395*                 Swap the second of pair with IMAXth
396*
397                  KP = ABS( IPIV( K ) )
398                  IF( KP.NE.K )
399     $               CALL CSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
400*
401*                 NOW swap the first of pair with Pth
402*
403                  KP = ABS( IPIV( K-1 ) )
404                  IF( KP.NE.K-1 )
405     $               CALL CSWAP( NRHS, B( K-1, 1 ), LDB, B( KP, 1 ),
406     $                           LDB )
407*
408               END IF
409               K = K - 2
410            END IF
411            GO TO 40
412   60       CONTINUE
413         END IF
414*--------------------------------------------------
415*
416*     Compute  B := A^H * B  (conjugate transpose)
417*
418*--------------------------------------------------
419      ELSE
420*
421*        Form  B := U^H*B
422*        where U  = P(m)*inv(U(m))* ... *P(1)*inv(U(1))
423*        and   U^H = inv(U^H(1))*P(1)* ... *inv(U^H(m))*P(m)
424*
425         IF( LSAME( UPLO, 'U' ) ) THEN
426*
427*           Loop backward applying the transformations.
428*
429            K = N
430   70       IF( K.LT.1 )
431     $         GO TO 90
432*
433*           1 x 1 pivot block.
434*
435            IF( IPIV( K ).GT.0 ) THEN
436               IF( K.GT.1 ) THEN
437*
438*                 Interchange if P(K) != I.
439*
440                  KP = IPIV( K )
441                  IF( KP.NE.K )
442     $               CALL CSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
443*
444*                 Apply the transformation
445*                    y = y - B' conjg(x),
446*                 where x is a column of A and y is a row of B.
447*
448                  CALL CLACGV( NRHS, B( K, 1 ), LDB )
449                  CALL CGEMV( 'Conjugate', K-1, NRHS, CONE, B, LDB,
450     $                        A( 1, K ), 1, CONE, B( K, 1 ), LDB )
451                  CALL CLACGV( NRHS, B( K, 1 ), LDB )
452               END IF
453               IF( NOUNIT )
454     $            CALL CSCAL( NRHS, A( K, K ), B( K, 1 ), LDB )
455               K = K - 1
456*
457*           2 x 2 pivot block.
458*
459            ELSE
460               IF( K.GT.2 ) THEN
461*
462*                 Swap the second of pair with Pth
463*
464                  KP = ABS( IPIV( K ) )
465                  IF( KP.NE.K )
466     $               CALL CSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
467*
468*                 Now swap the first of pair with IMAX(r)th
469*
470                  KP = ABS( IPIV( K-1 ) )
471                  IF( KP.NE.K-1 )
472     $               CALL CSWAP( NRHS, B( K-1, 1 ), LDB, B( KP, 1 ),
473     $                           LDB )
474*
475*                 Apply the transformations
476*                    y = y - B' conjg(x),
477*                 where x is a block column of A and y is a block
478*                 row of B.
479*
480                  CALL CLACGV( NRHS, B( K, 1 ), LDB )
481                  CALL CGEMV( 'Conjugate', K-2, NRHS, CONE, B, LDB,
482     $                        A( 1, K ), 1, CONE, B( K, 1 ), LDB )
483                  CALL CLACGV( NRHS, B( K, 1 ), LDB )
484*
485                  CALL CLACGV( NRHS, B( K-1, 1 ), LDB )
486                  CALL CGEMV( 'Conjugate', K-2, NRHS, CONE, B, LDB,
487     $                        A( 1, K-1 ), 1, CONE, B( K-1, 1 ), LDB )
488                  CALL CLACGV( NRHS, B( K-1, 1 ), LDB )
489               END IF
490*
491*              Multiply by the diagonal block if non-unit.
492*
493               IF( NOUNIT ) THEN
494                  D11 = A( K-1, K-1 )
495                  D22 = A( K, K )
496                  D12 = A( K-1, K )
497                  D21 = CONJG( D12 )
498                  DO 80 J = 1, NRHS
499                     T1 = B( K-1, J )
500                     T2 = B( K, J )
501                     B( K-1, J ) = D11*T1 + D12*T2
502                     B( K, J ) = D21*T1 + D22*T2
503   80             CONTINUE
504               END IF
505               K = K - 2
506            END IF
507            GO TO 70
508   90       CONTINUE
509*
510*        Form  B := L^H*B
511*        where L  = P(1)*inv(L(1))* ... *P(m)*inv(L(m))
512*        and   L^H = inv(L^H(m))*P(m)* ... *inv(L^H(1))*P(1)
513*
514         ELSE
515*
516*           Loop forward applying the L-transformations.
517*
518            K = 1
519  100       CONTINUE
520            IF( K.GT.N )
521     $         GO TO 120
522*
523*           1 x 1 pivot block
524*
525            IF( IPIV( K ).GT.0 ) THEN
526               IF( K.LT.N ) THEN
527*
528*                 Interchange if P(K) != I.
529*
530                  KP = IPIV( K )
531                  IF( KP.NE.K )
532     $               CALL CSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
533*
534*                 Apply the transformation
535*
536                  CALL CLACGV( NRHS, B( K, 1 ), LDB )
537                  CALL CGEMV( 'Conjugate', N-K, NRHS, CONE, B( K+1, 1 ),
538     $                       LDB, A( K+1, K ), 1, CONE, B( K, 1 ), LDB )
539                  CALL CLACGV( NRHS, B( K, 1 ), LDB )
540               END IF
541               IF( NOUNIT )
542     $            CALL CSCAL( NRHS, A( K, K ), B( K, 1 ), LDB )
543               K = K + 1
544*
545*           2 x 2 pivot block.
546*
547            ELSE
548               IF( K.LT.N-1 ) THEN
549*
550*                 Swap the first of pair with Pth
551*
552                  KP = ABS( IPIV( K ) )
553                  IF( KP.NE.K )
554     $               CALL CSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
555*
556*                 Now swap the second of pair with IMAX(r)th
557*
558                  KP = ABS( IPIV( K+1 ) )
559                  IF( KP.NE.K+1 )
560     $               CALL CSWAP( NRHS, B( K+1, 1 ), LDB, B( KP, 1 ),
561     $                           LDB )
562*
563*                 Apply the transformation
564*
565                  CALL CLACGV( NRHS, B( K+1, 1 ), LDB )
566                  CALL CGEMV( 'Conjugate', N-K-1, NRHS, CONE,
567     $                        B( K+2, 1 ), LDB, A( K+2, K+1 ), 1, CONE,
568     $                        B( K+1, 1 ), LDB )
569                  CALL CLACGV( NRHS, B( K+1, 1 ), LDB )
570*
571                  CALL CLACGV( NRHS, B( K, 1 ), LDB )
572                  CALL CGEMV( 'Conjugate', N-K-1, NRHS, CONE,
573     $                        B( K+2, 1 ), LDB, A( K+2, K ), 1, CONE,
574     $                        B( K, 1 ), LDB )
575                  CALL CLACGV( NRHS, B( K, 1 ), LDB )
576               END IF
577*
578*              Multiply by the diagonal block if non-unit.
579*
580               IF( NOUNIT ) THEN
581                  D11 = A( K, K )
582                  D22 = A( K+1, K+1 )
583                  D21 = A( K+1, K )
584                  D12 = CONJG( D21 )
585                  DO 110 J = 1, NRHS
586                     T1 = B( K, J )
587                     T2 = B( K+1, J )
588                     B( K, J ) = D11*T1 + D12*T2
589                     B( K+1, J ) = D21*T1 + D22*T2
590  110             CONTINUE
591               END IF
592               K = K + 2
593            END IF
594            GO TO 100
595  120       CONTINUE
596         END IF
597*
598      END IF
599      RETURN
600*
601*     End of CLAVHE_ROOK
602*
603      END
604