3
4
5
6
7
8
9 CHARACTER TRANS, UPLO
10 INTEGER BWL, BWU, IB, INFO, JA, LAF, LWORK, N, NRHS
11
12
13 INTEGER DESCA( * ), DESCB( * )
14 REAL A( * ), AF( * ), B( * ), WORK( * )
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373 REAL ONE
374 parameter( one = 1.0e+0 )
375 REAL ZERO
376 parameter( zero = 0.0e+0 )
377 INTEGER INT_ONE
378 parameter( int_one = 1 )
379 INTEGER DESCMULT, BIGNUM
380 parameter( descmult = 100, bignum = descmult*descmult )
381 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
382 $ LLD_, MB_, M_, NB_, N_, RSRC_
383 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
384 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
385 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
386
387
388 INTEGER CSRC, FIRST_PROC, ICTXT, ICTXT_NEW, ICTXT_SAVE,
389 $ IDUM1, IDUM2, IDUM3, JA_NEW, LEVEL_DIST, LLDA,
390 $ LLDB, MAX_BW, MBW2, MYCOL, MYROW, MY_NUM_COLS,
391 $ NB, NP, NPCOL, NPROW, NP_SAVE, ODD_SIZE, OFST,
392 $ PART_OFFSET, PART_SIZE, RETURN_CODE, STORE_M_B,
393 $ STORE_N_A, WORK_SIZE_MIN, WORK_U
394
395
396 INTEGER DESCA_1XP( 7 ), DESCB_PX1( 7 ),
397 $ PARAM_CHECK( 18, 3 )
398
399
401 $ sgemm, sgerv2d, sgesd2d, slamov,
smatadd,
403
404
405 LOGICAL LSAME
406 INTEGER NUMROC
408
409
410 INTRINSIC ichar,
max,
min, mod
411
412
413
414
415
416 info = 0
417
418
419
420
421 desca_1xp( 1 ) = 501
422 descb_px1( 1 ) = 502
423
425
426 IF( return_code.NE.0 ) THEN
427 info = -( 9*100+2 )
428 END IF
429
431
432 IF( return_code.NE.0 ) THEN
433 info = -( 12*100+2 )
434 END IF
435
436
437
438
439 IF( desca_1xp( 2 ).NE.descb_px1( 2 ) ) THEN
440 info = -( 12*100+2 )
441 END IF
442
443
444
445
446
447 IF( desca_1xp( 4 ).NE.descb_px1( 4 ) ) THEN
448 info = -( 12*100+4 )
449 END IF
450
451
452
453 IF( desca_1xp( 5 ).NE.descb_px1( 5 ) ) THEN
454 info = -( 12*100+5 )
455 END IF
456
457
458
459 ictxt = desca_1xp( 2 )
460 csrc = desca_1xp( 5 )
461 nb = desca_1xp( 4 )
462 llda = desca_1xp( 6 )
463 store_n_a = desca_1xp( 3 )
464 lldb = descb_px1( 6 )
465 store_m_b = descb_px1( 3 )
466
467
468
469
470
471
472 max_bw =
max( bwl, bwu )
473 mbw2 = max_bw*max_bw
474
475 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
476 np = nprow*npcol
477
478
479
480 IF(
lsame( uplo,
'U' ) )
THEN
481 idum1 = ichar( 'U' )
482 ELSE IF(
lsame( uplo,
'L' ) )
THEN
483 idum1 = ichar( 'L' )
484 ELSE
485 info = -1
486 END IF
487
488 IF(
lsame( trans,
'N' ) )
THEN
489 idum2 = ichar( 'N' )
490 ELSE IF(
lsame( trans,
'T' ) )
THEN
491 idum2 = ichar( 'T' )
492 ELSE IF(
lsame( trans,
'C' ) )
THEN
493 idum2 = ichar( 'T' )
494 ELSE
495 info = -2
496 END IF
497
498 IF( lwork.LT.-1 ) THEN
499 info = -16
500 ELSE IF( lwork.EQ.-1 ) THEN
501 idum3 = -1
502 ELSE
503 idum3 = 1
504 END IF
505
506 IF( n.LT.0 ) THEN
507 info = -3
508 END IF
509
510 IF( n+ja-1.GT.store_n_a ) THEN
511 info = -( 9*100+6 )
512 END IF
513
514 IF( ( bwl.GT.n-1 ) .OR. ( bwl.LT.0 ) ) THEN
515 info = -4
516 END IF
517
518 IF( ( bwu.GT.n-1 ) .OR. ( bwu.LT.0 ) ) THEN
519 info = -5
520 END IF
521
522 IF( llda.LT.( bwl+bwu+1 ) ) THEN
523 info = -( 9*100+6 )
524 END IF
525
526 IF( nb.LE.0 ) THEN
527 info = -( 9*100+4 )
528 END IF
529
530 IF( n+ib-1.GT.store_m_b ) THEN
531 info = -( 12*100+3 )
532 END IF
533
534 IF( lldb.LT.nb ) THEN
535 info = -( 12*100+6 )
536 END IF
537
538 IF( nrhs.LT.0 ) THEN
539 info = -6
540 END IF
541
542
543
544 IF( ja.NE.ib ) THEN
545 info = -8
546 END IF
547
548
549
550 IF( nprow.NE.1 ) THEN
551 info = -( 9*100+2 )
552 END IF
553
554 IF( n.GT.np*nb-mod( ja-1, nb ) ) THEN
555 info = -( 3 )
557 $ 'PSDBTRSV, D&C alg.: only 1 block per proc',
558 $ -info )
559 RETURN
560 END IF
561
562 IF( ( ja+n-1.GT.nb ) .AND. ( nb.LT.2*
max( bwl, bwu ) ) )
THEN
563 info = -( 9*100+4 )
564 CALL pxerbla( ictxt,
'PSDBTRSV, D&C alg.: NB too small',
565 $ -info )
566 RETURN
567 END IF
568
569
570 work_size_min =
max( bwl, bwu )*nrhs
571
572 work( 1 ) = work_size_min
573
574 IF( lwork.LT.work_size_min ) THEN
575 IF( lwork.NE.-1 ) THEN
576 info = -16
577 CALL pxerbla( ictxt,
'PSDBTRSV: worksize error', -info )
578 END IF
579 RETURN
580 END IF
581
582
583
584 param_check( 18, 1 ) = descb( 5 )
585 param_check( 17, 1 ) = descb( 4 )
586 param_check( 16, 1 ) = descb( 3 )
587 param_check( 15, 1 ) = descb( 2 )
588 param_check( 14, 1 ) = descb( 1 )
589 param_check( 13, 1 ) = ib
590 param_check( 12, 1 ) = desca( 5 )
591 param_check( 11, 1 ) = desca( 4 )
592 param_check( 10, 1 ) = desca( 3 )
593 param_check( 9, 1 ) = desca( 1 )
594 param_check( 8, 1 ) = ja
595 param_check( 7, 1 ) = nrhs
596 param_check( 6, 1 ) = bwu
597 param_check( 5, 1 ) = bwl
598 param_check( 4, 1 ) = n
599 param_check( 3, 1 ) = idum3
600 param_check( 2, 1 ) = idum2
601 param_check( 1, 1 ) = idum1
602
603 param_check( 18, 2 ) = 1205
604 param_check( 17, 2 ) = 1204
605 param_check( 16, 2 ) = 1203
606 param_check( 15, 2 ) = 1202
607 param_check( 14, 2 ) = 1201
608 param_check( 13, 2 ) = 11
609 param_check( 12, 2 ) = 905
610 param_check( 11, 2 ) = 904
611 param_check( 10, 2 ) = 903
612 param_check( 9, 2 ) = 901
613 param_check( 8, 2 ) = 8
614 param_check( 7, 2 ) = 6
615 param_check( 6, 2 ) = 5
616 param_check( 5, 2 ) = 4
617 param_check( 4, 2 ) = 3
618 param_check( 3, 2 ) = 16
619 param_check( 2, 2 ) = 2
620 param_check( 1, 2 ) = 1
621
622
623
624
625
626 IF( info.GE.0 ) THEN
627 info = bignum
628 ELSE IF( info.LT.-descmult ) THEN
629 info = -info
630 ELSE
631 info = -info*descmult
632 END IF
633
634
635
636 CALL globchk( ictxt, 18, param_check, 18, param_check( 1, 3 ),
637 $ info )
638
639
640
641
642 IF( info.EQ.bignum ) THEN
643 info = 0
644 ELSE IF( mod( info, descmult ).EQ.0 ) THEN
645 info = -info / descmult
646 ELSE
647 info = -info
648 END IF
649
650 IF( info.LT.0 ) THEN
651 CALL pxerbla( ictxt,
'PSDBTRSV', -info )
652 RETURN
653 END IF
654
655
656
657 IF( n.EQ.0 )
658 $ RETURN
659
660 IF( nrhs.EQ.0 )
661 $ RETURN
662
663
664
665
666
667 part_offset = nb*( ( ja-1 ) / ( npcol*nb ) )
668
669 IF( ( mycol-csrc ).LT.( ja-part_offset-1 ) / nb ) THEN
670 part_offset = part_offset + nb
671 END IF
672
673 IF( mycol.LT.csrc ) THEN
674 part_offset = part_offset - nb
675 END IF
676
677
678
679
680
681
682
683 first_proc = mod( ( ja-1 ) / nb+csrc, npcol )
684
685
686
687 ja_new = mod( ja-1, nb ) + 1
688
689
690
691 np_save = np
692 np = ( ja_new+n-2 ) / nb + 1
693
694
695
696 CALL reshape( ictxt, int_one, ictxt_new, int_one, first_proc,
697 $ int_one, np )
698
699
700
701 ictxt_save = ictxt
702 ictxt = ictxt_new
703 desca_1xp( 2 ) = ictxt_new
704 descb_px1( 2 ) = ictxt_new
705
706
707
708 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
709
710
711
712 IF( myrow.LT.0 ) THEN
713 GO TO 200
714 END IF
715
716
717
718
719
720
721 part_size = nb
722
723
724
725 my_num_cols =
numroc( n, part_size, mycol, 0, npcol )
726
727
728
729 IF( mycol.EQ.0 ) THEN
730 part_offset = part_offset + mod( ja_new-1, part_size )
731 my_num_cols = my_num_cols - mod( ja_new-1, part_size )
732 END IF
733
734
735
736 ofst = part_offset*llda
737
738
739
740 odd_size = my_num_cols
741 IF( mycol.LT.np-1 ) THEN
742 odd_size = odd_size - max_bw
743 END IF
744
745
746
747 work_u = bwu*odd_size + 3*mbw2
748
749
750
751
752
753 IF(
lsame( uplo,
'L' ) )
THEN
754
755 IF(
lsame( trans,
'N' ) )
THEN
756
757
758
759
760
761
762
763
764
765
766 CALL stbtrs( uplo, 'N', 'U', odd_size, bwl, nrhs,
767 $ a( ofst+1+bwu ), llda, b( part_offset+1 ),
768 $ lldb, info )
769
770
771 IF( mycol.LT.np-1 ) THEN
772
773
774
775
776
777
778
779 CALL slamov( 'N', bwl, nrhs,
780 $ b( part_offset+odd_size-bwl+1 ), lldb,
781 $ work( 1 ), max_bw )
782
783 CALL strmm( 'L', 'U', 'N', 'N', bwl, nrhs, -one,
784 $ a( ( ofst+( bwl+bwu+1 )+( odd_size-bwl )*
785 $ llda ) ), llda-1, work( 1 ), max_bw )
786
787 CALL smatadd( bwl, nrhs, one, work( 1 ), max_bw, one,
788 $ b( part_offset+odd_size+1 ), lldb )
789
790 END IF
791
792
793
794 DO 10 idum1 = 1, work_size_min
795 work( idum1 ) = 0.0
796 10 CONTINUE
797
798
799 IF( mycol.NE.0 ) THEN
800
801
802
803
804 CALL sgemm( 'N', 'N', bwu, nrhs, odd_size, -one, af( 1 ),
805 $ bwu, b( part_offset+1 ), lldb, zero,
806 $ work( 1+max_bw-bwu ), max_bw )
807
808 END IF
809
810
811
812
813
814
815
816
817
818 IF( mycol.GT.0 ) THEN
819
820 CALL sgesd2d( ictxt, max_bw, nrhs, work( 1 ), max_bw, 0,
821 $ mycol-1 )
822
823 END IF
824
825
826
827 IF( mycol.LT.npcol-1 ) THEN
828
829 CALL sgerv2d( ictxt, max_bw, nrhs, work( 1 ), max_bw, 0,
830 $ mycol+1 )
831
832
833
834 CALL smatadd( max_bw, nrhs, one, work( 1 ), max_bw, one,
835 $ b( part_offset+odd_size+1 ), lldb )
836
837 END IF
838
839
840
841
842 IF( mycol.EQ.npcol-1 ) THEN
843 GO TO 40
844 END IF
845
846
847
848
849
850
851
852 level_dist = 1
853
854
855
856 20 CONTINUE
857 IF( mod( ( mycol+1 ) / level_dist, 2 ).NE.0 )
858 $ GO TO 30
859
860
861
862 IF( mycol-level_dist.GE.0 ) THEN
863
864 CALL sgerv2d( ictxt, max_bw, nrhs, work( 1 ), max_bw, 0,
865 $ mycol-level_dist )
866
867 CALL smatadd( max_bw, nrhs, one, work( 1 ), max_bw, one,
868 $ b( part_offset+odd_size+1 ), lldb )
869
870 END IF
871
872
873
874 IF( mycol+level_dist.LT.npcol-1 ) THEN
875
876 CALL sgerv2d( ictxt, max_bw, nrhs, work( 1 ), max_bw, 0,
877 $ mycol+level_dist )
878
879 CALL smatadd( max_bw, nrhs, one, work( 1 ), max_bw, one,
880 $ b( part_offset+odd_size+1 ), lldb )
881
882 END IF
883
884 level_dist = level_dist*2
885
886 GO TO 20
887 30 CONTINUE
888
889
890
891
892
893
894
895
896
897 CALL stbtrs(
'L',
'N',
'U', max_bw,
min( bwl, max_bw-1 ),
898 $ nrhs, af( odd_size*bwu+mbw2+1 ), max_bw+1,
899 $ b( part_offset+odd_size+1 ), lldb, info )
900
901 IF( info.NE.0 ) THEN
902 GO TO 190
903 END IF
904
905
906
907
908 IF( mycol / level_dist.LE.( npcol-1 ) / level_dist-2 ) THEN
909
910
911
912 CALL sgemm( 'T', 'N', max_bw, nrhs, max_bw, -one,
913 $ af( ( odd_size )*bwu+1 ), max_bw,
914 $ b( part_offset+odd_size+1 ), lldb, zero,
915 $ work( 1 ), max_bw )
916
917
918
919 CALL sgesd2d( ictxt, max_bw, nrhs, work( 1 ), max_bw, 0,
920 $ mycol+level_dist )
921
922 END IF
923
924
925
926 IF( ( mycol / level_dist.GT.0 ) .AND.
927 $ ( mycol / level_dist.LE.( npcol-1 ) / level_dist-1 ) )
928 $ THEN
929
930
931
932
933
934 CALL sgemm( 'N', 'N', max_bw, nrhs, max_bw, -one,
935 $ af( odd_size*bwu+2*mbw2+1 ), max_bw,
936 $ b( part_offset+odd_size+1 ), lldb, zero,
937 $ work( 1 ), max_bw )
938
939
940
941 CALL sgesd2d( ictxt, max_bw, nrhs, work( 1 ), max_bw, 0,
942 $ mycol-level_dist )
943
944 END IF
945
946
947 40 CONTINUE
948
949 ELSE
950
951
952
953
954
955
956
957
958
959
960
961 IF( mycol.EQ.npcol-1 ) THEN
962 GO TO 90
963 END IF
964
965
966
967 level_dist = 1
968 50 CONTINUE
969 IF( mod( ( mycol+1 ) / level_dist, 2 ).NE.0 )
970 $ GO TO 60
971
972 level_dist = level_dist*2
973
974 GO TO 50
975 60 CONTINUE
976
977
978 IF( ( mycol / level_dist.GT.0 ) .AND.
979 $ ( mycol / level_dist.LE.( npcol-1 ) / level_dist-1 ) )
980 $ THEN
981
982
983
984 CALL sgerv2d( ictxt, max_bw, nrhs, work( 1 ), max_bw, 0,
985 $ mycol-level_dist )
986
987
988
989
990
991 CALL sgemm( 'T', 'N', max_bw, nrhs, max_bw, -one,
992 $ af( odd_size*bwu+2*mbw2+1 ), max_bw,
993 $ work( 1 ), max_bw, one,
994 $ b( part_offset+odd_size+1 ), lldb )
995 END IF
996
997
998
999 IF( mycol / level_dist.LE.( npcol-1 ) / level_dist-2 ) THEN
1000
1001
1002
1003 CALL sgerv2d( ictxt, max_bw, nrhs, work( 1 ), max_bw, 0,
1004 $ mycol+level_dist )
1005
1006
1007
1008 CALL sgemm( 'N', 'N', max_bw, nrhs, max_bw, -one,
1009 $ af( ( odd_size )*bwu+1 ), max_bw, work( 1 ),
1010 $ max_bw, one, b( part_offset+odd_size+1 ),
1011 $ lldb )
1012
1013 END IF
1014
1015
1016
1017
1018
1019 CALL stbtrs(
'L',
'T',
'U', max_bw,
min( bwl, max_bw-1 ),
1020 $ nrhs, af( odd_size*bwu+mbw2+1 ), max_bw+1,
1021 $ b( part_offset+odd_size+1 ), lldb, info )
1022
1023 IF( info.NE.0 ) THEN
1024 GO TO 190
1025 END IF
1026
1027
1028
1029
1030
1031 70 CONTINUE
1032 IF( level_dist.EQ.1 )
1033 $ GO TO 80
1034
1035 level_dist = level_dist / 2
1036
1037
1038
1039 IF( mycol+level_dist.LT.npcol-1 ) THEN
1040
1041 CALL sgesd2d( ictxt, max_bw, nrhs,
1042 $ b( part_offset+odd_size+1 ), lldb, 0,
1043 $ mycol+level_dist )
1044
1045 END IF
1046
1047
1048
1049 IF( mycol-level_dist.GE.0 ) THEN
1050
1051 CALL sgesd2d( ictxt, max_bw, nrhs,
1052 $ b( part_offset+odd_size+1 ), lldb, 0,
1053 $ mycol-level_dist )
1054
1055 END IF
1056
1057 GO TO 70
1058 80 CONTINUE
1059
1060
1061 90 CONTINUE
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071 IF( mycol.LT.npcol-1 ) THEN
1072
1073 CALL sgesd2d( ictxt, max_bw, nrhs,
1074 $ b( part_offset+odd_size+1 ), lldb, 0,
1075 $ mycol+1 )
1076
1077 END IF
1078
1079
1080
1081 IF( mycol.GT.0 ) THEN
1082
1083 CALL sgerv2d( ictxt, max_bw, nrhs, work( 1 ), max_bw, 0,
1084 $ mycol-1 )
1085
1086 END IF
1087
1088
1089
1090
1091
1092
1093
1094 IF( mycol.NE.0 ) THEN
1095
1096
1097
1098 CALL sgemm( 'T', 'N', odd_size, nrhs, bwu, -one, af( 1 ),
1099 $ bwu, work( 1+max_bw-bwu ), max_bw, one,
1100 $ b( part_offset+1 ), lldb )
1101
1102 END IF
1103
1104
1105 IF( mycol.LT.np-1 ) THEN
1106
1107
1108
1109
1110
1111
1112
1113 CALL slamov( 'N', bwl, nrhs, b( part_offset+odd_size+1 ),
1114 $ lldb, work( 1+max_bw-bwl ), max_bw )
1115
1116 CALL strmm( 'L', 'U', 'T', 'N', bwl, nrhs, -one,
1117 $ a( ( ofst+( bwl+bwu+1 )+( odd_size-bwl )*
1118 $ llda ) ), llda-1, work( 1+max_bw-bwl ),
1119 $ max_bw )
1120
1121 CALL smatadd( bwl, nrhs, one, work( 1+max_bw-bwl ),
1122 $ max_bw, one, b( part_offset+odd_size-bwl+
1123 $ 1 ), lldb )
1124
1125 END IF
1126
1127
1128
1129 CALL stbtrs( uplo, 'T', 'U', odd_size, bwl, nrhs,
1130 $ a( ofst+1+bwu ), llda, b( part_offset+1 ),
1131 $ lldb, info )
1132
1133 END IF
1134
1135
1136
1137 ELSE
1138
1139
1140
1141 IF(
lsame( trans,
'T' ) )
THEN
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152 CALL stbtrs( uplo, 'T', 'N', odd_size, bwu, nrhs,
1153 $ a( ofst+1 ), llda, b( part_offset+1 ), lldb,
1154 $ info )
1155
1156
1157 IF( mycol.LT.np-1 ) THEN
1158
1159
1160
1161
1162
1163
1164
1165 CALL slamov( 'N', bwu, nrhs,
1166 $ b( part_offset+odd_size-bwu+1 ), lldb,
1167 $ work( 1 ), max_bw )
1168
1169 CALL strmm( 'L', 'L', 'T', 'N', bwu, nrhs, -one,
1170 $ a( ( ofst+1+odd_size*llda ) ), llda-1,
1171 $ work( 1 ), max_bw )
1172
1173 CALL smatadd( bwu, nrhs, one, work( 1 ), max_bw, one,
1174 $ b( part_offset+odd_size+1 ), lldb )
1175
1176 END IF
1177
1178
1179
1180 DO 100 idum1 = 1, work_size_min
1181 work( idum1 ) = 0.0
1182 100 CONTINUE
1183
1184
1185 IF( mycol.NE.0 ) THEN
1186
1187
1188
1189 CALL sgemm( 'N', 'N', bwl, nrhs, odd_size, -one,
1190 $ af( work_u+1 ), bwl, b( part_offset+1 ),
1191 $ lldb, zero, work( 1+max_bw-bwl ), max_bw )
1192 END IF
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202 IF( mycol.GT.0 ) THEN
1203
1204 CALL sgesd2d( ictxt, max_bw, nrhs, work( 1 ), max_bw, 0,
1205 $ mycol-1 )
1206
1207 END IF
1208
1209
1210
1211 IF( mycol.LT.npcol-1 ) THEN
1212
1213 CALL sgerv2d( ictxt, max_bw, nrhs, work( 1 ), max_bw, 0,
1214 $ mycol+1 )
1215
1216
1217
1218 CALL smatadd( max_bw, nrhs, one, work( 1 ), max_bw, one,
1219 $ b( part_offset+odd_size+1 ), lldb )
1220
1221 END IF
1222
1223
1224
1225
1226 IF( mycol.EQ.npcol-1 ) THEN
1227 GO TO 130
1228 END IF
1229
1230
1231
1232
1233
1234
1235
1236 level_dist = 1
1237
1238
1239
1240 110 CONTINUE
1241 IF( mod( ( mycol+1 ) / level_dist, 2 ).NE.0 )
1242 $ GO TO 120
1243
1244
1245
1246 IF( mycol-level_dist.GE.0 ) THEN
1247
1248 CALL sgerv2d( ictxt, max_bw, nrhs, work( 1 ), max_bw, 0,
1249 $ mycol-level_dist )
1250
1251 CALL smatadd( max_bw, nrhs, one, work( 1 ), max_bw, one,
1252 $ b( part_offset+odd_size+1 ), lldb )
1253
1254 END IF
1255
1256
1257
1258 IF( mycol+level_dist.LT.npcol-1 ) THEN
1259
1260 CALL sgerv2d( ictxt, max_bw, nrhs, work( 1 ), max_bw, 0,
1261 $ mycol+level_dist )
1262
1263 CALL smatadd( max_bw, nrhs, one, work( 1 ), max_bw, one,
1264 $ b( part_offset+odd_size+1 ), lldb )
1265
1266 END IF
1267
1268 level_dist = level_dist*2
1269
1270 GO TO 110
1271 120 CONTINUE
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281 CALL stbtrs(
'U',
'T',
'N', max_bw,
min( bwu, max_bw-1 ),
1282 $ nrhs, af( odd_size*bwu+mbw2+1-
min( bwu,
1283 $ max_bw-1 ) ), max_bw+1,
1284 $ b( part_offset+odd_size+1 ), lldb, info )
1285
1286 IF( info.NE.0 ) THEN
1287 GO TO 190
1288 END IF
1289
1290
1291
1292
1293 IF( mycol / level_dist.LE.( npcol-1 ) / level_dist-2 ) THEN
1294
1295
1296
1297 CALL sgemm( 'T', 'N', max_bw, nrhs, max_bw, -one,
1298 $ af( work_u+( odd_size )*bwl+1 ), max_bw,
1299 $ b( part_offset+odd_size+1 ), lldb, zero,
1300 $ work( 1 ), max_bw )
1301
1302
1303
1304 CALL sgesd2d( ictxt, max_bw, nrhs, work( 1 ), max_bw, 0,
1305 $ mycol+level_dist )
1306
1307 END IF
1308
1309
1310
1311 IF( ( mycol / level_dist.GT.0 ) .AND.
1312 $ ( mycol / level_dist.LE.( npcol-1 ) / level_dist-1 ) )
1313 $ THEN
1314
1315
1316
1317
1318
1319 CALL sgemm( 'N', 'N', max_bw, nrhs, max_bw, -one,
1320 $ af( work_u+odd_size*bwl+2*mbw2+1 ), max_bw,
1321 $ b( part_offset+odd_size+1 ), lldb, zero,
1322 $ work( 1 ), max_bw )
1323
1324
1325
1326 CALL sgesd2d( ictxt, max_bw, nrhs, work( 1 ), max_bw, 0,
1327 $ mycol-level_dist )
1328
1329 END IF
1330
1331
1332 130 CONTINUE
1333
1334 ELSE
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346 IF( mycol.EQ.npcol-1 ) THEN
1347 GO TO 180
1348 END IF
1349
1350
1351
1352 level_dist = 1
1353 140 CONTINUE
1354 IF( mod( ( mycol+1 ) / level_dist, 2 ).NE.0 )
1355 $ GO TO 150
1356
1357 level_dist = level_dist*2
1358
1359 GO TO 140
1360 150 CONTINUE
1361
1362
1363 IF( ( mycol / level_dist.GT.0 ) .AND.
1364 $ ( mycol / level_dist.LE.( npcol-1 ) / level_dist-1 ) )
1365 $ THEN
1366
1367
1368
1369 CALL sgerv2d( ictxt, max_bw, nrhs, work( 1 ), max_bw, 0,
1370 $ mycol-level_dist )
1371
1372
1373
1374
1375
1376 CALL sgemm( 'T', 'N', max_bw, nrhs, max_bw, -one,
1377 $ af( work_u+odd_size*bwl+2*mbw2+1 ), max_bw,
1378 $ work( 1 ), max_bw, one,
1379 $ b( part_offset+odd_size+1 ), lldb )
1380 END IF
1381
1382
1383
1384 IF( mycol / level_dist.LE.( npcol-1 ) / level_dist-2 ) THEN
1385
1386
1387
1388 CALL sgerv2d( ictxt, max_bw, nrhs, work( 1 ), max_bw, 0,
1389 $ mycol+level_dist )
1390
1391
1392
1393 CALL sgemm( 'N', 'N', max_bw, nrhs, max_bw, -one,
1394 $ af( work_u+( odd_size )*bwl+1 ), max_bw,
1395 $ work( 1 ), max_bw, one,
1396 $ b( part_offset+odd_size+1 ), lldb )
1397
1398 END IF
1399
1400
1401
1402
1403
1404 CALL stbtrs(
'U',
'N',
'N', max_bw,
min( bwu, max_bw-1 ),
1405 $ nrhs, af( odd_size*bwu+mbw2+1-
min( bwu,
1406 $ max_bw-1 ) ), max_bw+1,
1407 $ b( part_offset+odd_size+1 ), lldb, info )
1408
1409 IF( info.NE.0 ) THEN
1410 GO TO 190
1411 END IF
1412
1413
1414
1415
1416
1417 160 CONTINUE
1418 IF( level_dist.EQ.1 )
1419 $ GO TO 170
1420
1421 level_dist = level_dist / 2
1422
1423
1424
1425 IF( mycol+level_dist.LT.npcol-1 ) THEN
1426
1427 CALL sgesd2d( ictxt, max_bw, nrhs,
1428 $ b( part_offset+odd_size+1 ), lldb, 0,
1429 $ mycol+level_dist )
1430
1431 END IF
1432
1433
1434
1435 IF( mycol-level_dist.GE.0 ) THEN
1436
1437 CALL sgesd2d( ictxt, max_bw, nrhs,
1438 $ b( part_offset+odd_size+1 ), lldb, 0,
1439 $ mycol-level_dist )
1440
1441 END IF
1442
1443 GO TO 160
1444 170 CONTINUE
1445
1446
1447 180 CONTINUE
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457 IF( mycol.LT.npcol-1 ) THEN
1458
1459 CALL sgesd2d( ictxt, max_bw, nrhs,
1460 $ b( part_offset+odd_size+1 ), lldb, 0,
1461 $ mycol+1 )
1462
1463 END IF
1464
1465
1466
1467 IF( mycol.GT.0 ) THEN
1468
1469 CALL sgerv2d( ictxt, max_bw, nrhs, work( 1 ), max_bw, 0,
1470 $ mycol-1 )
1471
1472 END IF
1473
1474
1475
1476
1477
1478
1479
1480 IF( mycol.NE.0 ) THEN
1481
1482
1483
1484 CALL sgemm( 'T', 'N', odd_size, nrhs, bwl, -one,
1485 $ af( work_u+1 ), bwl, work( 1+max_bw-bwl ),
1486 $ max_bw, one, b( part_offset+1 ), lldb )
1487
1488 END IF
1489
1490
1491 IF( mycol.LT.np-1 ) THEN
1492
1493
1494
1495
1496
1497
1498
1499 CALL slamov( 'N', bwu, nrhs, b( part_offset+odd_size+1 ),
1500 $ lldb, work( 1+max_bw-bwu ), max_bw+bwl )
1501
1502 CALL strmm( 'L', 'L', 'N', 'N', bwu, nrhs, -one,
1503 $ a( ( ofst+1+odd_size*llda ) ), llda-1,
1504 $ work( 1+max_bw-bwu ), max_bw+bwl )
1505
1506 CALL smatadd( bwu, nrhs, one, work( 1+max_bw-bwu ),
1507 $ max_bw+bwl, one, b( part_offset+odd_size-
1508 $ bwu+1 ), lldb )
1509
1510 END IF
1511
1512
1513
1514 CALL stbtrs( uplo, 'N', 'N', odd_size, bwu, nrhs,
1515 $ a( ofst+1 ), llda, b( part_offset+1 ), lldb,
1516 $ info )
1517
1518 END IF
1519
1520
1521
1522 END IF
1523
1524 190 CONTINUE
1525
1526
1527
1528
1529 IF( ictxt_save.NE.ictxt_new ) THEN
1530 CALL blacs_gridexit( ictxt_new )
1531 END IF
1532
1533 200 CONTINUE
1534
1535
1536
1537 ictxt = ictxt_save
1538 np = np_save
1539
1540
1541
1542 work( 1 ) = work_size_min
1543
1544
1545 RETURN
1546
1547
1548
subroutine desc_convert(desc_in, desc_out, info)
integer function numroc(n, nb, iproc, isrcproc, nprocs)
subroutine globchk(ictxt, n, x, ldx, iwork, info)
subroutine pxerbla(ictxt, srname, info)
void reshape(Int *context_in, Int *major_in, Int *context_out, Int *major_out, Int *first_proc, Int *nprow_new, Int *npcol_new)
subroutine smatadd(m, n, alpha, a, lda, beta, c, ldc)