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