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