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