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