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