3
4
5
6
7
8
9 INTEGER INFO, JA, LAF, LWORK, N
10
11
12 INTEGER DESCA( * )
13 COMPLEX*16 AF( * ), D( * ), DL( * ), DU( * ), WORK( * )
14
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 DOUBLE PRECISION ONE, ZERO
357 parameter( one = 1.0d+0 )
358 parameter( zero = 0.0d+0 )
359 COMPLEX*16 CONE, CZERO
360 parameter( cone = ( 1.0d+0, 0.0d+0 ) )
361 parameter( czero = ( 0.0d+0, 0.0d+0 ) )
362 INTEGER INT_ONE
363 parameter( int_one = 1 )
364 INTEGER DESCMULT, BIGNUM
365 parameter(descmult = 100, bignum = descmult * descmult)
366 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
367 $ LLD_, MB_, M_, NB_, N_, RSRC_
368 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
369 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
370 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
371
372
373 INTEGER COMM_PROC, CSRC, FIRST_PROC, I, ICTXT,
374 $ ICTXT_NEW, ICTXT_SAVE, IDUM3, JA_NEW, LAF_MIN,
375 $ LEVEL_DIST, LLDA, MYCOL, MYROW, MY_NUM_COLS,
376 $ NB, NP, NPCOL, NPROW, NP_SAVE, ODD_SIZE,
377 $ PART_OFFSET, PART_SIZE, RETURN_CODE, STORE_N_A,
378 $ TEMP, WORK_SIZE_MIN, WORK_U
379 COMPLEX*16 DOTC
380
381
382 INTEGER DESCA_1XP( 7 ), PARAM_CHECK( 7, 3 )
383
384
385 EXTERNAL blacs_get, blacs_gridexit, blacs_gridinfo,
387 $ zgemm, zgerv2d, zgesd2d, zlamov,
zlatcpy,
388 $ zpbtrf, zpotrf, zsyrk, ztbtrs, ztrmm, ztrrv2d,
389 $ ztrsd2d, ztrsm, ztrtrs,
zzdotc
390
391
392 LOGICAL LSAME
393 INTEGER NUMROC
395
396
397 INTRINSIC ichar,
min, mod
398
399
400
401
402
403 info = 0
404
405
406
407
408 desca_1xp( 1 ) = 501
409
410 temp = desca( dtype_ )
411 IF( temp .EQ. 502 ) THEN
412
413 desca( dtype_ ) = 501
414 ENDIF
415
417
418 desca( dtype_ ) = temp
419
420 IF( return_code .NE. 0) THEN
421 info = -( 6*100 + 2 )
422 ENDIF
423
424
425
426 ictxt = desca_1xp( 2 )
427 csrc = desca_1xp( 5 )
428 nb = desca_1xp( 4 )
429 llda = desca_1xp( 6 )
430 store_n_a = desca_1xp( 3 )
431
432
433
434
435 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
436 np = nprow * npcol
437
438
439
440 IF( lwork .LT. -1) THEN
441 info = -10
442 ELSE IF ( lwork .EQ. -1 ) THEN
443 idum3 = -1
444 ELSE
445 idum3 = 1
446 ENDIF
447
448 IF( n .LT. 0 ) THEN
449 info = -1
450 ENDIF
451
452 IF( n+ja-1 .GT. store_n_a ) THEN
453 info = -( 6*100 + 6 )
454 ENDIF
455
456
457
458 IF( nprow .NE. 1 ) THEN
459 info = -( 6*100+2 )
460 ENDIF
461
462 IF( n .GT. np*nb-mod( ja-1, nb )) THEN
463 info = -( 1 )
465 $ 'PZDTTRF, D&C alg.: only 1 block per proc',
466 $ -info )
467 RETURN
468 ENDIF
469
470 IF((ja+n-1.GT.nb) .AND. ( nb.LT.2*int_one )) THEN
471 info = -( 6*100+4 )
473 $ 'PZDTTRF, D&C alg.: NB too small',
474 $ -info )
475 RETURN
476 ENDIF
477
478
479
480
481 laf_min = (12*npcol+3*nb)
482
483 IF( laf .LT. laf_min ) THEN
484 info = -8
485
486 af( 1 ) = laf_min
488 $ 'PZDTTRF: auxiliary storage error ',
489 $ -info )
490 RETURN
491 ENDIF
492
493
494
495 work_size_min = 8*npcol
496
497 work( 1 ) = work_size_min
498
499 IF( lwork .LT. work_size_min ) THEN
500 IF( lwork .NE. -1 ) THEN
501 info = -10
503 $ 'PZDTTRF: worksize error ',
504 $ -info )
505 ENDIF
506 RETURN
507 ENDIF
508
509
510
511 param_check( 7, 1 ) = desca(5)
512 param_check( 6, 1 ) = desca(4)
513 param_check( 5, 1 ) = desca(3)
514 param_check( 4, 1 ) = desca(1)
515 param_check( 3, 1 ) = ja
516 param_check( 2, 1 ) = n
517 param_check( 1, 1 ) = idum3
518
519 param_check( 7, 2 ) = 605
520 param_check( 6, 2 ) = 604
521 param_check( 5, 2 ) = 603
522 param_check( 4, 2 ) = 601
523 param_check( 3, 2 ) = 5
524 param_check( 2, 2 ) = 1
525 param_check( 1, 2 ) = 10
526
527
528
529
530
531 IF( info.GE.0 ) THEN
532 info = bignum
533 ELSE IF( info.LT.-descmult ) THEN
534 info = -info
535 ELSE
536 info = -info * descmult
537 END IF
538
539
540
541 CALL globchk( ictxt, 7, param_check, 7,
542 $ param_check( 1, 3 ), info )
543
544
545
546
547 IF( info.EQ.bignum ) THEN
548 info = 0
549 ELSE IF( mod( info, descmult ) .EQ. 0 ) THEN
550 info = -info / descmult
551 ELSE
552 info = -info
553 END IF
554
555 IF( info.LT.0 ) THEN
556 CALL pxerbla( ictxt,
'PZDTTRF', -info )
557 RETURN
558 END IF
559
560
561
562 IF( n.EQ.0 )
563 $ RETURN
564
565
566
567
568
569 part_offset = nb*( (ja-1)/(npcol*nb) )
570
571 IF ( (mycol-csrc) .LT. (ja-part_offset-1)/nb ) THEN
572 part_offset = part_offset + nb
573 ENDIF
574
575 IF ( mycol .LT. csrc ) THEN
576 part_offset = part_offset - nb
577 ENDIF
578
579
580
581
582
583
584
585 first_proc = mod( ( ja-1 )/nb+csrc, npcol )
586
587
588
589 ja_new = mod( ja-1, nb ) + 1
590
591
592
593 np_save = np
594 np = ( ja_new+n-2 )/nb + 1
595
596
597
598 CALL reshape( ictxt, int_one, ictxt_new, int_one,
599 $ first_proc, int_one, np )
600
601
602
603 ictxt_save = ictxt
604 ictxt = ictxt_new
605 desca_1xp( 2 ) = ictxt_new
606
607
608
609 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
610
611
612
613 IF( myrow .LT. 0 ) THEN
614 GOTO 1234
615 ENDIF
616
617
618
619
620
621
622 part_size = nb
623
624
625
626 my_num_cols =
numroc( n, part_size, mycol, 0, npcol )
627
628
629
630 IF ( mycol .EQ. 0 ) THEN
631 part_offset = part_offset+mod( ja_new-1, part_size )
632 my_num_cols = my_num_cols - mod(ja_new-1, part_size )
633 ENDIF
634
635
636
637 odd_size = my_num_cols
638 IF ( mycol .LT. np-1 ) THEN
639 odd_size = odd_size - int_one
640 ENDIF
641
642
643
644 work_u = int_one*odd_size + 3
645
646
647
648
649 DO 10 i=1, laf_min
650 af( i ) = czero
651 10 CONTINUE
652
653
654
655
656
657
658
659
660
661 IF ( mycol .LT. np-1 ) THEN
662
663
664
665
666
667 CALL ztrsd2d( ictxt, 'U', 'N', 1, 1,
668 $ du( part_offset+odd_size+1 ), llda-1, 0,
669 $ mycol+1 )
670
671 ENDIF
672
673
674
675
676 CALL zdttrf( odd_size, dl( part_offset+2 ), d( part_offset+1 ),
677 $ du( part_offset+1 ), info )
678
679 IF( info.NE.0 ) THEN
680 info = mycol+1
681 GOTO 1500
682 ENDIF
683
684
685 IF ( mycol .LT. np-1 ) THEN
686
687
688
689
690
691
692
693
694 dl( part_offset+odd_size+1 ) =
695 $ ( dl( part_offset+odd_size+1 ) )
696 $ / ( d( part_offset+odd_size ) )
697
698
699
700
701
702
703 d( part_offset+odd_size+1 ) = d( part_offset+odd_size+1 )-
704 $ dl( part_offset+odd_size+1 )*du( part_offset+odd_size )
705
706 ENDIF
707
708
709
710 1500 CONTINUE
711
712
713 IF ( mycol .NE. 0 ) THEN
714
715
716
717 af( work_u+1 ) = ( dl( part_offset+1 ) )
718
719 IF (info.EQ.0) THEN
720
721
722
723 CALL zdttrsv(
'L',
'N', odd_size, int_one,
724 $ dl( part_offset+2 ), d( part_offset+1 ),
725 $ du( part_offset+1 ), af( work_u+1 ), odd_size,
726 $ info )
727
728
729
730
731 CALL ztrrv2d( ictxt, 'U', 'N', 1, 1, af( 1 ), odd_size, 0,
732 $ mycol-1 )
733
734 af( 1 ) = dconjg( af( 1 ) )
735
736 CALL zdttrsv(
'U',
'C', odd_size, int_one,
737 $ dl( part_offset+2 ), d( part_offset+1 ),
738 $ du( part_offset+1 ),
739 $ af( 1 ), odd_size, info )
740
741
742
743
744 CALL zzdotc( odd_size, dotc, af( 1 ), 1, af( work_u+1 ), 1 )
745 af( odd_size+3 ) = -cone * dotc
746
747
748
749
750
751 CALL zgesd2d( ictxt, int_one, int_one, af( odd_size+3 ),
752 $ int_one, 0, mycol-1 )
753
754
755 IF ( mycol .LT. np-1 ) THEN
756
757
758
759
760
761 af( odd_size+1 ) = -cone
762 $ * dconjg( dl( part_offset+odd_size+1 )
763 $ * af( work_u+odd_size ) )
764
765
766 af(work_u+(odd_size)+1 ) = -cone
767 $ * du( part_offset+odd_size )
768 $ * dconjg( af( odd_size ) )
769
770 ENDIF
771
772 ENDIF
773
774
775 ENDIF
776
777
778
779
780
781 CALL igamx2d( ictxt, 'A', ' ', 1, 1, info, 1, info, info,
782 $ -1, 0, 0 )
783
784 IF( mycol.EQ.0 ) THEN
785 CALL igebs2d( ictxt, 'A', ' ', 1, 1, info, 1 )
786 ELSE
787 CALL igebr2d( ictxt, 'A', ' ', 1, 1, info, 1, 0, 0 )
788 ENDIF
789
790 IF ( info.NE.0 ) THEN
791 GOTO 1000
792 ENDIF
793
794
795
796
797
798
799
800
801
802
803
804
805 IF( mycol .EQ. npcol-1 ) THEN
806 GOTO 14
807 ENDIF
808
809
810
811
812
813 IF( (mod( mycol+1, 2 ) .EQ. 0) .AND. ( mycol .GT. 0 ) ) THEN
814
815 CALL zgesd2d( ictxt, int_one, int_one,
816 $ af( odd_size+1 ),
817 $ int_one, 0, mycol-1 )
818
819 CALL zgesd2d( ictxt, int_one, int_one,
820 $ af( work_u+odd_size+1 ),
821 $ int_one, 0, mycol-1 )
822
823 ENDIF
824
825
826
827
828 af( odd_size+2 ) =
829 $ dcmplx( d( part_offset+odd_size+1 ) )
830
831
832
833 IF( mycol.LT. npcol-1 ) THEN
834
835 CALL zgerv2d( ictxt, int_one, int_one,
836 $ af( odd_size+2+1 ),
837 $ int_one, 0,
838 $ mycol+1 )
839
840
841
842 af( odd_size+2 ) = af( odd_size+2 )+af( odd_size+3 )
843
844 ENDIF
845
846
847
848
849
850
851
852 level_dist = 1
853
854
855
856 12 CONTINUE
857 IF( mod( (mycol+1)/level_dist, 2) .NE. 0 ) GOTO 11
858
859
860
861 IF( mycol-level_dist .GE. 0 ) THEN
862 CALL zgerv2d( ictxt, int_one, int_one, work( 1 ),
863 $ int_one, 0, mycol-level_dist )
864
865 af( odd_size+2 ) = af( odd_size+2 )+work( 1 )
866
867 ENDIF
868
869
870
871 IF( mycol+level_dist .LT. npcol-1 ) THEN
872 CALL zgerv2d( ictxt, int_one, int_one, work( 1 ),
873 $ int_one, 0, mycol+level_dist )
874
875 af( odd_size+2 ) = af( odd_size+2 )+work( 1 )
876
877 ENDIF
878
879 level_dist = level_dist*2
880
881 GOTO 12
882 11 CONTINUE
883
884
885
886
887
888 IF( af( odd_size+2 ) .EQ. czero ) THEN
889 info = npcol + mycol
890 ENDIF
891
892
893
894
895
896
897 IF( level_dist .EQ. 1 )THEN
898 comm_proc = mycol + 1
899
900
901
902
903 af( work_u+odd_size+3 ) = af( odd_size+1 )
904
905 af( odd_size+3 ) = af( work_u+odd_size+1 )
906
907 ELSE
908 comm_proc = mycol + level_dist/2
909 ENDIF
910
911 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )THEN
912
913 CALL zgerv2d( ictxt, int_one, int_one,
914 $ af( odd_size+1 ),
915 $ int_one, 0, comm_proc )
916
917 CALL zgerv2d( ictxt, int_one, int_one,
918 $ af( work_u+odd_size+1 ),
919 $ int_one, 0, comm_proc )
920
921 IF( info .EQ. 0 ) THEN
922
923
924
925
926
927 af( odd_size+1 ) = af( odd_size+1 )
928 $ / dconjg( af( odd_size+2 ) )
929
930 ENDIF
931
932
933
934
935 work( 1 ) = -one*dconjg( af( odd_size+1 ) )*
936 $ af( work_u+(odd_size)+1 )
937
938
939
940 CALL zgesd2d( ictxt, int_one, int_one, work( 1 ), int_one,
941 $ 0, mycol+level_dist )
942
943 ENDIF
944
945
946
947
948
949
950
951 IF( (mycol/level_dist .GT. 0 ).AND.
952 $ ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) ) THEN
953
954 IF( level_dist .GT. 1)THEN
955
956
957
958
959 CALL zgerv2d( ictxt, int_one, int_one,
960 $ af( work_u+odd_size+2+1 ),
961 $ int_one, 0, mycol-level_dist/2 )
962
963
964
965
966 CALL zgerv2d( ictxt, int_one, int_one,
967 $ af( odd_size+2+1 ),
968 $ int_one, 0, mycol-level_dist/2 )
969
970 ENDIF
971
972
973 IF( info.EQ.0 ) THEN
974
975
976
977 af( odd_size+3 ) = af( odd_size+3 )
978 $ / ( af( odd_size+2 ) )
979
980
981 ENDIF
982
983
984
985
986
987 work( 1 ) = -one*af( odd_size+3 )
988 $ *dconjg( af( work_u+odd_size+3 ) )
989
990
991
992 CALL zgesd2d( ictxt, int_one, int_one, work( 1 ), int_one,
993 $ 0, mycol-level_dist )
994
995
996
997 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 ) THEN
998
999
1000
1001 IF( ( mod( mycol/( 2*level_dist ),2 )) .EQ.0 ) THEN
1002 comm_proc = mycol + level_dist
1003 ELSE
1004 comm_proc = mycol - level_dist
1005 ENDIF
1006
1007
1008
1009
1010
1011 work( 1 ) = -one*af( work_u+odd_size+3 )
1012 $ * af( odd_size+1 )
1013
1014
1015
1016 CALL zgesd2d( ictxt, int_one, int_one, work( 1 ), int_one,
1017 $ 0, comm_proc )
1018
1019 work( 1 ) = -one*af( odd_size+3 )
1020 $ * af( work_u+odd_size+1 )
1021
1022
1023
1024 CALL zgesd2d( ictxt, int_one, int_one, work( 1 ), int_one,
1025 $ 0, comm_proc )
1026
1027 ENDIF
1028
1029 ENDIF
1030
1031
1032 14 CONTINUE
1033
1034
1035 1000 CONTINUE
1036
1037
1038
1039
1040 IF( ictxt_save .NE. ictxt_new ) THEN
1041 CALL blacs_gridexit( ictxt_new )
1042 ENDIF
1043
1044 1234 CONTINUE
1045
1046
1047
1048 ictxt = ictxt_save
1049 np = np_save
1050
1051
1052
1053 work( 1 ) = work_size_min
1054
1055
1056
1057 CALL igamx2d( ictxt, 'A', ' ', 1, 1, info, 1, info, info,
1058 $ -1, 0, 0 )
1059
1060 IF( mycol.EQ.0 ) THEN
1061 CALL igebs2d( ictxt, 'A', ' ', 1, 1, info, 1 )
1062 ELSE
1063 CALL igebr2d( ictxt, 'A', ' ', 1, 1, info, 1, 0, 0 )
1064 ENDIF
1065
1066
1067 RETURN
1068
1069
1070
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 zdttrf(n, dl, d, du, info)
subroutine zdttrsv(uplo, trans, n, nrhs, dl, d, du, b, ldb, info)
subroutine zlatcpy(uplo, m, n, a, lda, b, ldb)
subroutine zzdotc(n, dotc, x, incx, y, incy)