196 SUBROUTINE strsyl3( TRANA, TRANB, ISGN, M, N, A, LDA, B, LDB,
197 $ C, LDC, SCALE, IWORK, LIWORK, SWORK,
202 CHARACTER TRANA, TRANB
203 INTEGER INFO, ISGN, LDA, LDB, LDC, M, N,
209 REAL A( LDA, * ), B( LDB, * ), C( LDC, * ),
210 $ swork( ldswork, * )
214 PARAMETER ( ZERO = 0.0e+0, one = 1.0e+0 )
217 LOGICAL NOTRNA, NOTRNB, LQUERY, SKIP
218 INTEGER AWRK, BWRK, I, I1, I2, IINFO, J, J1, J2, JJ,
219 $ k, k1, k2, l, l1, l2, ll, nba, nb, nbb, pc
220 REAL ANRM, BIGNUM, BNRM, CNRM, SCAL, SCALOC,
221 $ SCAMIN, SGN, XNRM, BUF, SMLNUM
224 REAL WNRM( MAX( M, N ) )
229 REAL SLANGE, SLAMCH, SLARMM
230 EXTERNAL slange, slamch, slarmm, ilaenv,
238 INTRINSIC abs, exponent, max, min, real
244 notrna = lsame( trana,
'N' )
245 notrnb = lsame( tranb,
'N' )
249 nb = max(8, ilaenv( 1,
'STRSYL',
'', m, n, -1, -1) )
253 nba = max( 1, (m + nb - 1) / nb )
254 nbb = max( 1, (n + nb - 1) / nb )
259 lquery = ( liwork.EQ.-1 .OR. ldswork.EQ.-1 )
260 iwork( 1 ) = nba + nbb + 2
263 swork( 1, 1 ) = real( max( nba, nbb ) )
264 swork( 2, 1 ) = real( 2 * nbb + nba )
269 IF( .NOT.notrna .AND. .NOT.lsame( trana,
'T' ) .AND. .NOT.
270 $ lsame( trana,
'C' ) )
THEN
272 ELSE IF( .NOT.notrnb .AND. .NOT.lsame( tranb,
'T' ) .AND. .NOT.
273 $ lsame( tranb,
'C' ) )
THEN
275 ELSE IF( isgn.NE.1 .AND. isgn.NE.-1 )
THEN
277 ELSE IF( m.LT.0 )
THEN
279 ELSE IF( n.LT.0 )
THEN
281 ELSE IF( lda.LT.max( 1, m ) )
THEN
283 ELSE IF( ldb.LT.max( 1, n ) )
THEN
285 ELSE IF( ldc.LT.max( 1, m ) )
THEN
287 ELSE IF( .NOT.lquery .AND. liwork.LT.iwork(1) )
THEN
289 ELSE IF( .NOT.lquery .AND. ldswork.LT.max( nba, nbb ) )
THEN
293 CALL xerbla(
'STRSYL3', -info )
295 ELSE IF( lquery )
THEN
302 IF( m.EQ.0 .OR. n.EQ.0 )
308 IF( min( nba, nbb ).EQ.1 .OR. ldswork.LT.max( nba, nbb ) .OR.
309 $ liwork.LT.iwork(1) )
THEN
310 CALL strsyl( trana, tranb, isgn, m, n, a, lda, b, ldb,
311 $ c, ldc, scale, info )
317 smlnum = slamch(
'S' )
318 bignum = one / smlnum
324 iwork( i ) = ( i - 1 ) * nb + 1
326 iwork( nba + 1 ) = m + 1
329 l2 = iwork( k + 1 ) - 1
339 IF( a( l, l+1 ).NE.zero .AND. a( l+1, l ).NE.zero )
THEN
341 IF( l + 1 .EQ. iwork( k + 1 ) )
THEN
342 iwork( k + 1 ) = iwork( k + 1 ) + 1
349 iwork( nba + 1 ) = m + 1
350 IF( iwork( nba ).GE.iwork( nba + 1 ) )
THEN
351 iwork( nba ) = iwork( nba + 1 )
360 iwork( pc + i ) = ( i - 1 ) * nb + 1
362 iwork( pc + nbb + 1 ) = n + 1
365 l2 = iwork( pc + k + 1 ) - 1
375 IF( b( l, l+1 ).NE.zero .AND. b( l+1, l ).NE.zero )
THEN
377 IF( l + 1 .EQ. iwork( pc + k + 1 ) )
THEN
378 iwork( pc + k + 1 ) = iwork( pc + k + 1 ) + 1
385 iwork( pc + nbb + 1 ) = n + 1
386 IF( iwork( pc + nbb ).GE.iwork( pc + nbb + 1 ) )
THEN
387 iwork( pc + nbb ) = iwork( pc + nbb + 1 )
414 swork( k, awrk + l ) = slange(
'I', k2-k1, l2-l1,
415 $ a( k1, l1 ), lda, wnrm )
417 swork( l, awrk + k ) = slange(
'1', k2-k1, l2-l1,
418 $ a( k1, l1 ), lda, wnrm )
425 k2 = iwork( pc + k + 1 )
428 l2 = iwork( pc + l + 1 )
430 swork( k, bwrk + l ) = slange(
'I', k2-k1, l2-l1,
431 $ b( k1, l1 ), ldb, wnrm )
433 swork( l, bwrk + k ) = slange(
'1', k2-k1, l2-l1,
434 $ b( k1, l1 ), ldb, wnrm )
441 IF( notrna .AND. notrnb )
THEN
472 l2 = iwork( pc + l + 1 )
474 CALL strsyl( trana, tranb, isgn, k2-k1, l2-l1,
477 $ c( k1, l1 ), ldc, scaloc, iinfo )
478 info = max( info, iinfo )
480 IF ( scaloc * swork( k, l ) .EQ. zero )
THEN
481 IF( scaloc .EQ. zero )
THEN
489 buf = buf*2.e0**exponent( scaloc )
496 swork( ll, jj ) = min( bignum,
497 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
501 swork( k, l ) = scaloc * swork( k, l )
502 xnrm = slange(
'I', k2-k1, l2-l1, c( k1, l1 ), ldc,
515 cnrm = slange(
'I', i2-i1, l2-l1, c( i1, l1 ),
517 scamin = min( swork( i, l ), swork( k, l ) )
518 cnrm = cnrm * ( scamin / swork( i, l ) )
519 xnrm = xnrm * ( scamin / swork( k, l ) )
520 anrm = swork( i, awrk + k )
521 scaloc = slarmm( anrm, xnrm, cnrm )
522 IF( scaloc * scamin .EQ. zero )
THEN
524 buf = buf*2.e0**exponent( scaloc )
527 swork( ll, jj ) = min( bignum,
528 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
531 scamin = scamin / 2.e0**exponent( scaloc )
532 scaloc = scaloc / 2.e0**exponent( scaloc )
540 scal = ( scamin / swork( k, l ) ) * scaloc
541 IF (scal .NE. one)
THEN
543 CALL sscal( k2-k1, scal, c( k1, jj ), 1)
547 scal = ( scamin / swork( i, l ) ) * scaloc
548 IF (scal .NE. one)
THEN
550 CALL sscal( i2-i1, scal, c( i1, ll ), 1)
556 swork( k, l ) = scamin * scaloc
557 swork( i, l ) = scamin * scaloc
559 CALL sgemm(
'N',
'N', i2-i1, l2-l1, k2-k1, -one,
560 $ a( i1, k1 ), lda, c( k1, l1 ), ldc,
561 $ one, c( i1, l1 ), ldc )
570 j2 = iwork( pc + j + 1 )
575 cnrm = slange(
'I', k2-k1, j2-j1, c( k1, j1 ),
577 scamin = min( swork( k, j ), swork( k, l ) )
578 cnrm = cnrm * ( scamin / swork( k, j ) )
579 xnrm = xnrm * ( scamin / swork( k, l ) )
580 bnrm = swork(l, bwrk + j)
581 scaloc = slarmm( bnrm, xnrm, cnrm )
582 IF( scaloc * scamin .EQ. zero )
THEN
584 buf = buf*2.e0**exponent( scaloc )
587 swork( ll, jj ) = min( bignum,
588 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
591 scamin = scamin / 2.e0**exponent( scaloc )
592 scaloc = scaloc / 2.e0**exponent( scaloc )
600 scal = ( scamin / swork( k, l ) ) * scaloc
601 IF( scal .NE. one )
THEN
603 CALL sscal( k2-k1, scal, c( k1, ll ), 1 )
607 scal = ( scamin / swork( k, j ) ) * scaloc
608 IF( scal .NE. one )
THEN
610 CALL sscal( k2-k1, scal, c( k1, jj ), 1 )
616 swork( k, l ) = scamin * scaloc
617 swork( k, j ) = scamin * scaloc
619 CALL sgemm(
'N',
'N', k2-k1, j2-j1, l2-l1, -sgn,
620 $ c( k1, l1 ), ldc, b( l1, j1 ), ldb,
621 $ one, c( k1, j1 ), ldc )
625 ELSE IF( .NOT.notrna .AND. notrnb )
THEN
656 l2 = iwork( pc + l + 1 )
658 CALL strsyl( trana, tranb, isgn, k2-k1, l2-l1,
661 $ c( k1, l1 ), ldc, scaloc, iinfo )
662 info = max( info, iinfo )
664 IF( scaloc * swork( k, l ) .EQ. zero )
THEN
665 IF( scaloc .EQ. zero )
THEN
673 buf = buf*2.e0**exponent( scaloc )
680 swork( ll, jj ) = min( bignum,
681 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
685 swork( k, l ) = scaloc * swork( k, l )
686 xnrm = slange(
'I', k2-k1, l2-l1, c( k1, l1 ), ldc,
699 cnrm = slange(
'I', i2-i1, l2-l1, c( i1, l1 ),
701 scamin = min( swork( i, l ), swork( k, l ) )
702 cnrm = cnrm * ( scamin / swork( i, l ) )
703 xnrm = xnrm * ( scamin / swork( k, l ) )
704 anrm = swork( i, awrk + k )
705 scaloc = slarmm( anrm, xnrm, cnrm )
706 IF( scaloc * scamin .EQ. zero )
THEN
708 buf = buf*2.e0**exponent( scaloc )
711 swork( ll, jj ) = min( bignum,
712 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
715 scamin = scamin / 2.e0**exponent( scaloc )
716 scaloc = scaloc / 2.e0**exponent( scaloc )
724 scal = ( scamin / swork( k, l ) ) * scaloc
725 IF (scal .NE. one)
THEN
727 CALL sscal( k2-k1, scal, c( k1, ll ), 1 )
731 scal = ( scamin / swork( i, l ) ) * scaloc
732 IF (scal .NE. one)
THEN
734 CALL sscal( i2-i1, scal, c( i1, ll ), 1 )
740 swork( k, l ) = scamin * scaloc
741 swork( i, l ) = scamin * scaloc
743 CALL sgemm(
'T',
'N', i2-i1, l2-l1, k2-k1, -one,
744 $ a( k1, i1 ), lda, c( k1, l1 ), ldc,
745 $ one, c( i1, l1 ), ldc )
753 j2 = iwork( pc + j + 1 )
758 cnrm = slange(
'I', k2-k1, j2-j1, c( k1, j1 ),
760 scamin = min( swork( k, j ), swork( k, l ) )
761 cnrm = cnrm * ( scamin / swork( k, j ) )
762 xnrm = xnrm * ( scamin / swork( k, l ) )
763 bnrm = swork( l, bwrk + j )
764 scaloc = slarmm( bnrm, xnrm, cnrm )
765 IF( scaloc * scamin .EQ. zero )
THEN
767 buf = buf*2.e0**exponent( scaloc )
770 swork( ll, jj ) = min( bignum,
771 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
774 scamin = scamin / 2.e0**exponent( scaloc )
775 scaloc = scaloc / 2.e0**exponent( scaloc )
783 scal = ( scamin / swork( k, l ) ) * scaloc
784 IF( scal .NE. one )
THEN
786 CALL sscal( k2-k1, scal, c( k1, ll ), 1 )
790 scal = ( scamin / swork( k, j ) ) * scaloc
791 IF( scal .NE. one )
THEN
793 CALL sscal( k2-k1, scal, c( k1, jj ), 1 )
799 swork( k, l ) = scamin * scaloc
800 swork( k, j ) = scamin * scaloc
802 CALL sgemm(
'N',
'N', k2-k1, j2-j1, l2-l1, -sgn,
803 $ c( k1, l1 ), ldc, b( l1, j1 ), ldb,
804 $ one, c( k1, j1 ), ldc )
808 ELSE IF( .NOT.notrna .AND. .NOT.notrnb )
THEN
839 l2 = iwork( pc + l + 1 )
841 CALL strsyl( trana, tranb, isgn, k2-k1, l2-l1,
844 $ c( k1, l1 ), ldc, scaloc, iinfo )
845 info = max( info, iinfo )
847 IF( scaloc * swork( k, l ) .EQ. zero )
THEN
848 IF( scaloc .EQ. zero )
THEN
856 buf = buf*2.e0**exponent( scaloc )
863 swork( ll, jj ) = min( bignum,
864 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
868 swork( k, l ) = scaloc * swork( k, l )
869 xnrm = slange(
'I', k2-k1, l2-l1, c( k1, l1 ), ldc,
882 cnrm = slange(
'I', i2-i1, l2-l1, c( i1, l1 ),
884 scamin = min( swork( i, l ), swork( k, l ) )
885 cnrm = cnrm * ( scamin / swork( i, l ) )
886 xnrm = xnrm * ( scamin / swork( k, l ) )
887 anrm = swork( i, awrk + k )
888 scaloc = slarmm( anrm, xnrm, cnrm )
889 IF( scaloc * scamin .EQ. zero )
THEN
891 buf = buf*2.e0**exponent( scaloc )
894 swork( ll, jj ) = min( bignum,
895 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
898 scamin = scamin / 2.e0**exponent( scaloc )
899 scaloc = scaloc / 2.e0**exponent( scaloc )
907 scal = ( scamin / swork( k, l ) ) * scaloc
908 IF (scal .NE. one)
THEN
910 CALL sscal( k2-k1, scal, c( k1, ll ), 1 )
914 scal = ( scamin / swork( i, l ) ) * scaloc
915 IF (scal .NE. one)
THEN
917 CALL sscal( i2-i1, scal, c( i1, ll ), 1 )
923 swork( k, l ) = scamin * scaloc
924 swork( i, l ) = scamin * scaloc
926 CALL sgemm(
'T',
'N', i2-i1, l2-l1, k2-k1, -one,
927 $ a( k1, i1 ), lda, c( k1, l1 ), ldc,
928 $ one, c( i1, l1 ), ldc )
936 j2 = iwork( pc + j + 1 )
941 cnrm = slange(
'I', k2-k1, j2-j1, c( k1, j1 ),
943 scamin = min( swork( k, j ), swork( k, l ) )
944 cnrm = cnrm * ( scamin / swork( k, j ) )
945 xnrm = xnrm * ( scamin / swork( k, l ) )
946 bnrm = swork( l, bwrk + j )
947 scaloc = slarmm( bnrm, xnrm, cnrm )
948 IF( scaloc * scamin .EQ. zero )
THEN
950 buf = buf*2.e0**exponent( scaloc )
953 swork( ll, jj ) = min( bignum,
954 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
957 scamin = scamin / 2.e0**exponent( scaloc )
958 scaloc = scaloc / 2.e0**exponent( scaloc )
966 scal = ( scamin / swork( k, l ) ) * scaloc
967 IF( scal .NE. one )
THEN
969 CALL sscal( k2-k1, scal, c( k1, ll ), 1)
973 scal = ( scamin / swork( k, j ) ) * scaloc
974 IF( scal .NE. one )
THEN
976 CALL sscal( k2-k1, scal, c( k1, jj ), 1 )
982 swork( k, l ) = scamin * scaloc
983 swork( k, j ) = scamin * scaloc
985 CALL sgemm(
'N',
'T', k2-k1, j2-j1, l2-l1, -sgn,
986 $ c( k1, l1 ), ldc, b( j1, l1 ), ldb,
987 $ one, c( k1, j1 ), ldc )
991 ELSE IF( notrna .AND. .NOT.notrnb )
THEN
1021 l1 = iwork( pc + l )
1022 l2 = iwork( pc + l + 1 )
1024 CALL strsyl( trana, tranb, isgn, k2-k1, l2-l1,
1027 $ c( k1, l1 ), ldc, scaloc, iinfo )
1028 info = max( info, iinfo )
1030 IF( scaloc * swork( k, l ) .EQ. zero )
THEN
1031 IF( scaloc .EQ. zero )
THEN
1039 buf = buf*2.e0**exponent( scaloc )
1046 swork( ll, jj ) = min( bignum,
1047 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
1051 swork( k, l ) = scaloc * swork( k, l )
1052 xnrm = slange(
'I', k2-k1, l2-l1, c( k1, l1 ), ldc,
1065 cnrm = slange(
'I', i2-i1, l2-l1, c( i1, l1 ),
1067 scamin = min( swork( i, l ), swork( k, l ) )
1068 cnrm = cnrm * ( scamin / swork( i, l ) )
1069 xnrm = xnrm * ( scamin / swork( k, l ) )
1070 anrm = swork( i, awrk + k )
1071 scaloc = slarmm( anrm, xnrm, cnrm )
1072 IF( scaloc * scamin .EQ. zero )
THEN
1074 buf = buf*2.e0**exponent( scaloc )
1077 swork( ll, jj ) = min( bignum,
1078 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
1081 scamin = scamin / 2.e0**exponent( scaloc )
1082 scaloc = scaloc / 2.e0**exponent( scaloc )
1084 cnrm = cnrm * scaloc
1085 xnrm = xnrm * scaloc
1090 scal = ( scamin / swork( k, l ) ) * scaloc
1091 IF (scal .NE. one)
THEN
1093 CALL sscal( k2-k1, scal, c( k1, ll ), 1 )
1097 scal = ( scamin / swork( i, l ) ) * scaloc
1098 IF (scal .NE. one)
THEN
1100 CALL sscal( i2-i1, scal, c( i1, ll ), 1 )
1106 swork( k, l ) = scamin * scaloc
1107 swork( i, l ) = scamin * scaloc
1109 CALL sgemm(
'N',
'N', i2-i1, l2-l1, k2-k1, -one,
1110 $ a( i1, k1 ), lda, c( k1, l1 ), ldc,
1111 $ one, c( i1, l1 ), ldc )
1119 j1 = iwork( pc + j )
1120 j2 = iwork( pc + j + 1 )
1125 cnrm = slange(
'I', k2-k1, j2-j1, c( k1, j1 ),
1127 scamin = min( swork( k, j ), swork( k, l ) )
1128 cnrm = cnrm * ( scamin / swork( k, j ) )
1129 xnrm = xnrm * ( scamin / swork( k, l ) )
1130 bnrm = swork( l, bwrk + j )
1131 scaloc = slarmm( bnrm, xnrm, cnrm )
1132 IF( scaloc * scamin .EQ. zero )
THEN
1134 buf = buf*2.e0**exponent( scaloc )
1137 swork( ll, jj ) = min( bignum,
1138 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
1141 scamin = scamin / 2.e0**exponent( scaloc )
1142 scaloc = scaloc / 2.e0**exponent( scaloc )
1144 cnrm = cnrm * scaloc
1145 xnrm = xnrm * scaloc
1150 scal = ( scamin / swork( k, l ) ) * scaloc
1151 IF( scal .NE. one )
THEN
1153 CALL sscal( k2-k1, scal, c( k1, jj ), 1 )
1157 scal = ( scamin / swork( k, j ) ) * scaloc
1158 IF( scal .NE. one )
THEN
1160 CALL sscal( k2-k1, scal, c( k1, jj ), 1 )
1166 swork( k, l ) = scamin * scaloc
1167 swork( k, j ) = scamin * scaloc
1169 CALL sgemm(
'N',
'T', k2-k1, j2-j1, l2-l1, -sgn,
1170 $ c( k1, l1 ), ldc, b( j1, l1 ), ldb,
1171 $ one, c( k1, j1 ), ldc )
1180 scale = swork( 1, 1 )
1183 scale = min( scale, swork( k, l ) )
1187 IF( scale .EQ. zero )
THEN
1193 iwork(1) = nba + nbb + 2
1194 swork(1,1) = real( max( nba, nbb ) )
1195 swork(2,1) = real( 2 * nbb + nba )
1205 l1 = iwork( pc + l )
1206 l2 = iwork( pc + l + 1 )
1207 scal = scale / swork( k, l )
1208 IF( scal .NE. one )
THEN
1210 CALL sscal( k2-k1, scal, c( k1, ll ), 1 )
1216 IF( buf .NE. one .AND. buf.GT.zero )
THEN
1220 scaloc = min( scale / smlnum, one / buf )
1222 scale = scale / scaloc
1225 IF( buf.NE.one .AND. buf.GT.zero )
THEN
1238 scal = max( scal, abs( c( k, l ) ) )
1244 scaloc = min( bignum / scal, one / buf )
1246 CALL slascl(
'G', -1, -1, one, scaloc, m, n, c, ldc,
1257 iwork(1) = nba + nbb + 2
1258 swork(1,1) = real( max( nba, nbb ) )
1259 swork(2,1) = real( 2 * nbb + nba )