199 IMPLICIT NONE
200
201
202 CHARACTER TRANA, TRANB
203 INTEGER INFO, ISGN, LDA, LDB, LDC, M, N,
204 $ LIWORK, LDSWORK
205 REAL SCALE
206
207
208 INTEGER IWORK( * )
209 REAL A( LDA, * ), B( LDB, * ), C( LDC, * ),
210 $ SWORK( LDSWORK, * )
211
212
213 REAL ZERO, ONE
214 parameter( zero = 0.0e+0, one = 1.0e+0 )
215
216
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
222
223
224 REAL WNRM( MAX( M, N ) )
225
226
227 LOGICAL LSAME
228 INTEGER ILAENV
229 REAL SLANGE, SLAMCH, SLARMM
232
233
236
237
238 INTRINSIC abs, exponent, max, min, real
239
240
241
242
243
244 notrna =
lsame( trana,
'N' )
245 notrnb =
lsame( tranb,
'N' )
246
247
248
249 nb = max(8,
ilaenv( 1,
'STRSYL',
'', m, n, -1, -1) )
250
251
252
253 nba = max( 1, (m + nb - 1) / nb )
254 nbb = max( 1, (n + nb - 1) / nb )
255
256
257
258 info = 0
259 lquery = ( liwork.EQ.-1 .OR. ldswork.EQ.-1 )
260 iwork( 1 ) = nba + nbb + 2
261 IF( lquery ) THEN
262 ldswork = 2
263 swork( 1, 1 ) = real( max( nba, nbb ) )
264 swork( 2, 1 ) = real( 2 * nbb + nba )
265 END IF
266
267
268
269 IF( .NOT.notrna .AND. .NOT.
lsame( trana,
'T' ) .AND. .NOT.
270 $
lsame( trana,
'C' ) )
THEN
271 info = -1
272 ELSE IF( .NOT.notrnb .AND. .NOT.
lsame( tranb,
'T' ) .AND. .NOT.
273 $
lsame( tranb,
'C' ) )
THEN
274 info = -2
275 ELSE IF( isgn.NE.1 .AND. isgn.NE.-1 ) THEN
276 info = -3
277 ELSE IF( m.LT.0 ) THEN
278 info = -4
279 ELSE IF( n.LT.0 ) THEN
280 info = -5
281 ELSE IF( lda.LT.max( 1, m ) ) THEN
282 info = -7
283 ELSE IF( ldb.LT.max( 1, n ) ) THEN
284 info = -9
285 ELSE IF( ldc.LT.max( 1, m ) ) THEN
286 info = -11
287 ELSE IF( .NOT.lquery .AND. liwork.LT.iwork(1) ) THEN
288 info = -14
289 ELSE IF( .NOT.lquery .AND. ldswork.LT.max( nba, nbb ) ) THEN
290 info = -16
291 END IF
292 IF( info.NE.0 ) THEN
293 CALL xerbla(
'STRSYL3', -info )
294 RETURN
295 ELSE IF( lquery ) THEN
296 RETURN
297 END IF
298
299
300
301 scale = one
302 IF( m.EQ.0 .OR. n.EQ.0 )
303 $ RETURN
304
305
306
307
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 )
312 RETURN
313 END IF
314
315
316
318 bignum = one / smlnum
319
320
321
322 skip = .false.
323 DO i = 1, nba
324 iwork( i ) = ( i - 1 ) * nb + 1
325 END DO
326 iwork( nba + 1 ) = m + 1
327 DO k = 1, nba
328 l1 = iwork( k )
329 l2 = iwork( k + 1 ) - 1
330 DO l = l1, l2
331 IF( skip ) THEN
332 skip = .false.
333 cycle
334 END IF
335 IF( l.GE.m ) THEN
336
337 cycle
338 END IF
339 IF( a( l, l+1 ).NE.zero .AND. a( l+1, l ).NE.zero ) THEN
340
341 IF( l + 1 .EQ. iwork( k + 1 ) ) THEN
342 iwork( k + 1 ) = iwork( k + 1 ) + 1
343 cycle
344 END IF
345 skip = .true.
346 END IF
347 END DO
348 END DO
349 iwork( nba + 1 ) = m + 1
350 IF( iwork( nba ).GE.iwork( nba + 1 ) ) THEN
351 iwork( nba ) = iwork( nba + 1 )
352 nba = nba - 1
353 END IF
354
355
356
357 pc = nba + 1
358 skip = .false.
359 DO i = 1, nbb
360 iwork( pc + i ) = ( i - 1 ) * nb + 1
361 END DO
362 iwork( pc + nbb + 1 ) = n + 1
363 DO k = 1, nbb
364 l1 = iwork( pc + k )
365 l2 = iwork( pc + k + 1 ) - 1
366 DO l = l1, l2
367 IF( skip ) THEN
368 skip = .false.
369 cycle
370 END IF
371 IF( l.GE.n ) THEN
372
373 cycle
374 END IF
375 IF( b( l, l+1 ).NE.zero .AND. b( l+1, l ).NE.zero ) THEN
376
377 IF( l + 1 .EQ. iwork( pc + k + 1 ) ) THEN
378 iwork( pc + k + 1 ) = iwork( pc + k + 1 ) + 1
379 cycle
380 END IF
381 skip = .true.
382 END IF
383 END DO
384 END DO
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 )
388 nbb = nbb - 1
389 END IF
390
391
392
393 DO l = 1, nbb
394 DO k = 1, nba
395 swork( k, l ) = one
396 END DO
397 END DO
398
399
400
401
402 buf = one
403
404
405
406 awrk = nbb
407 DO k = 1, nba
408 k1 = iwork( k )
409 k2 = iwork( k + 1 )
410 DO l = k, nba
411 l1 = iwork( l )
412 l2 = iwork( l + 1 )
413 IF( notrna ) THEN
414 swork( k, awrk + l ) =
slange(
'I', k2-k1, l2-l1,
415 $ a( k1, l1 ), lda, wnrm )
416 ELSE
417 swork( l, awrk + k ) =
slange(
'1', k2-k1, l2-l1,
418 $ a( k1, l1 ), lda, wnrm )
419 END IF
420 END DO
421 END DO
422 bwrk = nbb + nba
423 DO k = 1, nbb
424 k1 = iwork( pc + k )
425 k2 = iwork( pc + k + 1 )
426 DO l = k, nbb
427 l1 = iwork( pc + l )
428 l2 = iwork( pc + l + 1 )
429 IF( notrnb ) THEN
430 swork( k, bwrk + l ) =
slange(
'I', k2-k1, l2-l1,
431 $ b( k1, l1 ), ldb, wnrm )
432 ELSE
433 swork( l, bwrk + k ) =
slange(
'1', k2-k1, l2-l1,
434 $ b( k1, l1 ), ldb, wnrm )
435 END IF
436 END DO
437 END DO
438
439 sgn = real( isgn )
440
441 IF( notrna .AND. notrnb ) THEN
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457 DO k = nba, 1, -1
458
459
460
461
462
463 k1 = iwork( k )
464 k2 = iwork( k + 1 )
465 DO l = 1, nbb
466
467
468
469
470
471 l1 = iwork( pc + l )
472 l2 = iwork( pc + l + 1 )
473
474 CALL strsyl( trana, tranb, isgn, k2-k1, l2-l1,
475 $ a( k1, k1 ), lda,
476 $ b( l1, l1 ), ldb,
477 $ c( k1, l1 ), ldc, scaloc, iinfo )
478 info = max( info, iinfo )
479
480 IF ( scaloc * swork( k, l ) .EQ. zero ) THEN
481 IF( scaloc .EQ. zero ) THEN
482
483
484
485
486 buf = zero
487 ELSE
488
489 buf = buf*2.e0**exponent( scaloc )
490 END IF
491 DO jj = 1, nbb
492 DO ll = 1, nba
493
494
495
496 swork( ll, jj ) = min( bignum,
497 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
498 END DO
499 END DO
500 END IF
501 swork( k, l ) = scaloc * swork( k, l )
502 xnrm =
slange(
'I', k2-k1, l2-l1, c( k1, l1 ), ldc,
503 $ wnrm )
504
505 DO i = k - 1, 1, -1
506
507
508
509 i1 = iwork( i )
510 i2 = iwork( i + 1 )
511
512
513
514
515 cnrm =
slange(
'I', i2-i1, l2-l1, c( i1, l1 ),
516 $ ldc, wnrm )
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
523
524 buf = buf*2.e0**exponent( scaloc )
525 DO jj = 1, nbb
526 DO ll = 1, nba
527 swork( ll, jj ) = min( bignum,
528 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
529 END DO
530 END DO
531 scamin = scamin / 2.e0**exponent( scaloc )
532 scaloc = scaloc / 2.e0**exponent( scaloc )
533 END IF
534 cnrm = cnrm * scaloc
535 xnrm = xnrm * scaloc
536
537
538
539
540 scal = ( scamin / swork( k, l ) ) * scaloc
541 IF (scal .NE. one) THEN
542 DO jj = l1, l2-1
543 CALL sscal( k2-k1, scal, c( k1, jj ), 1)
544 END DO
545 ENDIF
546
547 scal = ( scamin / swork( i, l ) ) * scaloc
548 IF (scal .NE. one) THEN
549 DO ll = l1, l2-1
550 CALL sscal( i2-i1, scal, c( i1, ll ), 1)
551 END DO
552 ENDIF
553
554
555
556 swork( k, l ) = scamin * scaloc
557 swork( i, l ) = scamin * scaloc
558
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 )
562
563 END DO
564
565 DO j = l + 1, nbb
566
567
568
569 j1 = iwork( pc + j )
570 j2 = iwork( pc + j + 1 )
571
572
573
574
575 cnrm =
slange(
'I', k2-k1, j2-j1, c( k1, j1 ),
576 $ ldc, wnrm )
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
583
584 buf = buf*2.e0**exponent( scaloc )
585 DO jj = 1, nbb
586 DO ll = 1, nba
587 swork( ll, jj ) = min( bignum,
588 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
589 END DO
590 END DO
591 scamin = scamin / 2.e0**exponent( scaloc )
592 scaloc = scaloc / 2.e0**exponent( scaloc )
593 END IF
594 cnrm = cnrm * scaloc
595 xnrm = xnrm * scaloc
596
597
598
599
600 scal = ( scamin / swork( k, l ) ) * scaloc
601 IF( scal .NE. one ) THEN
602 DO ll = l1, l2-1
603 CALL sscal( k2-k1, scal, c( k1, ll ), 1 )
604 END DO
605 ENDIF
606
607 scal = ( scamin / swork( k, j ) ) * scaloc
608 IF( scal .NE. one ) THEN
609 DO jj = j1, j2-1
610 CALL sscal( k2-k1, scal, c( k1, jj ), 1 )
611 END DO
612 ENDIF
613
614
615
616 swork( k, l ) = scamin * scaloc
617 swork( k, j ) = scamin * scaloc
618
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 )
622 END DO
623 END DO
624 END DO
625 ELSE IF( .NOT.notrna .AND. notrnb ) THEN
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641 DO k = 1, nba
642
643
644
645
646
647 k1 = iwork( k )
648 k2 = iwork( k + 1 )
649 DO l = 1, nbb
650
651
652
653
654
655 l1 = iwork( pc + l )
656 l2 = iwork( pc + l + 1 )
657
658 CALL strsyl( trana, tranb, isgn, k2-k1, l2-l1,
659 $ a( k1, k1 ), lda,
660 $ b( l1, l1 ), ldb,
661 $ c( k1, l1 ), ldc, scaloc, iinfo )
662 info = max( info, iinfo )
663
664 IF( scaloc * swork( k, l ) .EQ. zero ) THEN
665 IF( scaloc .EQ. zero ) THEN
666
667
668
669
670 buf = zero
671 ELSE
672
673 buf = buf*2.e0**exponent( scaloc )
674 END IF
675 DO jj = 1, nbb
676 DO ll = 1, nba
677
678
679
680 swork( ll, jj ) = min( bignum,
681 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
682 END DO
683 END DO
684 END IF
685 swork( k, l ) = scaloc * swork( k, l )
686 xnrm =
slange(
'I', k2-k1, l2-l1, c( k1, l1 ), ldc,
687 $ wnrm )
688
689 DO i = k + 1, nba
690
691
692
693 i1 = iwork( i )
694 i2 = iwork( i + 1 )
695
696
697
698
699 cnrm =
slange(
'I', i2-i1, l2-l1, c( i1, l1 ),
700 $ ldc, wnrm )
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
707
708 buf = buf*2.e0**exponent( scaloc )
709 DO jj = 1, nbb
710 DO ll = 1, nba
711 swork( ll, jj ) = min( bignum,
712 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
713 END DO
714 END DO
715 scamin = scamin / 2.e0**exponent( scaloc )
716 scaloc = scaloc / 2.e0**exponent( scaloc )
717 END IF
718 cnrm = cnrm * scaloc
719 xnrm = xnrm * scaloc
720
721
722
723
724 scal = ( scamin / swork( k, l ) ) * scaloc
725 IF (scal .NE. one) THEN
726 DO ll = l1, l2-1
727 CALL sscal( k2-k1, scal, c( k1, ll ), 1 )
728 END DO
729 ENDIF
730
731 scal = ( scamin / swork( i, l ) ) * scaloc
732 IF (scal .NE. one) THEN
733 DO ll = l1, l2-1
734 CALL sscal( i2-i1, scal, c( i1, ll ), 1 )
735 END DO
736 ENDIF
737
738
739
740 swork( k, l ) = scamin * scaloc
741 swork( i, l ) = scamin * scaloc
742
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 )
746 END DO
747
748 DO j = l + 1, nbb
749
750
751
752 j1 = iwork( pc + j )
753 j2 = iwork( pc + j + 1 )
754
755
756
757
758 cnrm =
slange(
'I', k2-k1, j2-j1, c( k1, j1 ),
759 $ ldc, wnrm )
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
766
767 buf = buf*2.e0**exponent( scaloc )
768 DO jj = 1, nbb
769 DO ll = 1, nba
770 swork( ll, jj ) = min( bignum,
771 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
772 END DO
773 END DO
774 scamin = scamin / 2.e0**exponent( scaloc )
775 scaloc = scaloc / 2.e0**exponent( scaloc )
776 END IF
777 cnrm = cnrm * scaloc
778 xnrm = xnrm * scaloc
779
780
781
782
783 scal = ( scamin / swork( k, l ) ) * scaloc
784 IF( scal .NE. one ) THEN
785 DO ll = l1, l2-1
786 CALL sscal( k2-k1, scal, c( k1, ll ), 1 )
787 END DO
788 ENDIF
789
790 scal = ( scamin / swork( k, j ) ) * scaloc
791 IF( scal .NE. one ) THEN
792 DO jj = j1, j2-1
793 CALL sscal( k2-k1, scal, c( k1, jj ), 1 )
794 END DO
795 ENDIF
796
797
798
799 swork( k, l ) = scamin * scaloc
800 swork( k, j ) = scamin * scaloc
801
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 )
805 END DO
806 END DO
807 END DO
808 ELSE IF( .NOT.notrna .AND. .NOT.notrnb ) THEN
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824 DO k = 1, nba
825
826
827
828
829
830 k1 = iwork( k )
831 k2 = iwork( k + 1 )
832 DO l = nbb, 1, -1
833
834
835
836
837
838 l1 = iwork( pc + l )
839 l2 = iwork( pc + l + 1 )
840
841 CALL strsyl( trana, tranb, isgn, k2-k1, l2-l1,
842 $ a( k1, k1 ), lda,
843 $ b( l1, l1 ), ldb,
844 $ c( k1, l1 ), ldc, scaloc, iinfo )
845 info = max( info, iinfo )
846
847 IF( scaloc * swork( k, l ) .EQ. zero ) THEN
848 IF( scaloc .EQ. zero ) THEN
849
850
851
852
853 buf = zero
854 ELSE
855
856 buf = buf*2.e0**exponent( scaloc )
857 END IF
858 DO jj = 1, nbb
859 DO ll = 1, nba
860
861
862
863 swork( ll, jj ) = min( bignum,
864 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
865 END DO
866 END DO
867 END IF
868 swork( k, l ) = scaloc * swork( k, l )
869 xnrm =
slange(
'I', k2-k1, l2-l1, c( k1, l1 ), ldc,
870 $ wnrm )
871
872 DO i = k + 1, nba
873
874
875
876 i1 = iwork( i )
877 i2 = iwork( i + 1 )
878
879
880
881
882 cnrm =
slange(
'I', i2-i1, l2-l1, c( i1, l1 ),
883 $ ldc, wnrm )
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
890
891 buf = buf*2.e0**exponent( scaloc )
892 DO jj = 1, nbb
893 DO ll = 1, nba
894 swork( ll, jj ) = min( bignum,
895 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
896 END DO
897 END DO
898 scamin = scamin / 2.e0**exponent( scaloc )
899 scaloc = scaloc / 2.e0**exponent( scaloc )
900 END IF
901 cnrm = cnrm * scaloc
902 xnrm = xnrm * scaloc
903
904
905
906
907 scal = ( scamin / swork( k, l ) ) * scaloc
908 IF (scal .NE. one) THEN
909 DO ll = l1, l2-1
910 CALL sscal( k2-k1, scal, c( k1, ll ), 1 )
911 END DO
912 ENDIF
913
914 scal = ( scamin / swork( i, l ) ) * scaloc
915 IF (scal .NE. one) THEN
916 DO ll = l1, l2-1
917 CALL sscal( i2-i1, scal, c( i1, ll ), 1 )
918 END DO
919 ENDIF
920
921
922
923 swork( k, l ) = scamin * scaloc
924 swork( i, l ) = scamin * scaloc
925
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 )
929 END DO
930
931 DO j = 1, l - 1
932
933
934
935 j1 = iwork( pc + j )
936 j2 = iwork( pc + j + 1 )
937
938
939
940
941 cnrm =
slange(
'I', k2-k1, j2-j1, c( k1, j1 ),
942 $ ldc, wnrm )
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
949
950 buf = buf*2.e0**exponent( scaloc )
951 DO jj = 1, nbb
952 DO ll = 1, nba
953 swork( ll, jj ) = min( bignum,
954 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
955 END DO
956 END DO
957 scamin = scamin / 2.e0**exponent( scaloc )
958 scaloc = scaloc / 2.e0**exponent( scaloc )
959 END IF
960 cnrm = cnrm * scaloc
961 xnrm = xnrm * scaloc
962
963
964
965
966 scal = ( scamin / swork( k, l ) ) * scaloc
967 IF( scal .NE. one ) THEN
968 DO ll = l1, l2-1
969 CALL sscal( k2-k1, scal, c( k1, ll ), 1)
970 END DO
971 ENDIF
972
973 scal = ( scamin / swork( k, j ) ) * scaloc
974 IF( scal .NE. one ) THEN
975 DO jj = j1, j2-1
976 CALL sscal( k2-k1, scal, c( k1, jj ), 1 )
977 END DO
978 ENDIF
979
980
981
982 swork( k, l ) = scamin * scaloc
983 swork( k, j ) = scamin * scaloc
984
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 )
988 END DO
989 END DO
990 END DO
991 ELSE IF( notrna .AND. .NOT.notrnb ) THEN
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007 DO k = nba, 1, -1
1008
1009
1010
1011
1012
1013 k1 = iwork( k )
1014 k2 = iwork( k + 1 )
1015 DO l = nbb, 1, -1
1016
1017
1018
1019
1020
1021 l1 = iwork( pc + l )
1022 l2 = iwork( pc + l + 1 )
1023
1024 CALL strsyl( trana, tranb, isgn, k2-k1, l2-l1,
1025 $ a( k1, k1 ), lda,
1026 $ b( l1, l1 ), ldb,
1027 $ c( k1, l1 ), ldc, scaloc, iinfo )
1028 info = max( info, iinfo )
1029
1030 IF( scaloc * swork( k, l ) .EQ. zero ) THEN
1031 IF( scaloc .EQ. zero ) THEN
1032
1033
1034
1035
1036 buf = zero
1037 ELSE
1038
1039 buf = buf*2.e0**exponent( scaloc )
1040 END IF
1041 DO jj = 1, nbb
1042 DO ll = 1, nba
1043
1044
1045
1046 swork( ll, jj ) = min( bignum,
1047 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
1048 END DO
1049 END DO
1050 END IF
1051 swork( k, l ) = scaloc * swork( k, l )
1052 xnrm =
slange(
'I', k2-k1, l2-l1, c( k1, l1 ), ldc,
1053 $ wnrm )
1054
1055 DO i = 1, k - 1
1056
1057
1058
1059 i1 = iwork( i )
1060 i2 = iwork( i + 1 )
1061
1062
1063
1064
1065 cnrm =
slange(
'I', i2-i1, l2-l1, c( i1, l1 ),
1066 $ ldc, wnrm )
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
1073
1074 buf = buf*2.e0**exponent( scaloc )
1075 DO jj = 1, nbb
1076 DO ll = 1, nba
1077 swork( ll, jj ) = min( bignum,
1078 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
1079 END DO
1080 END DO
1081 scamin = scamin / 2.e0**exponent( scaloc )
1082 scaloc = scaloc / 2.e0**exponent( scaloc )
1083 END IF
1084 cnrm = cnrm * scaloc
1085 xnrm = xnrm * scaloc
1086
1087
1088
1089
1090 scal = ( scamin / swork( k, l ) ) * scaloc
1091 IF (scal .NE. one) THEN
1092 DO ll = l1, l2-1
1093 CALL sscal( k2-k1, scal, c( k1, ll ), 1 )
1094 END DO
1095 ENDIF
1096
1097 scal = ( scamin / swork( i, l ) ) * scaloc
1098 IF (scal .NE. one) THEN
1099 DO ll = l1, l2-1
1100 CALL sscal( i2-i1, scal, c( i1, ll ), 1 )
1101 END DO
1102 ENDIF
1103
1104
1105
1106 swork( k, l ) = scamin * scaloc
1107 swork( i, l ) = scamin * scaloc
1108
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 )
1112
1113 END DO
1114
1115 DO j = 1, l - 1
1116
1117
1118
1119 j1 = iwork( pc + j )
1120 j2 = iwork( pc + j + 1 )
1121
1122
1123
1124
1125 cnrm =
slange(
'I', k2-k1, j2-j1, c( k1, j1 ),
1126 $ ldc, wnrm )
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
1133
1134 buf = buf*2.e0**exponent( scaloc )
1135 DO jj = 1, nbb
1136 DO ll = 1, nba
1137 swork( ll, jj ) = min( bignum,
1138 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
1139 END DO
1140 END DO
1141 scamin = scamin / 2.e0**exponent( scaloc )
1142 scaloc = scaloc / 2.e0**exponent( scaloc )
1143 END IF
1144 cnrm = cnrm * scaloc
1145 xnrm = xnrm * scaloc
1146
1147
1148
1149
1150 scal = ( scamin / swork( k, l ) ) * scaloc
1151 IF( scal .NE. one ) THEN
1152 DO jj = l1, l2-1
1153 CALL sscal( k2-k1, scal, c( k1, jj ), 1 )
1154 END DO
1155 ENDIF
1156
1157 scal = ( scamin / swork( k, j ) ) * scaloc
1158 IF( scal .NE. one ) THEN
1159 DO jj = j1, j2-1
1160 CALL sscal( k2-k1, scal, c( k1, jj ), 1 )
1161 END DO
1162 ENDIF
1163
1164
1165
1166 swork( k, l ) = scamin * scaloc
1167 swork( k, j ) = scamin * scaloc
1168
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 )
1172 END DO
1173 END DO
1174 END DO
1175
1176 END IF
1177
1178
1179
1180 scale = swork( 1, 1 )
1181 DO k = 1, nba
1182 DO l = 1, nbb
1183 scale = min( scale, swork( k, l ) )
1184 END DO
1185 END DO
1186
1187 IF( scale .EQ. zero ) THEN
1188
1189
1190
1191
1192
1193 iwork(1) = nba + nbb + 2
1194 swork(1,1) = real( max( nba, nbb ) )
1195 swork(2,1) = real( 2 * nbb + nba )
1196 RETURN
1197 END IF
1198
1199
1200
1201 DO k = 1, nba
1202 k1 = iwork( k )
1203 k2 = iwork( k + 1 )
1204 DO l = 1, nbb
1205 l1 = iwork( pc + l )
1206 l2 = iwork( pc + l + 1 )
1207 scal = scale / swork( k, l )
1208 IF( scal .NE. one ) THEN
1209 DO ll = l1, l2-1
1210 CALL sscal( k2-k1, scal, c( k1, ll ), 1 )
1211 END DO
1212 ENDIF
1213 END DO
1214 END DO
1215
1216 IF( buf .NE. one .AND. buf.GT.zero ) THEN
1217
1218
1219
1220 scaloc = min( scale / smlnum, one / buf )
1221 buf = buf * scaloc
1222 scale = scale / scaloc
1223 END IF
1224
1225 IF( buf.NE.one .AND. buf.GT.zero ) THEN
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235 scal = c( 1, 1 )
1236 DO k = 1, m
1237 DO l = 1, n
1238 scal = max( scal, abs( c( k, l ) ) )
1239 END DO
1240 END DO
1241
1242
1243
1244 scaloc = min( bignum / scal, one / buf )
1245 buf = buf * scaloc
1246 CALL slascl(
'G', -1, -1, one, scaloc, m, n, c, ldc,
1247 $ iwork(1) )
1248 END IF
1249
1250
1251
1252
1253 scale = scale * buf
1254
1255
1256
1257 iwork(1) = nba + nbb + 2
1258 swork(1,1) = real( max( nba, nbb ) )
1259 swork(2,1) = real( 2 * nbb + nba )
1260
1261 RETURN
1262
1263
1264
subroutine xerbla(srname, info)
subroutine sgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
SGEMM
integer function ilaenv(ispec, name, opts, n1, n2, n3, n4)
ILAENV
real function slamch(cmach)
SLAMCH
real function slange(norm, m, n, a, lda, work)
SLANGE returns the value of the 1-norm, Frobenius norm, infinity-norm, or the largest absolute value ...
real function slarmm(anorm, bnorm, cnorm)
SLARMM
subroutine slascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
SLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
logical function lsame(ca, cb)
LSAME
subroutine sscal(n, sa, sx, incx)
SSCAL
subroutine strsyl(trana, tranb, isgn, m, n, a, lda, b, ldb, c, ldc, scale, info)
STRSYL