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