161
162
163
164
165
166 IMPLICIT NONE
167
168
169 CHARACTER SIDE, TRANS
170 INTEGER M, N, N1, N2, LDQ, LDC, LWORK, INFO
171
172
173 DOUBLE PRECISION Q( LDQ, * ), C( LDC, * ), WORK( * )
174
175
176
177
178
179 DOUBLE PRECISION ONE
180 parameter( one = 1.0d+0 )
181
182
183 LOGICAL LEFT, LQUERY, NOTRAN
184 INTEGER I, LDWORK, LEN, LWKOPT, NB, NQ, NW
185
186
187 LOGICAL LSAME
189
190
192
193
194 INTRINSIC dble, max, min
195
196
197
198
199
200 info = 0
201 left =
lsame( side,
'L' )
202 notran =
lsame( trans,
'N' )
203 lquery = ( lwork.EQ.-1 )
204
205
206
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
250
251 IF( m.EQ.0 .OR. n.EQ.0 ) THEN
252 work( 1 ) = 1
253 RETURN
254 END IF
255
256
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
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
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
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
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
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
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
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
331
332 CALL dgemm(
'Transpose',
'No Transpose', n2, len, n1,
333 $ one, q, ldq, c( 1, i ), ldc, one, work,
334 $ ldwork )
335
336
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
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
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
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
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
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
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
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
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
413
414 CALL dgemm(
'No Transpose',
'Transpose', len, n1, n2,
415 $ one, c( i, 1 ), ldc, q, ldq, one, work,
416 $ ldwork )
417
418
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
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
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
444
subroutine xerbla(srname, info)
subroutine dgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
DGEMM
subroutine dlacpy(uplo, m, n, a, lda, b, ldb)
DLACPY copies all or part of one two-dimensional array to another.
logical function lsame(ca, cb)
LSAME
subroutine dtrmm(side, uplo, transa, diag, m, n, alpha, a, lda, b, ldb)
DTRMM