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      REAL               Q( LDQ, * ), C( LDC, * ), WORK( * )
  174
  175
  176
  177
  178
  179      REAL               ONE
  180      parameter( one = 1.0e+0 )
  181
  182
  183      LOGICAL            LEFT, LQUERY, NOTRAN
  184      INTEGER            I, LDWORK, LEN, LWKOPT, NB, NQ, NW
  185
  186
  187      LOGICAL            LSAME
  188      REAL               SROUNDUP_LWORK
  190
  191
  193
  194
  195      INTRINSIC          max, min
  196
  197
  198
  199
  200
  201      info = 0
  202      left = 
lsame( side, 
'L' )
 
  203      notran = 
lsame( trans, 
'N' )
 
  204      lquery = ( lwork.EQ.-1 )
  205
  206
  207
  208
  209      IF( left ) THEN
  210         nq = m
  211      ELSE
  212         nq = n
  213      END IF
  214      nw = nq
  215      IF( n1.EQ.0 .OR. n2.EQ.0 ) nw = 1
  216      IF( .NOT.left .AND. .NOT.
lsame( side, 
'R' ) ) 
THEN 
  217         info = -1
  218      ELSE IF( .NOT.
lsame( trans, 
'N' ) .AND.
 
  219     $         .NOT.
lsame( trans, 
'T' ) )
 
  220     $          THEN
  221         info = -2
  222      ELSE IF( m.LT.0 ) THEN
  223         info = -3
  224      ELSE IF( n.LT.0 ) THEN
  225         info = -4
  226      ELSE IF( n1.LT.0 .OR. n1+n2.NE.nq ) THEN
  227         info = -5
  228      ELSE IF( n2.LT.0 ) THEN
  229         info = -6
  230      ELSE IF( ldq.LT.max( 1, nq ) ) THEN
  231         info = -8
  232      ELSE IF( ldc.LT.max( 1, m ) ) THEN
  233         info = -10
  234      ELSE IF( lwork.LT.nw .AND. .NOT.lquery ) THEN
  235         info = -12
  236      END IF
  237
  238      IF( info.EQ.0 ) THEN
  239         lwkopt = m*n
  241      END IF
  242
  243      IF( info.NE.0 ) THEN
  244         CALL xerbla( 
'SORM22', -info )
 
  245         RETURN
  246      ELSE IF( lquery ) THEN
  247         RETURN
  248      END IF
  249
  250
  251
  252      IF( m.EQ.0 .OR. n.EQ.0 ) THEN
  253         work( 1 ) = 1
  254         RETURN
  255      END IF
  256
  257
  258
  259      IF( n1.EQ.0 ) THEN
  260         CALL strmm( side, 
'Upper', trans, 
'Non-Unit', m, n, one,
 
  261     $               q, ldq, c, ldc )
  262         work( 1 ) = one
  263         RETURN
  264      ELSE IF( n2.EQ.0 ) THEN
  265         CALL strmm( side, 
'Lower', trans, 
'Non-Unit', m, n, one,
 
  266     $               q, ldq, c, ldc )
  267         work( 1 ) = one
  268         RETURN
  269      END IF
  270
  271
  272
  273      nb = max( 1, min( lwork, lwkopt ) / nq )
  274
  275      IF( left ) THEN
  276         IF( notran ) THEN
  277            DO i = 1, n, nb
  278               len = min( nb, n-i+1 )
  279               ldwork = m
  280
  281
  282
  283               CALL slacpy( 
'All', n1, len, c( n2+1, i ), ldc, work,
 
  284     $                      ldwork )
  285               CALL strmm( 
'Left', 
'Lower', 
'No Transpose',
 
  286     $                     'Non-Unit',
  287     $                     n1, len, one, q( 1, n2+1 ), ldq, work,
  288     $                     ldwork )
  289
  290
  291
  292               CALL sgemm( 
'No Transpose', 
'No Transpose', n1, len,
 
  293     $                     n2,
  294     $                     one, q, ldq, c( 1, i ), ldc, one, work,
  295     $                     ldwork )
  296
  297
  298
  299               CALL slacpy( 
'All', n2, len, c( 1, i ), ldc,
 
  300     $                      work( n1+1 ), ldwork )
  301               CALL strmm( 
'Left', 
'Upper', 
'No Transpose',
 
  302     $                     'Non-Unit',
  303     $                     n2, len, one, q( n1+1, 1 ), ldq,
  304     $                     work( n1+1 ), ldwork )
  305
  306
  307
  308               CALL sgemm( 
'No Transpose', 
'No Transpose', n2, len,
 
  309     $                     n1,
  310     $                     one, q( n1+1, n2+1 ), ldq, c( n2+1, i ), ldc,
  311     $                     one, work( n1+1 ), ldwork )
  312
  313
  314
  315               CALL slacpy( 
'All', m, len, work, ldwork, c( 1, i ),
 
  316     $                      ldc )
  317            END DO
  318         ELSE
  319            DO i = 1, n, nb
  320               len = min( nb, n-i+1 )
  321               ldwork = m
  322
  323
  324
  325               CALL slacpy( 
'All', n2, len, c( n1+1, i ), ldc, work,
 
  326     $                      ldwork )
  327               CALL strmm( 
'Left', 
'Upper', 
'Transpose', 
'Non-Unit',
 
  328     $                     n2, len, one, q( n1+1, 1 ), ldq, work,
  329     $                     ldwork )
  330
  331
  332
  333               CALL sgemm( 
'Transpose', 
'No Transpose', n2, len, n1,
 
  334     $                     one, q, ldq, c( 1, i ), ldc, one, work,
  335     $                     ldwork )
  336
  337
  338
  339               CALL slacpy( 
'All', n1, len, c( 1, i ), ldc,
 
  340     $                      work( n2+1 ), ldwork )
  341               CALL strmm( 
'Left', 
'Lower', 
'Transpose', 
'Non-Unit',
 
  342     $                     n1, len, one, q( 1, n2+1 ), ldq,
  343     $                     work( n2+1 ), ldwork )
  344
  345
  346
  347               CALL sgemm( 
'Transpose', 
'No Transpose', n1, len, n2,
 
  348     $                     one, q( n1+1, n2+1 ), ldq, c( n1+1, i ), ldc,
  349     $                     one, work( n2+1 ), ldwork )
  350
  351
  352
  353               CALL slacpy( 
'All', m, len, work, ldwork, c( 1, i ),
 
  354     $                      ldc )
  355            END DO
  356         END IF
  357      ELSE
  358         IF( notran ) THEN
  359            DO i = 1, m, nb
  360               len = min( nb, m-i+1 )
  361               ldwork = len
  362
  363
  364
  365               CALL slacpy( 
'All', len, n2, c( i, n1+1 ), ldc, work,
 
  366     $                      ldwork )
  367               CALL strmm( 
'Right', 
'Upper', 
'No Transpose',
 
  368     $                     'Non-Unit',
  369     $                     len, n2, one, q( n1+1, 1 ), ldq, work,
  370     $                     ldwork )
  371
  372
  373
  374               CALL sgemm( 
'No Transpose', 
'No Transpose', len, n2,
 
  375     $                     n1,
  376     $                     one, c( i, 1 ), ldc, q, ldq, one, work,
  377     $                     ldwork )
  378
  379
  380
  381               CALL slacpy( 
'All', len, n1, c( i, 1 ), ldc,
 
  382     $                      work( 1 + n2*ldwork ), ldwork )
  383               CALL strmm( 
'Right', 
'Lower', 
'No Transpose',
 
  384     $                     'Non-Unit',
  385     $                     len, n1, one, q( 1, n2+1 ), ldq,
  386     $                     work( 1 + n2*ldwork ), ldwork )
  387
  388
  389
  390               CALL sgemm( 
'No Transpose', 
'No Transpose', len, n1,
 
  391     $                     n2,
  392     $                     one, c( i, n1+1 ), ldc, q( n1+1, n2+1 ), ldq,
  393     $                     one, work( 1 + n2*ldwork ), ldwork )
  394
  395
  396
  397               CALL slacpy( 
'All', len, n, work, ldwork, c( i, 1 ),
 
  398     $                      ldc )
  399            END DO
  400         ELSE
  401            DO i = 1, m, nb
  402               len = min( nb, m-i+1 )
  403               ldwork = len
  404
  405
  406
  407               CALL slacpy( 
'All', len, n1, c( i, n2+1 ), ldc, work,
 
  408     $                      ldwork )
  409               CALL strmm( 
'Right', 
'Lower', 
'Transpose', 
'Non-Unit',
 
  410     $                     len, n1, one, q( 1, n2+1 ), ldq, work,
  411     $                     ldwork )
  412
  413
  414
  415               CALL sgemm( 
'No Transpose', 
'Transpose', len, n1, n2,
 
  416     $                     one, c( i, 1 ), ldc, q, ldq, one, work,
  417     $                     ldwork )
  418
  419
  420
  421               CALL slacpy( 
'All', len, n2, c( i, 1 ), ldc,
 
  422     $                      work( 1 + n1*ldwork ), ldwork )
  423               CALL strmm( 
'Right', 
'Upper', 
'Transpose', 
'Non-Unit',
 
  424     $                     len, n2, one, q( n1+1, 1 ), ldq,
  425     $                     work( 1 + n1*ldwork ), ldwork )
  426
  427
  428
  429               CALL sgemm( 
'No Transpose', 
'Transpose', len, n2, n1,
 
  430     $                     one, c( i, n2+1 ), ldc, q( n1+1, n2+1 ), ldq,
  431     $                     one, work( 1 + n1*ldwork ), ldwork )
  432
  433
  434
  435               CALL slacpy( 
'All', len, n, work, ldwork, c( i, 1 ),
 
  436     $                      ldc )
  437            END DO
  438         END IF
  439      END IF
  440
  442      RETURN
  443
  444
  445
subroutine xerbla(srname, info)
subroutine sgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
SGEMM
subroutine slacpy(uplo, m, n, a, lda, b, ldb)
SLACPY copies all or part of one two-dimensional array to another.
logical function lsame(ca, cb)
LSAME
real function sroundup_lwork(lwork)
SROUNDUP_LWORK
subroutine strmm(side, uplo, transa, diag, m, n, alpha, a, lda, b, ldb)
STRMM