3
4
5
6
7
8
9
10
11
12 CHARACTER TRANS
13 INTEGER BWL, BWU, IB, INFO, JA, LDBW, LWORK, N, NRHS
14
15
16 INTEGER DESCA( * ), DESCB( * )
17 COMPLEX A( * ), B( * ), WORK( * ), X( * )
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 REAL ONE, ZERO
324 parameter( one = 1.0e+0 )
325 parameter( zero = 0.0e+0 )
326 COMPLEX CONE, CZERO
327 parameter( cone = ( 1.0e+0, 0.0e+0 ) )
328 parameter( czero = ( 0.0e+0, 0.0e+0 ) )
329 INTEGER INT_ONE
330 parameter( int_one = 1 )
331 INTEGER DESCMULT, BIGNUM
332 parameter(descmult = 100, bignum = descmult * descmult)
333 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
334 $ LLD_, MB_, M_, NB_, N_, RSRC_
335 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
336 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
337 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
338
339
340 INTEGER CSRC, DL_N_M, DL_N_N, DL_P_M, DL_P_N, DU_N_M,
341 $ DU_N_N, DU_P_M, DU_P_N, FIRST_PROC, I, ICTXT,
342 $ ICTXT_NEW, ICTXT_SAVE, IDUM2, IDUM3, J, JA_NEW,
343 $ LLDA, LLDB, MAX_BW, MYCOL, MYROW, MY_NUM_COLS,
344 $ NB, NP, NPCOL, NPROW, NP_SAVE, ODD_SIZE, OFST,
345 $ PART_OFFSET, PART_SIZE, STORE_M_B, STORE_N_A
346 INTEGER NUMROC_SIZE
347
348
349 INTEGER PARAM_CHECK( 17, 3 )
350
351
353
354
355 LOGICAL LSAME
356 INTEGER NUMROC
358
359
360 INTRINSIC ichar,
min, mod
361
362
363
364
365
366 info = 0
367
368 ictxt = desca( ctxt_ )
369 csrc = desca( csrc_ )
370 nb = desca( nb_ )
371 llda = desca( lld_ )
372 store_n_a = desca( n_ )
373 lldb = descb( lld_ )
374 store_m_b = descb( m_ )
375
376
377
378
379 max_bw =
max(bwl,bwu)
380
381 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
382 np = nprow * npcol
383
384
385
386 IF(
lsame( trans,
'N' ) )
THEN
387 idum2 = ichar( 'N' )
388 ELSE IF (
lsame( trans,
'C' ) )
THEN
389 idum2 = ichar( 'C' )
390 ELSE
391 info = -1
392 END IF
393
394 IF( lwork .LT. -1) THEN
395 info = -15
396 ELSE IF ( lwork .EQ. -1 ) THEN
397 idum3 = -1
398 ELSE
399 idum3 = 1
400 ENDIF
401
402 IF( n .LT. 0 ) THEN
403 info = -2
404 ENDIF
405
406 IF( n+ja-1 .GT. store_n_a ) THEN
407 info = -( 8*100 + 6 )
408 ENDIF
409
410 IF(( bwl .GT. n-1 ) .OR.
411 $ ( bwl .LT. 0 ) ) THEN
412 info = -3
413 ENDIF
414
415 IF(( bwu .GT. n-1 ) .OR.
416 $ ( bwu .LT. 0 ) ) THEN
417 info = -4
418 ENDIF
419
420 IF( llda .LT. (bwl+bwu+1) ) THEN
421 info = -( 8*100 + 6 )
422 ENDIF
423
424 IF( nb .LE. 0 ) THEN
425 info = -( 8*100 + 4 )
426 ENDIF
427
428
429
430 IF( nprow .NE. 1 ) THEN
431 info = -( 8*100+2 )
432 ENDIF
433
434 IF( n .GT. np*nb-mod( ja-1, nb )) THEN
435 info = -( 2 )
437 $ 'PCDBDCMV, D&C alg.: only 1 block per proc',
438 $ -info )
439 RETURN
440 ENDIF
441
442 IF((ja+n-1.GT.nb) .AND. ( nb.LT.2*
max(bwl,bwu) ))
THEN
443 info = -( 8*100+4 )
445 $ 'PCDBDCMV, D&C alg.: NB too small',
446 $ -info )
447 RETURN
448 ENDIF
449
450
451
452
453 param_check( 17, 1 ) = descb(5)
454 param_check( 16, 1 ) = descb(4)
455 param_check( 15, 1 ) = descb(3)
456 param_check( 14, 1 ) = descb(2)
457 param_check( 13, 1 ) = descb(1)
458 param_check( 12, 1 ) = ib
459 param_check( 11, 1 ) = desca(5)
460 param_check( 10, 1 ) = desca(4)
461 param_check( 9, 1 ) = desca(3)
462 param_check( 8, 1 ) = desca(1)
463 param_check( 7, 1 ) = ja
464 param_check( 6, 1 ) = nrhs
465 param_check( 5, 1 ) = bwu
466 param_check( 4, 1 ) = bwl
467 param_check( 3, 1 ) = n
468 param_check( 2, 1 ) = idum3
469 param_check( 1, 1 ) = idum2
470
471 param_check( 17, 2 ) = 1105
472 param_check( 16, 2 ) = 1104
473 param_check( 15, 2 ) = 1103
474 param_check( 14, 2 ) = 1102
475 param_check( 13, 2 ) = 1101
476 param_check( 12, 2 ) = 10
477 param_check( 11, 2 ) = 805
478 param_check( 10, 2 ) = 804
479 param_check( 9, 2 ) = 803
480 param_check( 8, 2 ) = 801
481 param_check( 7, 2 ) = 7
482 param_check( 6, 2 ) = 5
483 param_check( 5, 2 ) = 4
484 param_check( 4, 2 ) = 3
485 param_check( 3, 2 ) = 2
486 param_check( 2, 2 ) = 15
487 param_check( 1, 2 ) = 1
488
489
490
491
492
493 IF( info.GE.0 ) THEN
494 info = bignum
495 ELSE IF( info.LT.-descmult ) THEN
496 info = -info
497 ELSE
498 info = -info * descmult
499 END IF
500
501
502
503 CALL globchk( ictxt, 17, param_check, 17,
504 $ param_check( 1, 3 ), info )
505
506
507
508
509 IF( info.EQ.bignum ) THEN
510 info = 0
511 ELSE IF( mod( info, descmult ) .EQ. 0 ) THEN
512 info = -info / descmult
513 ELSE
514 info = -info
515 END IF
516
517 IF( info.LT.0 ) THEN
518 CALL pxerbla( ictxt,
'PCDBDCMV', -info )
519 RETURN
520 END IF
521
522
523
524 IF( n.EQ.0 )
525 $ RETURN
526
527
528
529
530
531 part_offset = nb*( (ja-1)/(npcol*nb) )
532
533 IF ( (mycol-csrc) .LT. (ja-part_offset-1)/nb ) THEN
534 part_offset = part_offset + nb
535 ENDIF
536
537 IF ( mycol .LT. csrc ) THEN
538 part_offset = part_offset - nb
539 ENDIF
540
541
542
543
544
545
546
547 first_proc = mod( ( ja-1 )/nb+csrc, npcol )
548
549
550
551 ja_new = mod( ja-1, nb ) + 1
552
553
554
555 np_save = np
556 np = ( ja_new+n-2 )/nb + 1
557
558
559
560 CALL reshape( ictxt, int_one, ictxt_new, int_one,
561 $ first_proc, int_one, np )
562
563
564
565 ictxt_save = ictxt
566 ictxt = ictxt_new
567
568
569
570 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
571
572
573
574 IF( myrow .LT. 0 ) THEN
575 GOTO 1234
576 ENDIF
577
578
579
580
581
582
583 part_size = nb
584
585
586
587 my_num_cols =
numroc( n, part_size, mycol, 0, npcol )
588
589
590
591 IF ( mycol .EQ. 0 ) THEN
592 part_offset = part_offset+mod( ja_new-1, part_size )
593 my_num_cols = my_num_cols - mod(ja_new-1, part_size )
594 ENDIF
595
596
597
598 ofst = part_offset*llda
599
600
601
602 odd_size = my_num_cols
603 IF ( mycol .LT. np-1 ) THEN
604 odd_size = odd_size - max_bw
605 ENDIF
606
607
608
609
610
611 numroc_size =
612 $
numroc( n, part_size, mycol, 0, npcol)
613
614 DO 2279 j=1,nrhs
615 DO 4502 i=1,numroc_size
616 x( (j-1)*lldb + i ) = czero
617 4502 CONTINUE
618 2279 CONTINUE
619
620 DO 5642 i=1, (max_bw+2)*max_bw
621 work( i ) = czero
622 5642 CONTINUE
623
624
625
626
627
628
629 IF (
lsame( trans,
'N' ) )
THEN
630
631
632
633 IF( mycol .GT. 0 ) THEN
634
636 $
numroc( n, part_size, mycol, 0, npcol ) )
638 $
numroc( n, part_size, mycol-1, 0, npcol ) )
639
641 $
numroc( n, part_size, mycol-1, 0, npcol ) )
643 $
numroc( n, part_size, mycol, 0, npcol ) )
644 ENDIF
645
646 IF( mycol .LT. npcol-1 ) THEN
647
649 $
numroc( n, part_size, mycol+1, 0, npcol ) )
651 $
numroc( n, part_size, mycol, 0, npcol ) )
652
654 $
numroc( n, part_size, mycol, 0, npcol ) )
656 $
numroc( n, part_size, mycol+1, 0, npcol ) )
657 ENDIF
658
659
660
661
662 CALL cgbmv( trans, numroc_size, numroc_size, bwl, bwu, cone,
663 $ a( ofst+1 ), llda, b(part_offset+1), 1, czero,
664 $ x( part_offset+1 ), 1 )
665
666
667
668 IF ( mycol .LT. npcol-1 ) THEN
669
670
671
672 CALL ccopy( dl_n_n,
673 $ b( numroc_size-dl_n_n+1 ),
674 $ 1, work( max_bw*max_bw+1+bwl-dl_n_n ), 1 )
675
676 CALL ctrmv( 'U', 'N', 'N', bwl,
677 $ a( llda*( numroc_size-bwl )+1+bwu+bwl ), llda-1,
678 $ work( max_bw*max_bw+1 ), 1)
679
680
681
682 IF( dl_n_m .GT. dl_n_n ) THEN
683 DO 10 i = dl_n_m-dl_n_n, dl_n_m
684 work( max_bw*max_bw+i ) = 0
685 10 CONTINUE
686 ENDIF
687
688
689
690 CALL cgesd2d( ictxt, bwl, 1,
691 $ work( max_bw*max_bw+1 ), bwl, myrow, mycol+1 )
692
693 ENDIF
694
695 IF ( mycol .GT. 0 ) THEN
696
697 DO 20 i=1, max_bw*( max_bw+2 )
698 work( i ) = czero
699 20 CONTINUE
700
701
702
703
704
705 CALL ccopy( du_p_n, b( 1 ), 1,
706 $ work( max_bw*max_bw+1 ), 1)
707
708 CALL ctrmv(
709 $ 'L',
710 $ 'N',
711 $ 'N', bwu,
712 $ a( 1 ), llda-1,
713 $ work( max_bw*max_bw+1 ), 1 )
714
715
716
717 IF( du_p_n .GT. du_p_m ) THEN
718 DO 30 i=1, du_p_n-du_p_m
719 work( max_bw*max_bw+i ) = 0
720 30 CONTINUE
721 ENDIF
722
723
724
725 CALL cgesd2d( ictxt, bwu, 1, work(max_bw*max_bw+1 ),
726 $ bwu, myrow, mycol-1 )
727
728
729
730 CALL cgerv2d( ictxt, bwl, 1, work( max_bw*max_bw+1 ),
731 $ bwl, myrow, mycol-1 )
732
733
734
735 CALL caxpy( bwl, cone,
736 $ work( max_bw*max_bw+1 ), 1,
737 $ x( 1 ), 1 )
738
739 ENDIF
740
741
742
743 IF( mycol .LT. npcol-1 ) THEN
744
745
746
747 CALL cgerv2d( ictxt, bwu, 1, work( max_bw*max_bw+1 ),
748 $ bwu, myrow, mycol+1 )
749
750
751
752 CALL caxpy( bwu, cone,
753 $ work( max_bw*max_bw+1 ), 1,
754 $ x( numroc_size-bwu+1 ), 1)
755
756 ENDIF
757
758
759 ENDIF
760
761
762
763
764
765 IF (
lsame( trans,
'C' ) )
THEN
766
767
768
769 IF( mycol .GT. 0 ) THEN
770
772 $
numroc( n, part_size, mycol, 0, npcol ) )
774 $
numroc( n, part_size, mycol-1, 0, npcol ) )
775
777 $
numroc( n, part_size, mycol-1, 0, npcol ) )
779 $
numroc( n, part_size, mycol, 0, npcol ) )
780 ENDIF
781
782 IF( mycol .LT. npcol-1 ) THEN
783
785 $
numroc( n, part_size, mycol+1, 0, npcol ) )
787 $
numroc( n, part_size, mycol, 0, npcol ) )
788
790 $
numroc( n, part_size, mycol, 0, npcol ) )
792 $
numroc( n, part_size, mycol+1, 0, npcol ) )
793 ENDIF
794
795
796 IF( mycol .GT. 0 ) THEN
797
798
799
800
801 CALL clatcpy(
'L', bwu, bwu, a( ofst+1 ),
802 $ llda-1, work( 1 ), max_bw )
803
804
805
806 CALL ctrsd2d(ictxt, 'U', 'N',
807 $ bwu, bwu,
808 $ work( 1 ),
809 $ max_bw, myrow, mycol-1 )
810
811 ENDIF
812
813 IF( mycol .LT. npcol-1 ) THEN
814
815
816
817
819 $ a( llda*( numroc_size-bwl )+1+bwu+bwl ),
820 $ llda-1, work( 1 ), max_bw )
821
822
823
824 CALL ctrsd2d(ictxt, 'L', 'N',
825 $ bwl, bwl,
826 $ work( 1 ),
827 $ max_bw, myrow, mycol+1 )
828
829 ENDIF
830
831
832
833 CALL cgbmv( trans, numroc_size, numroc_size, bwl, bwu, cone,
834 $ a( ofst+1 ), llda, b(part_offset+1), 1, czero,
835 $ x( part_offset+1 ), 1 )
836
837
838
839 IF ( mycol .LT. npcol-1 ) THEN
840
841
842
843 CALL ccopy( dl_n_n,
844 $ b( numroc_size-dl_n_n+1 ),
845 $ 1, work( max_bw*max_bw+1+bwu-dl_n_n ), 1 )
846
847
848
849 CALL ctrrv2d(ictxt, 'U', 'N',
850 $ bwu, bwu,
851 $ work( 1 ), max_bw, myrow, mycol+1 )
852
853 CALL ctrmv( 'U', 'N', 'N', bwu,
854 $ work( 1 ), max_bw,
855 $ work( max_bw*max_bw+1 ), 1)
856
857
858
859 IF( dl_n_m .GT. dl_n_n ) THEN
860 DO 40 i = dl_n_m-dl_n_n, dl_n_m
861 work( max_bw*max_bw+i ) = 0
862 40 CONTINUE
863 ENDIF
864
865
866
867 CALL cgesd2d( ictxt, bwu, 1,
868 $ work( max_bw*max_bw+1 ), bwu, myrow, mycol+1 )
869
870 ENDIF
871
872 IF ( mycol .GT. 0 ) THEN
873
874 DO 50 i=1, max_bw*( max_bw+2 )
875 work( i ) = czero
876 50 CONTINUE
877
878
879
880
881
882 CALL ccopy( du_p_n, b( 1 ), 1,
883 $ work( max_bw*max_bw+1 ), 1)
884
885
886
887 CALL ctrrv2d(ictxt, 'L', 'N',
888 $ bwl, bwl,
889 $ work( 1 ), max_bw, myrow, mycol-1 )
890
891 CALL ctrmv(
892 $ 'L',
893 $ 'N',
894 $ 'N', bwl,
895 $ work( 1 ), max_bw,
896 $ work( max_bw*max_bw+1 ), 1 )
897
898
899
900 IF( du_p_n .GT. du_p_m ) THEN
901 DO 60 i=1, du_p_n-du_p_m
902 work( max_bw*max_bw+i ) = 0
903 60 CONTINUE
904 ENDIF
905
906
907
908 CALL cgesd2d( ictxt, bwl, 1, work(max_bw*max_bw+1 ),
909 $ bwl, myrow, mycol-1 )
910
911
912
913 CALL cgerv2d( ictxt, bwu, 1, work( max_bw*max_bw+1 ),
914 $ bwu, myrow, mycol-1 )
915
916
917
918 CALL caxpy( bwu, cone,
919 $ work( max_bw*max_bw+1 ), 1,
920 $ x( 1 ), 1 )
921
922 ENDIF
923
924
925
926 IF( mycol .LT. npcol-1 ) THEN
927
928
929
930 CALL cgerv2d( ictxt, bwl, 1, work( max_bw*max_bw+1 ),
931 $ bwl, myrow, mycol+1 )
932
933
934
935 CALL caxpy( bwl, cone,
936 $ work( max_bw*max_bw+1 ), 1,
937 $ x( numroc_size-bwl+1 ), 1)
938
939 ENDIF
940
941
942 ENDIF
943
944
945
946
947
948
949 IF( ictxt_save .NE. ictxt_new ) THEN
950 CALL blacs_gridexit( ictxt_new )
951 ENDIF
952
953 1234 CONTINUE
954
955
956
957 ictxt = ictxt_save
958 np = np_save
959
960
961 RETURN
962
963
964
subroutine clatcpy(uplo, m, n, a, lda, b, ldb)
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)