LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches

◆ dorm22()

subroutine dorm22 ( character side,
character trans,
integer m,
integer n,
integer n1,
integer n2,
double precision, dimension( ldq, * ) q,
integer ldq,
double precision, dimension( ldc, * ) c,
integer ldc,
double precision, dimension( * ) work,
integer lwork,
integer info )

DORM22 multiplies a general matrix by a banded orthogonal matrix.

Download DORM22 + dependencies [TGZ] [ZIP] [TXT]

Purpose
!>
!>
!>  DORM22 overwrites the general real M-by-N matrix C with
!>
!>                  SIDE = 'L'     SIDE = 'R'
!>  TRANS = 'N':      Q * C          C * Q
!>  TRANS = 'T':      Q**T * C       C * Q**T
!>
!>  where Q is a real orthogonal matrix of order NQ, with NQ = M if
!>  SIDE = 'L' and NQ = N if SIDE = 'R'.
!>  The orthogonal matrix Q processes a 2-by-2 block structure
!>
!>         [  Q11  Q12  ]
!>     Q = [            ]
!>         [  Q21  Q22  ],
!>
!>  where Q12 is an N1-by-N1 lower triangular matrix and Q21 is an
!>  N2-by-N2 upper triangular matrix.
!> 
Parameters
[in]SIDE
!>          SIDE is CHARACTER*1
!>          = 'L': apply Q or Q**T from the Left;
!>          = 'R': apply Q or Q**T from the Right.
!> 
[in]TRANS
!>          TRANS is CHARACTER*1
!>          = 'N':  apply Q (No transpose);
!>          = 'C':  apply Q**T (Conjugate transpose).
!> 
[in]M
!>          M is INTEGER
!>          The number of rows of the matrix C. M >= 0.
!> 
[in]N
!>          N is INTEGER
!>          The number of columns of the matrix C. N >= 0.
!> 
[in]N1
[in]N2
!>          N1 is INTEGER
!>          N2 is INTEGER
!>          The dimension of Q12 and Q21, respectively. N1, N2 >= 0.
!>          The following requirement must be satisfied:
!>          N1 + N2 = M if SIDE = 'L' and N1 + N2 = N if SIDE = 'R'.
!> 
[in]Q
!>          Q is DOUBLE PRECISION array, dimension
!>                                       (LDQ,M) if SIDE = 'L'
!>                                       (LDQ,N) if SIDE = 'R'
!> 
[in]LDQ
!>          LDQ is INTEGER
!>          The leading dimension of the array Q.
!>          LDQ >= max(1,M) if SIDE = 'L'; LDQ >= max(1,N) if SIDE = 'R'.
!> 
[in,out]C
!>          C is DOUBLE PRECISION array, dimension (LDC,N)
!>          On entry, the M-by-N matrix C.
!>          On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q.
!> 
[in]LDC
!>          LDC is INTEGER
!>          The leading dimension of the array C. LDC >= max(1,M).
!> 
[out]WORK
!>          WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK))
!>          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
!> 
[in]LWORK
!>          LWORK is INTEGER
!>          The dimension of the array WORK.
!>          If SIDE = 'L', LWORK >= max(1,N);
!>          if SIDE = 'R', LWORK >= max(1,M).
!>          For optimum performance LWORK >= M*N.
!>
!>          If LWORK = -1, then a workspace query is assumed; the routine
!>          only calculates the optimal size of the WORK array, returns
!>          this value as the first entry of the WORK array, and no error
!>          message related to LWORK is issued by XERBLA.
!> 
[out]INFO
!>          INFO is INTEGER
!>          = 0:  successful exit
!>          < 0:  if INFO = -i, the i-th argument had an illegal value
!> 
Author
Univ. of Tennessee
Univ. of California Berkeley
Univ. of Colorado Denver
NAG Ltd.

Definition at line 159 of file dorm22.f.

161*
162* -- LAPACK computational routine --
163* -- LAPACK is a software package provided by Univ. of Tennessee, --
164* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
165*
166 IMPLICIT NONE
167*
168* .. Scalar Arguments ..
169 CHARACTER SIDE, TRANS
170 INTEGER M, N, N1, N2, LDQ, LDC, LWORK, INFO
171* ..
172* .. Array Arguments ..
173 DOUBLE PRECISION Q( LDQ, * ), C( LDC, * ), WORK( * )
174* ..
175*
176* =====================================================================
177*
178* .. Parameters ..
179 DOUBLE PRECISION ONE
180 parameter( one = 1.0d+0 )
181*
182* .. Local Scalars ..
183 LOGICAL LEFT, LQUERY, NOTRAN
184 INTEGER I, LDWORK, LEN, LWKOPT, NB, NQ, NW
185* ..
186* .. External Functions ..
187 LOGICAL LSAME
188 EXTERNAL lsame
189* ..
190* .. External Subroutines ..
191 EXTERNAL dgemm, dlacpy, dtrmm, xerbla
192* ..
193* .. Intrinsic Functions ..
194 INTRINSIC dble, max, min
195* ..
196* .. Executable Statements ..
197*
198* Test the input arguments
199*
200 info = 0
201 left = lsame( side, 'L' )
202 notran = lsame( trans, 'N' )
203 lquery = ( lwork.EQ.-1 )
204*
205* NQ is the order of Q;
206* NW is the minimum dimension of WORK.
207*
208 IF( left ) THEN
209 nq = m
210 ELSE
211 nq = n
212 END IF
213 nw = nq
214 IF( n1.EQ.0 .OR. n2.EQ.0 ) nw = 1
215 IF( .NOT.left .AND. .NOT.lsame( side, 'R' ) ) THEN
216 info = -1
217 ELSE IF( .NOT.lsame( trans, 'N' ) .AND.
218 $ .NOT.lsame( trans, 'T' ) )
219 $ THEN
220 info = -2
221 ELSE IF( m.LT.0 ) THEN
222 info = -3
223 ELSE IF( n.LT.0 ) THEN
224 info = -4
225 ELSE IF( n1.LT.0 .OR. n1+n2.NE.nq ) THEN
226 info = -5
227 ELSE IF( n2.LT.0 ) THEN
228 info = -6
229 ELSE IF( ldq.LT.max( 1, nq ) ) THEN
230 info = -8
231 ELSE IF( ldc.LT.max( 1, m ) ) THEN
232 info = -10
233 ELSE IF( lwork.LT.nw .AND. .NOT.lquery ) THEN
234 info = -12
235 END IF
236*
237 IF( info.EQ.0 ) THEN
238 lwkopt = m*n
239 work( 1 ) = dble( lwkopt )
240 END IF
241*
242 IF( info.NE.0 ) THEN
243 CALL xerbla( 'DORM22', -info )
244 RETURN
245 ELSE IF( lquery ) THEN
246 RETURN
247 END IF
248*
249* Quick return if possible
250*
251 IF( m.EQ.0 .OR. n.EQ.0 ) THEN
252 work( 1 ) = 1
253 RETURN
254 END IF
255*
256* Degenerate cases (N1 = 0 or N2 = 0) are handled using DTRMM.
257*
258 IF( n1.EQ.0 ) THEN
259 CALL dtrmm( side, 'Upper', trans, 'Non-Unit', m, n, one,
260 $ q, ldq, c, ldc )
261 work( 1 ) = one
262 RETURN
263 ELSE IF( n2.EQ.0 ) THEN
264 CALL dtrmm( side, 'Lower', trans, 'Non-Unit', m, n, one,
265 $ q, ldq, c, ldc )
266 work( 1 ) = one
267 RETURN
268 END IF
269*
270* Compute the largest chunk size available from the workspace.
271*
272 nb = max( 1, min( lwork, lwkopt ) / nq )
273*
274 IF( left ) THEN
275 IF( notran ) THEN
276 DO i = 1, n, nb
277 len = min( nb, n-i+1 )
278 ldwork = m
279*
280* Multiply bottom part of C by Q12.
281*
282 CALL dlacpy( 'All', n1, len, c( n2+1, i ), ldc, work,
283 $ ldwork )
284 CALL dtrmm( 'Left', 'Lower', 'No Transpose',
285 $ 'Non-Unit',
286 $ n1, len, one, q( 1, n2+1 ), ldq, work,
287 $ ldwork )
288*
289* Multiply top part of C by Q11.
290*
291 CALL dgemm( 'No Transpose', 'No Transpose', n1, len,
292 $ n2,
293 $ one, q, ldq, c( 1, i ), ldc, one, work,
294 $ ldwork )
295*
296* Multiply top part of C by Q21.
297*
298 CALL dlacpy( 'All', n2, len, c( 1, i ), ldc,
299 $ work( n1+1 ), ldwork )
300 CALL dtrmm( 'Left', 'Upper', 'No Transpose',
301 $ 'Non-Unit',
302 $ n2, len, one, q( n1+1, 1 ), ldq,
303 $ work( n1+1 ), ldwork )
304*
305* Multiply bottom part of C by Q22.
306*
307 CALL dgemm( 'No Transpose', 'No Transpose', n2, len,
308 $ n1,
309 $ one, q( n1+1, n2+1 ), ldq, c( n2+1, i ), ldc,
310 $ one, work( n1+1 ), ldwork )
311*
312* Copy everything back.
313*
314 CALL dlacpy( 'All', m, len, work, ldwork, c( 1, i ),
315 $ ldc )
316 END DO
317 ELSE
318 DO i = 1, n, nb
319 len = min( nb, n-i+1 )
320 ldwork = m
321*
322* Multiply bottom part of C by Q21**T.
323*
324 CALL dlacpy( 'All', n2, len, c( n1+1, i ), ldc, work,
325 $ ldwork )
326 CALL dtrmm( 'Left', 'Upper', 'Transpose', 'Non-Unit',
327 $ n2, len, one, q( n1+1, 1 ), ldq, work,
328 $ ldwork )
329*
330* Multiply top part of C by Q11**T.
331*
332 CALL dgemm( 'Transpose', 'No Transpose', n2, len, n1,
333 $ one, q, ldq, c( 1, i ), ldc, one, work,
334 $ ldwork )
335*
336* Multiply top part of C by Q12**T.
337*
338 CALL dlacpy( 'All', n1, len, c( 1, i ), ldc,
339 $ work( n2+1 ), ldwork )
340 CALL dtrmm( 'Left', 'Lower', 'Transpose', 'Non-Unit',
341 $ n1, len, one, q( 1, n2+1 ), ldq,
342 $ work( n2+1 ), ldwork )
343*
344* Multiply bottom part of C by Q22**T.
345*
346 CALL dgemm( 'Transpose', 'No Transpose', n1, len, n2,
347 $ one, q( n1+1, n2+1 ), ldq, c( n1+1, i ), ldc,
348 $ one, work( n2+1 ), ldwork )
349*
350* Copy everything back.
351*
352 CALL dlacpy( 'All', m, len, work, ldwork, c( 1, i ),
353 $ ldc )
354 END DO
355 END IF
356 ELSE
357 IF( notran ) THEN
358 DO i = 1, m, nb
359 len = min( nb, m-i+1 )
360 ldwork = len
361*
362* Multiply right part of C by Q21.
363*
364 CALL dlacpy( 'All', len, n2, c( i, n1+1 ), ldc, work,
365 $ ldwork )
366 CALL dtrmm( 'Right', 'Upper', 'No Transpose',
367 $ 'Non-Unit',
368 $ len, n2, one, q( n1+1, 1 ), ldq, work,
369 $ ldwork )
370*
371* Multiply left part of C by Q11.
372*
373 CALL dgemm( 'No Transpose', 'No Transpose', len, n2,
374 $ n1,
375 $ one, c( i, 1 ), ldc, q, ldq, one, work,
376 $ ldwork )
377*
378* Multiply left part of C by Q12.
379*
380 CALL dlacpy( 'All', len, n1, c( i, 1 ), ldc,
381 $ work( 1 + n2*ldwork ), ldwork )
382 CALL dtrmm( 'Right', 'Lower', 'No Transpose',
383 $ 'Non-Unit',
384 $ len, n1, one, q( 1, n2+1 ), ldq,
385 $ work( 1 + n2*ldwork ), ldwork )
386*
387* Multiply right part of C by Q22.
388*
389 CALL dgemm( 'No Transpose', 'No Transpose', len, n1,
390 $ n2,
391 $ one, c( i, n1+1 ), ldc, q( n1+1, n2+1 ), ldq,
392 $ one, work( 1 + n2*ldwork ), ldwork )
393*
394* Copy everything back.
395*
396 CALL dlacpy( 'All', len, n, work, ldwork, c( i, 1 ),
397 $ ldc )
398 END DO
399 ELSE
400 DO i = 1, m, nb
401 len = min( nb, m-i+1 )
402 ldwork = len
403*
404* Multiply right part of C by Q12**T.
405*
406 CALL dlacpy( 'All', len, n1, c( i, n2+1 ), ldc, work,
407 $ ldwork )
408 CALL dtrmm( 'Right', 'Lower', 'Transpose', 'Non-Unit',
409 $ len, n1, one, q( 1, n2+1 ), ldq, work,
410 $ ldwork )
411*
412* Multiply left part of C by Q11**T.
413*
414 CALL dgemm( 'No Transpose', 'Transpose', len, n1, n2,
415 $ one, c( i, 1 ), ldc, q, ldq, one, work,
416 $ ldwork )
417*
418* Multiply left part of C by Q21**T.
419*
420 CALL dlacpy( 'All', len, n2, c( i, 1 ), ldc,
421 $ work( 1 + n1*ldwork ), ldwork )
422 CALL dtrmm( 'Right', 'Upper', 'Transpose', 'Non-Unit',
423 $ len, n2, one, q( n1+1, 1 ), ldq,
424 $ work( 1 + n1*ldwork ), ldwork )
425*
426* Multiply right part of C by Q22**T.
427*
428 CALL dgemm( 'No Transpose', 'Transpose', len, n2, n1,
429 $ one, c( i, n2+1 ), ldc, q( n1+1, n2+1 ), ldq,
430 $ one, work( 1 + n1*ldwork ), ldwork )
431*
432* Copy everything back.
433*
434 CALL dlacpy( 'All', len, n, work, ldwork, c( i, 1 ),
435 $ ldc )
436 END DO
437 END IF
438 END IF
439*
440 work( 1 ) = dble( lwkopt )
441 RETURN
442*
443* End of DORM22
444*
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine dgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
DGEMM
Definition dgemm.f:188
subroutine dlacpy(uplo, m, n, a, lda, b, ldb)
DLACPY copies all or part of one two-dimensional array to another.
Definition dlacpy.f:101
logical function lsame(ca, cb)
LSAME
Definition lsame.f:48
subroutine dtrmm(side, uplo, transa, diag, m, n, alpha, a, lda, b, ldb)
DTRMM
Definition dtrmm.f:177
Here is the call graph for this function:
Here is the caller graph for this function: