3
4
5
6
7
8
9 CHARACTER TRANS, UPLO
10 INTEGER BW, 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 REAL ONE
369 parameter( one = 1.0e+0 )
370 REAL ZERO
371 parameter( zero = 0.0e+0 )
372 INTEGER INT_ONE
373 parameter( int_one = 1 )
374 INTEGER DESCMULT, BIGNUM
375 parameter( descmult = 100, bignum = descmult*descmult )
376 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
377 $ LLD_, MB_, M_, NB_, N_, RSRC_
378 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
379 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
380 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
381
382
383 INTEGER CSRC, FIRST_PROC, ICTXT, ICTXT_NEW, ICTXT_SAVE,
384 $ IDUM1, IDUM2, IDUM3, JA_NEW, LEVEL_DIST, LLDA,
385 $ LLDB, MBW2, MYCOL, MYROW, MY_NUM_COLS, NB, NP,
386 $ NPCOL, NPROW, NP_SAVE, ODD_SIZE, OFST,
387 $ PART_OFFSET, PART_SIZE, RETURN_CODE, STORE_M_B,
388 $ STORE_N_A, WORK_SIZE_MIN
389
390
391 INTEGER DESCA_1XP( 7 ), DESCB_PX1( 7 ),
392 $ PARAM_CHECK( 17, 3 )
393
394
397 $ sgesd2d, slamov,
smatadd, stbtrs, strmm, strtrs
398
399
400 LOGICAL LSAME
401 INTEGER NUMROC
403
404
405 INTRINSIC ichar, mod
406
407
408
409
410
411 info = 0
412
413
414
415
416 desca_1xp( 1 ) = 501
417 descb_px1( 1 ) = 502
418
420
421 IF( return_code.NE.0 ) THEN
422 info = -( 8*100+2 )
423 END IF
424
426
427 IF( return_code.NE.0 ) THEN
428 info = -( 11*100+2 )
429 END IF
430
431
432
433
434 IF( desca_1xp( 2 ).NE.descb_px1( 2 ) ) THEN
435 info = -( 11*100+2 )
436 END IF
437
438
439
440
441
442 IF( desca_1xp( 4 ).NE.descb_px1( 4 ) ) THEN
443 info = -( 11*100+4 )
444 END IF
445
446
447
448 IF( desca_1xp( 5 ).NE.descb_px1( 5 ) ) THEN
449 info = -( 11*100+5 )
450 END IF
451
452
453
454 ictxt = desca_1xp( 2 )
455 csrc = desca_1xp( 5 )
456 nb = desca_1xp( 4 )
457 llda = desca_1xp( 6 )
458 store_n_a = desca_1xp( 3 )
459 lldb = descb_px1( 6 )
460 store_m_b = descb_px1( 3 )
461
462
463
464
465
466
467 mbw2 = bw*bw
468
469 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
470 np = nprow*npcol
471
472
473
474 IF(
lsame( uplo,
'U' ) )
THEN
475 idum1 = ichar( 'U' )
476 ELSE IF(
lsame( uplo,
'L' ) )
THEN
477 idum1 = ichar( 'L' )
478 ELSE
479 info = -1
480 END IF
481
482 IF(
lsame( trans,
'N' ) )
THEN
483 idum2 = ichar( 'N' )
484 ELSE IF(
lsame( trans,
'T' ) )
THEN
485 idum2 = ichar( 'T' )
486 ELSE IF(
lsame( trans,
'C' ) )
THEN
487 idum2 = ichar( 'T' )
488 ELSE
489 info = -2
490 END IF
491
492 IF( lwork.LT.-1 ) THEN
493 info = -14
494 ELSE IF( lwork.EQ.-1 ) THEN
495 idum3 = -1
496 ELSE
497 idum3 = 1
498 END IF
499
500 IF( n.LT.0 ) THEN
501 info = -3
502 END IF
503
504 IF( n+ja-1.GT.store_n_a ) THEN
505 info = -( 8*100+6 )
506 END IF
507
508 IF( ( bw.GT.n-1 ) .OR. ( bw.LT.0 ) ) THEN
509 info = -4
510 END IF
511
512 IF( llda.LT.( bw+1 ) ) THEN
513 info = -( 8*100+6 )
514 END IF
515
516 IF( nb.LE.0 ) THEN
517 info = -( 8*100+4 )
518 END IF
519
520 IF( n+ib-1.GT.store_m_b ) THEN
521 info = -( 11*100+3 )
522 END IF
523
524 IF( lldb.LT.nb ) THEN
525 info = -( 11*100+6 )
526 END IF
527
528 IF( nrhs.LT.0 ) THEN
529 info = -5
530 END IF
531
532
533
534 IF( ja.NE.ib ) THEN
535 info = -7
536 END IF
537
538
539
540 IF( nprow.NE.1 ) THEN
541 info = -( 8*100+2 )
542 END IF
543
544 IF( n.GT.np*nb-mod( ja-1, nb ) ) THEN
545 info = -( 3 )
547 $ 'PSPBTRSV, D&C alg.: only 1 block per proc',
548 $ -info )
549 RETURN
550 END IF
551
552 IF( ( ja+n-1.GT.nb ) .AND. ( nb.LT.2*bw ) ) THEN
553 info = -( 8*100+4 )
554 CALL pxerbla( ictxt,
'PSPBTRSV, D&C alg.: NB too small',
555 $ -info )
556 RETURN
557 END IF
558
559
560 work_size_min = bw*nrhs
561
562 work( 1 ) = work_size_min
563
564 IF( lwork.LT.work_size_min ) THEN
565 IF( lwork.NE.-1 ) THEN
566 info = -14
567 CALL pxerbla( ictxt,
'PSPBTRSV: worksize error', -info )
568 END IF
569 RETURN
570 END IF
571
572
573
574 param_check( 17, 1 ) = descb( 5 )
575 param_check( 16, 1 ) = descb( 4 )
576 param_check( 15, 1 ) = descb( 3 )
577 param_check( 14, 1 ) = descb( 2 )
578 param_check( 13, 1 ) = descb( 1 )
579 param_check( 12, 1 ) = ib
580 param_check( 11, 1 ) = desca( 5 )
581 param_check( 10, 1 ) = desca( 4 )
582 param_check( 9, 1 ) = desca( 3 )
583 param_check( 8, 1 ) = desca( 1 )
584 param_check( 7, 1 ) = ja
585 param_check( 6, 1 ) = nrhs
586 param_check( 5, 1 ) = bw
587 param_check( 4, 1 ) = n
588 param_check( 3, 1 ) = idum3
589 param_check( 2, 1 ) = idum2
590 param_check( 1, 1 ) = idum1
591
592 param_check( 17, 2 ) = 1105
593 param_check( 16, 2 ) = 1104
594 param_check( 15, 2 ) = 1103
595 param_check( 14, 2 ) = 1102
596 param_check( 13, 2 ) = 1101
597 param_check( 12, 2 ) = 10
598 param_check( 11, 2 ) = 805
599 param_check( 10, 2 ) = 804
600 param_check( 9, 2 ) = 803
601 param_check( 8, 2 ) = 801
602 param_check( 7, 2 ) = 7
603 param_check( 6, 2 ) = 5
604 param_check( 5, 2 ) = 4
605 param_check( 4, 2 ) = 3
606 param_check( 3, 2 ) = 14
607 param_check( 2, 2 ) = 2
608 param_check( 1, 2 ) = 1
609
610
611
612
613
614 IF( info.GE.0 ) THEN
615 info = bignum
616 ELSE IF( info.LT.-descmult ) THEN
617 info = -info
618 ELSE
619 info = -info*descmult
620 END IF
621
622
623
624 CALL globchk( ictxt, 17, param_check, 17, param_check( 1, 3 ),
625 $ info )
626
627
628
629
630 IF( info.EQ.bignum ) THEN
631 info = 0
632 ELSE IF( mod( info, descmult ).EQ.0 ) THEN
633 info = -info / descmult
634 ELSE
635 info = -info
636 END IF
637
638 IF( info.LT.0 ) THEN
639 CALL pxerbla( ictxt,
'PSPBTRSV', -info )
640 RETURN
641 END IF
642
643
644
645 IF( n.EQ.0 )
646 $ RETURN
647
648 IF( nrhs.EQ.0 )
649 $ RETURN
650
651
652
653
654
655 part_offset = nb*( ( ja-1 ) / ( npcol*nb ) )
656
657 IF( ( mycol-csrc ).LT.( ja-part_offset-1 ) / nb ) THEN
658 part_offset = part_offset + nb
659 END IF
660
661 IF( mycol.LT.csrc ) THEN
662 part_offset = part_offset - nb
663 END IF
664
665
666
667
668
669
670
671 first_proc = mod( ( ja-1 ) / nb+csrc, npcol )
672
673
674
675 ja_new = mod( ja-1, nb ) + 1
676
677
678
679 np_save = np
680 np = ( ja_new+n-2 ) / nb + 1
681
682
683
684 CALL reshape( ictxt, int_one, ictxt_new, int_one, first_proc,
685 $ int_one, np )
686
687
688
689 ictxt_save = ictxt
690 ictxt = ictxt_new
691 desca_1xp( 2 ) = ictxt_new
692 descb_px1( 2 ) = ictxt_new
693
694
695
696 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
697
698
699
700 IF( myrow.LT.0 ) THEN
701 GO TO 180
702 END IF
703
704
705
706
707
708
709 part_size = nb
710
711
712
713 my_num_cols =
numroc( n, part_size, mycol, 0, npcol )
714
715
716
717 IF( mycol.EQ.0 ) THEN
718 part_offset = part_offset + mod( ja_new-1, part_size )
719 my_num_cols = my_num_cols - mod( ja_new-1, part_size )
720 END IF
721
722
723
724 ofst = part_offset*llda
725
726
727
728 odd_size = my_num_cols
729 IF( mycol.LT.np-1 ) THEN
730 odd_size = odd_size - bw
731 END IF
732
733
734
735
736
737 IF(
lsame( uplo,
'L' ) )
THEN
738
739 IF(
lsame( trans,
'N' ) )
THEN
740
741
742
743
744
745
746
747
748
749
750 CALL stbtrs( uplo, 'N', 'N', odd_size, bw, nrhs,
751 $ a( ofst+1 ), llda, b( part_offset+1 ), lldb,
752 $ info )
753
754
755 IF( mycol.LT.np-1 ) THEN
756
757
758
759
760
761
762
763 CALL slamov( 'N', bw, nrhs,
764 $ b( part_offset+odd_size-bw+1 ), lldb,
765 $ work( 1 ), bw )
766
767 CALL strmm( 'L', 'U', 'N', 'N', bw, nrhs, -one,
768 $ a( ( ofst+( bw+1 )+( odd_size-bw )*llda ) ),
769 $ llda-1, work( 1 ), bw )
770
771 CALL smatadd( bw, nrhs, one, work( 1 ), bw, one,
772 $ b( part_offset+odd_size+1 ), lldb )
773
774 END IF
775
776
777 IF( mycol.NE.0 ) THEN
778
779
780
781 CALL sgemm( 'T', 'N', bw, nrhs, odd_size, -one, af( 1 ),
782 $ odd_size, b( part_offset+1 ), lldb, zero,
783 $ work( 1+bw-bw ), bw )
784 END IF
785
786
787
788
789
790
791
792
793
794 IF( mycol.GT.0 ) THEN
795
796 CALL sgesd2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
797 $ mycol-1 )
798
799 END IF
800
801
802
803 IF( mycol.LT.npcol-1 ) THEN
804
805 CALL sgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
806 $ mycol+1 )
807
808
809
810 CALL smatadd( bw, nrhs, one, work( 1 ), bw, one,
811 $ b( part_offset+odd_size+1 ), lldb )
812
813 END IF
814
815
816
817
818 IF( mycol.EQ.npcol-1 ) THEN
819 GO TO 30
820 END IF
821
822
823
824
825
826
827
828 level_dist = 1
829
830
831
832 10 CONTINUE
833 IF( mod( ( mycol+1 ) / level_dist, 2 ).NE.0 )
834 $ GO TO 20
835
836
837
838 IF( mycol-level_dist.GE.0 ) THEN
839
840 CALL sgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
841 $ mycol-level_dist )
842
843 CALL smatadd( bw, nrhs, one, work( 1 ), bw, one,
844 $ b( part_offset+odd_size+1 ), lldb )
845
846 END IF
847
848
849
850 IF( mycol+level_dist.LT.npcol-1 ) THEN
851
852 CALL sgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
853 $ mycol+level_dist )
854
855 CALL smatadd( bw, nrhs, one, work( 1 ), bw, one,
856 $ b( part_offset+odd_size+1 ), lldb )
857
858 END IF
859
860 level_dist = level_dist*2
861
862 GO TO 10
863 20 CONTINUE
864
865
866
867
868
869
870
871
872
873 CALL strtrs( 'L', 'N', 'N', bw, nrhs,
874 $ af( odd_size*bw+mbw2+1 ), bw,
875 $ b( part_offset+odd_size+1 ), lldb, info )
876
877 IF( info.NE.0 ) THEN
878 GO TO 170
879 END IF
880
881
882
883
884 IF( mycol / level_dist.LE.( npcol-1 ) / level_dist-2 ) THEN
885
886
887
888 CALL sgemm( 'T', 'N', bw, nrhs, bw, -one,
889 $ af( ( odd_size )*bw+1 ), bw,
890 $ b( part_offset+odd_size+1 ), lldb, zero,
891 $ work( 1 ), bw )
892
893
894
895 CALL sgesd2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
896 $ mycol+level_dist )
897
898 END IF
899
900
901
902 IF( ( mycol / level_dist.GT.0 ) .AND.
903 $ ( mycol / level_dist.LE.( npcol-1 ) / level_dist-1 ) )
904 $ THEN
905
906
907
908
909
910 CALL sgemm( 'N', 'N', bw, nrhs, bw, -one,
911 $ af( odd_size*bw+2*mbw2+1 ), bw,
912 $ b( part_offset+odd_size+1 ), lldb, zero,
913 $ work( 1 ), bw )
914
915
916
917 CALL sgesd2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
918 $ mycol-level_dist )
919
920 END IF
921
922
923 30 CONTINUE
924
925 ELSE
926
927
928
929
930
931
932
933
934
935
936
937 IF( mycol.EQ.npcol-1 ) THEN
938 GO TO 80
939 END IF
940
941
942
943 level_dist = 1
944 40 CONTINUE
945 IF( mod( ( mycol+1 ) / level_dist, 2 ).NE.0 )
946 $ GO TO 50
947
948 level_dist = level_dist*2
949
950 GO TO 40
951 50 CONTINUE
952
953
954 IF( ( mycol / level_dist.GT.0 ) .AND.
955 $ ( mycol / level_dist.LE.( npcol-1 ) / level_dist-1 ) )
956 $ THEN
957
958
959
960 CALL sgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
961 $ mycol-level_dist )
962
963
964
965
966
967 CALL sgemm( 'T', 'N', bw, nrhs, bw, -one,
968 $ af( odd_size*bw+2*mbw2+1 ), bw, work( 1 ),
969 $ bw, one, b( part_offset+odd_size+1 ), lldb )
970 END IF
971
972
973
974 IF( mycol / level_dist.LE.( npcol-1 ) / level_dist-2 ) THEN
975
976
977
978 CALL sgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
979 $ mycol+level_dist )
980
981
982
983 CALL sgemm( 'N', 'N', bw, nrhs, bw, -one,
984 $ af( ( odd_size )*bw+1 ), bw, work( 1 ), bw,
985 $ one, b( part_offset+odd_size+1 ), lldb )
986
987 END IF
988
989
990
991
992
993 CALL strtrs( 'L', 'T', 'N', bw, nrhs,
994 $ af( odd_size*bw+mbw2+1 ), bw,
995 $ b( part_offset+odd_size+1 ), lldb, info )
996
997 IF( info.NE.0 ) THEN
998 GO TO 170
999 END IF
1000
1001
1002
1003
1004
1005 60 CONTINUE
1006 IF( level_dist.EQ.1 )
1007 $ GO TO 70
1008
1009 level_dist = level_dist / 2
1010
1011
1012
1013 IF( mycol+level_dist.LT.npcol-1 ) THEN
1014
1015 CALL sgesd2d( ictxt, bw, nrhs,
1016 $ b( part_offset+odd_size+1 ), lldb, 0,
1017 $ mycol+level_dist )
1018
1019 END IF
1020
1021
1022
1023 IF( mycol-level_dist.GE.0 ) THEN
1024
1025 CALL sgesd2d( ictxt, bw, nrhs,
1026 $ b( part_offset+odd_size+1 ), lldb, 0,
1027 $ mycol-level_dist )
1028
1029 END IF
1030
1031 GO TO 60
1032 70 CONTINUE
1033
1034
1035 80 CONTINUE
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045 IF( mycol.LT.npcol-1 ) THEN
1046
1047 CALL sgesd2d( ictxt, bw, nrhs,
1048 $ b( part_offset+odd_size+1 ), lldb, 0,
1049 $ mycol+1 )
1050
1051 END IF
1052
1053
1054
1055 IF( mycol.GT.0 ) THEN
1056
1057 CALL sgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
1058 $ mycol-1 )
1059
1060 END IF
1061
1062
1063
1064
1065
1066
1067
1068 IF( mycol.NE.0 ) THEN
1069
1070
1071
1072 CALL sgemm( 'N', 'N', odd_size, nrhs, bw, -one, af( 1 ),
1073 $ odd_size, work( 1+bw-bw ), bw, one,
1074 $ b( part_offset+1 ), lldb )
1075
1076 END IF
1077
1078
1079 IF( mycol.LT.np-1 ) THEN
1080
1081
1082
1083
1084
1085
1086
1087 CALL slamov( 'N', bw, nrhs, b( part_offset+odd_size+1 ),
1088 $ lldb, work( 1+bw-bw ), bw )
1089
1090 CALL strmm( 'L', 'U', 'T', 'N', bw, nrhs, -one,
1091 $ a( ( ofst+( bw+1 )+( odd_size-bw )*llda ) ),
1092 $ llda-1, work( 1+bw-bw ), bw )
1093
1094 CALL smatadd( bw, nrhs, one, work( 1+bw-bw ), bw, one,
1095 $ b( part_offset+odd_size-bw+1 ), lldb )
1096
1097 END IF
1098
1099
1100
1101 CALL stbtrs( uplo, 'T', 'N', odd_size, bw, nrhs,
1102 $ a( ofst+1 ), llda, b( part_offset+1 ), lldb,
1103 $ info )
1104
1105 END IF
1106
1107
1108
1109 ELSE
1110
1111
1112
1113 IF(
lsame( trans,
'T' ) )
THEN
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124 CALL stbtrs( uplo, 'T', 'N', odd_size, bw, nrhs,
1125 $ a( ofst+1 ), llda, b( part_offset+1 ), lldb,
1126 $ info )
1127
1128
1129 IF( mycol.LT.np-1 ) THEN
1130
1131
1132
1133
1134
1135
1136
1137 CALL slamov( 'N', bw, nrhs,
1138 $ b( part_offset+odd_size-bw+1 ), lldb,
1139 $ work( 1 ), bw )
1140
1141 CALL strmm( 'L', 'L', 'T', 'N', bw, nrhs, -one,
1142 $ a( ( ofst+1+odd_size*llda ) ), llda-1,
1143 $ work( 1 ), bw )
1144
1145 CALL smatadd( bw, nrhs, one, work( 1 ), bw, one,
1146 $ b( part_offset+odd_size+1 ), lldb )
1147
1148 END IF
1149
1150
1151 IF( mycol.NE.0 ) THEN
1152
1153
1154
1155 CALL sgemm( 'T', 'N', bw, nrhs, odd_size, -one, af( 1 ),
1156 $ odd_size, b( part_offset+1 ), lldb, zero,
1157 $ work( 1+bw-bw ), bw )
1158 END IF
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168 IF( mycol.GT.0 ) THEN
1169
1170 CALL sgesd2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
1171 $ mycol-1 )
1172
1173 END IF
1174
1175
1176
1177 IF( mycol.LT.npcol-1 ) THEN
1178
1179 CALL sgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
1180 $ mycol+1 )
1181
1182
1183
1184 CALL smatadd( bw, nrhs, one, work( 1 ), bw, one,
1185 $ b( part_offset+odd_size+1 ), lldb )
1186
1187 END IF
1188
1189
1190
1191
1192 IF( mycol.EQ.npcol-1 ) THEN
1193 GO TO 110
1194 END IF
1195
1196
1197
1198
1199
1200
1201
1202 level_dist = 1
1203
1204
1205
1206 90 CONTINUE
1207 IF( mod( ( mycol+1 ) / level_dist, 2 ).NE.0 )
1208 $ GO TO 100
1209
1210
1211
1212 IF( mycol-level_dist.GE.0 ) THEN
1213
1214 CALL sgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
1215 $ mycol-level_dist )
1216
1217 CALL smatadd( bw, nrhs, one, work( 1 ), bw, one,
1218 $ b( part_offset+odd_size+1 ), lldb )
1219
1220 END IF
1221
1222
1223
1224 IF( mycol+level_dist.LT.npcol-1 ) THEN
1225
1226 CALL sgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
1227 $ mycol+level_dist )
1228
1229 CALL smatadd( bw, nrhs, one, work( 1 ), bw, one,
1230 $ b( part_offset+odd_size+1 ), lldb )
1231
1232 END IF
1233
1234 level_dist = level_dist*2
1235
1236 GO TO 90
1237 100 CONTINUE
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247 CALL strtrs( 'L', 'N', 'N', bw, nrhs,
1248 $ af( odd_size*bw+mbw2+1 ), bw,
1249 $ b( part_offset+odd_size+1 ), lldb, info )
1250
1251 IF( info.NE.0 ) THEN
1252 GO TO 170
1253 END IF
1254
1255
1256
1257
1258 IF( mycol / level_dist.LE.( npcol-1 ) / level_dist-2 ) THEN
1259
1260
1261
1262 CALL sgemm( 'T', 'N', bw, nrhs, bw, -one,
1263 $ af( ( odd_size )*bw+1 ), bw,
1264 $ b( part_offset+odd_size+1 ), lldb, zero,
1265 $ work( 1 ), bw )
1266
1267
1268
1269 CALL sgesd2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
1270 $ mycol+level_dist )
1271
1272 END IF
1273
1274
1275
1276 IF( ( mycol / level_dist.GT.0 ) .AND.
1277 $ ( mycol / level_dist.LE.( npcol-1 ) / level_dist-1 ) )
1278 $ THEN
1279
1280
1281
1282
1283
1284 CALL sgemm( 'N', 'N', bw, nrhs, bw, -one,
1285 $ af( odd_size*bw+2*mbw2+1 ), bw,
1286 $ b( part_offset+odd_size+1 ), lldb, zero,
1287 $ work( 1 ), bw )
1288
1289
1290
1291 CALL sgesd2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
1292 $ mycol-level_dist )
1293
1294 END IF
1295
1296
1297 110 CONTINUE
1298
1299 ELSE
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311 IF( mycol.EQ.npcol-1 ) THEN
1312 GO TO 160
1313 END IF
1314
1315
1316
1317 level_dist = 1
1318 120 CONTINUE
1319 IF( mod( ( mycol+1 ) / level_dist, 2 ).NE.0 )
1320 $ GO TO 130
1321
1322 level_dist = level_dist*2
1323
1324 GO TO 120
1325 130 CONTINUE
1326
1327
1328 IF( ( mycol / level_dist.GT.0 ) .AND.
1329 $ ( mycol / level_dist.LE.( npcol-1 ) / level_dist-1 ) )
1330 $ THEN
1331
1332
1333
1334 CALL sgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
1335 $ mycol-level_dist )
1336
1337
1338
1339
1340
1341 CALL sgemm( 'T', 'N', bw, nrhs, bw, -one,
1342 $ af( odd_size*bw+2*mbw2+1 ), bw, work( 1 ),
1343 $ bw, one, b( part_offset+odd_size+1 ), lldb )
1344 END IF
1345
1346
1347
1348 IF( mycol / level_dist.LE.( npcol-1 ) / level_dist-2 ) THEN
1349
1350
1351
1352 CALL sgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
1353 $ mycol+level_dist )
1354
1355
1356
1357 CALL sgemm( 'N', 'N', bw, nrhs, bw, -one,
1358 $ af( ( odd_size )*bw+1 ), bw, work( 1 ), bw,
1359 $ one, b( part_offset+odd_size+1 ), lldb )
1360
1361 END IF
1362
1363
1364
1365
1366
1367 CALL strtrs( 'L', 'T', 'N', bw, nrhs,
1368 $ af( odd_size*bw+mbw2+1 ), bw,
1369 $ b( part_offset+odd_size+1 ), lldb, info )
1370
1371 IF( info.NE.0 ) THEN
1372 GO TO 170
1373 END IF
1374
1375
1376
1377
1378
1379 140 CONTINUE
1380 IF( level_dist.EQ.1 )
1381 $ GO TO 150
1382
1383 level_dist = level_dist / 2
1384
1385
1386
1387 IF( mycol+level_dist.LT.npcol-1 ) THEN
1388
1389 CALL sgesd2d( ictxt, bw, nrhs,
1390 $ b( part_offset+odd_size+1 ), lldb, 0,
1391 $ mycol+level_dist )
1392
1393 END IF
1394
1395
1396
1397 IF( mycol-level_dist.GE.0 ) THEN
1398
1399 CALL sgesd2d( ictxt, bw, nrhs,
1400 $ b( part_offset+odd_size+1 ), lldb, 0,
1401 $ mycol-level_dist )
1402
1403 END IF
1404
1405 GO TO 140
1406 150 CONTINUE
1407
1408
1409 160 CONTINUE
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419 IF( mycol.LT.npcol-1 ) THEN
1420
1421 CALL sgesd2d( ictxt, bw, nrhs,
1422 $ b( part_offset+odd_size+1 ), lldb, 0,
1423 $ mycol+1 )
1424
1425 END IF
1426
1427
1428
1429 IF( mycol.GT.0 ) THEN
1430
1431 CALL sgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
1432 $ mycol-1 )
1433
1434 END IF
1435
1436
1437
1438
1439
1440
1441
1442 IF( mycol.NE.0 ) THEN
1443
1444
1445
1446 CALL sgemm( 'N', 'N', odd_size, nrhs, bw, -one, af( 1 ),
1447 $ odd_size, work( 1+bw-bw ), bw, one,
1448 $ b( part_offset+1 ), lldb )
1449
1450 END IF
1451
1452
1453 IF( mycol.LT.np-1 ) THEN
1454
1455
1456
1457
1458
1459
1460
1461 CALL slamov( 'N', bw, nrhs, b( part_offset+odd_size+1 ),
1462 $ lldb, work( 1+bw-bw ), bw )
1463
1464 CALL strmm( 'L', 'L', 'N', 'N', bw, nrhs, -one,
1465 $ a( ( ofst+1+odd_size*llda ) ), llda-1,
1466 $ work( 1+bw-bw ), bw )
1467
1468 CALL smatadd( bw, nrhs, one, work( 1+bw-bw ), bw, one,
1469 $ b( part_offset+odd_size-bw+1 ), lldb )
1470
1471 END IF
1472
1473
1474
1475 CALL stbtrs( uplo, 'N', 'N', odd_size, bw, nrhs,
1476 $ a( ofst+1 ), llda, b( part_offset+1 ), lldb,
1477 $ info )
1478
1479 END IF
1480
1481
1482
1483 END IF
1484
1485 170 CONTINUE
1486
1487
1488
1489
1490 IF( ictxt_save.NE.ictxt_new ) THEN
1491 CALL blacs_gridexit( ictxt_new )
1492 END IF
1493
1494 180 CONTINUE
1495
1496
1497
1498 ictxt = ictxt_save
1499 np = np_save
1500
1501
1502
1503 work( 1 ) = work_size_min
1504
1505
1506 RETURN
1507
1508
1509
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)