1 SUBROUTINE pcpbtrf( UPLO, N, BW, A, JA, DESCA, AF, LAF, WORK,
10 INTEGER BW, , JA, LAF, LWORK, N
14 COMPLEX A( * ), AF( * ), WORK( * )
352 parameter( one = 1.0e+0 )
353 parameter( zero = 0.0e+0 )
355 parameter( cone = ( 1.0e+0, 0.0e+0 ) )
356 parameter( czero = ( 0.0e+0, 0.0e+0 ) )
358 parameter( int_one = 1 )
359 INTEGER DESCMULT, BIGNUM
360 parameter(descmult = 100, bignum = descmult * descmult)
361 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
362 $ lld_, mb_, m_, nb_, n_, rsrc_
363 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
364 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
365 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
368 INTEGER COMM_PROC, CSRC, FIRST_PROC, I, ICTXT,
369 $ ictxt_new, ictxt_save, idum1, idum3, ja_new,
370 $ laf_min, level_dist, llda, mbw2, mycol, myrow,
371 $ my_num_cols, nb, next_tri_size_m,
372 $ next_tri_size_n, np, npcol, nprow, np_save,
373 $ odd_size, ofst, part_offset, part_size,
374 $ prev_tri_size_m, prev_tri_size_n, return_code,
375 $ store_n_a, work_size_min
378 INTEGER DESCA_1XP( 7 ), PARAM_CHECK( 9, 3 )
390 EXTERNAL lsame, numroc
393 INTRINSIC ichar,
min, mod
408 IF( return_code .NE. 0)
THEN
409 info = -( 6*100 + 2 )
414 ictxt = desca_1xp( 2 )
415 csrc = desca_1xp( 5 )
417 llda = desca_1xp( 6 )
418 store_n_a = desca_1xp( 3 )
432 IF( lsame( uplo,
'U' ) )
THEN
434 ELSE IF ( lsame( uplo,
'L' ) )
THEN
440 IF( lwork .LT. -1)
THEN
442 ELSE IF ( lwork .EQ. -1 )
THEN
452 IF( n+ja-1 .GT. store_n_a )
THEN
453 info = -( 6*100 + 6 )
456 IF(( bw .GT. n-1 ) .OR.
457 $ ( bw .LT. 0 ) )
THEN
461 IF( llda .LT. (bw+1) )
THEN
462 info = -( 6*100 + 6 )
466 info = -( 6*100 + 4 )
471 IF( nprow .NE. 1 )
THEN
475 IF( n .GT. np*nb-mod( ja-1, nb ))
THEN
478 $
'PCPBTRF, D&C alg.: only 1 block per proc',
483 IF((ja+n-1.GT.nb) .AND. ( nb.LT.2*bw ))
THEN
486 $
'PCPBTRF, D&C alg.: NB too small',
494 laf_min = (nb+2*bw)*bw
496 IF( laf .LT. laf_min )
THEN
501 $
'PCPBTRF: auxiliary storage error ',
508 work_size_min = bw*bw
510 work( 1 ) = work_size_min
512 IF( lwork .LT. work_size_min )
THEN
513 IF( lwork .NE. -1 )
THEN
516 $
'PCPBTRF: worksize error ',
524 param_check( 9, 1 ) = desca(5)
525 param_check( 8, 1 ) = desca(4)
526 param_check( 7, 1 ) = desca(3)
527 param_check( 6, 1 ) = desca(1)
528 param_check( 5, 1 ) = ja
529 param_check( 4, 1 ) = bw
530 param_check( 3, 1 ) = n
531 param_check( 2, 1 ) = idum3
532 param_check( 1, 1 ) = idum1
534 param_check( 9, 2 ) = 605
535 param_check( 8, 2 ) = 604
536 param_check( 7, 2 ) = 603
537 param_check( 6, 2 ) = 601
538 param_check( 5, 2 ) = 5
539 param_check( 4, 2 ) = 3
540 param_check( 3, 2 ) = 2
541 param_check( 2, 2 ) = 10
542 param_check( 1, 2 ) = 1
550 ELSE IF( info.LT.-descmult )
THEN
553 info = -info * descmult
558 CALL globchk( ictxt, 9, param_check, 9,
559 $ param_check( 1, 3 ), info )
564 IF( info.EQ.bignum )
THEN
566 ELSE IF( mod( info, descmult ) .EQ. 0 )
THEN
567 info = -info / descmult
573 CALL pxerbla( ictxt,
'PCPBTRF', -info )
586 part_offset = nb*( (ja-1)/(npcol*nb) )
588 IF ( (mycol-csrc) .LT. (ja-part_offset-1)/nb )
THEN
589 part_offset = part_offset + nb
592 IF ( mycol .LT. csrc )
THEN
593 part_offset = part_offset - nb
602 first_proc = mod( ( ja-1 )/nb+csrc, npcol )
606 ja_new = mod( ja-1, nb ) + 1
611 np = ( ja_new+n-2 )/nb + 1
615 CALL reshape( ictxt, int_one, ictxt_new, int_one,
616 $ first_proc, int_one, np )
622 desca_1xp( 2 ) = ictxt_new
630 IF( myrow .LT. 0 )
THEN
643 my_num_cols = numroc( n, part_size, mycol, 0, npcol )
647 IF ( mycol .EQ. 0 )
THEN
648 part_offset = part_offset+mod( ja_new-1, part_size )
649 my_num_cols = my_num_cols - mod(ja_new-1, part_size )
654 ofst = part_offset*llda
658 odd_size = my_num_cols
659 IF ( mycol .LT. np-1 )
THEN
660 odd_size = odd_size - bw
672 DO 20 i=1, work_size_min
678 IF ( lsame( uplo,
'L' ) )
THEN
687 IF( mycol .GT. 0 )
THEN
688 prev_tri_size_m=
min( bw,
689 $ numroc( n, part_size, mycol, 0, npcol ) )
690 prev_tri_size_n=
min( bw,
691 $ numroc( n, part_size, mycol-1, 0, npcol ) )
694 IF( mycol .LT. npcol-1 )
THEN
695 next_tri_size_m=
min( bw,
696 $ numroc( n, part_size, mycol+1, 0, npcol ) )
697 next_tri_size_n=
min( bw,
698 $ numroc( n, part_size, mycol, 0, npcol ) )
701 IF ( mycol .LT. np-1 )
THEN
707 CALL ctrsd2d( ictxt,
'U',
'N', next_tri_size_m,
708 $ next_tri_size_n, a( ofst+odd_size*llda+(bw+1) ),
709 $ llda-1, 0, mycol+1 )
716 CALL cpbtrf( uplo, odd_size, bw, a( ofst + 1),
725 IF ( mycol .LT. np-1 )
THEN
731 $ a(( ofst+(bw+1)+(odd_size-bw)*llda )), llda-1,
732 $ af( odd_size*bw+2*mbw2+1+bw-bw ), bw )
736 CALL ctrtrs(
'L',
'N',
'N', bw, bw,
737 $ a( ofst+1+(odd_size-bw)*llda ), llda-1,
738 $ af( odd_size*bw+2*mbw2+1 ), bw, info )
744 CALL clatcpy(
'L', bw, bw, af( odd_size*bw+2*mbw2+1+bw-bw ),
745 $ bw, a(( ofst+(bw+1)+(odd_size-bw)*llda )),
756 CALL cherk( uplo,
'C', bw, bw, -one,
757 $ af( odd_size*bw+2*mbw2+1 ), bw, one,
758 $ a( ofst+1+odd_size*llda ), llda-1 )
767 IF ( mycol .NE. 0 )
THEN
777 CALL ctrrv2d( ictxt,
'U',
'N', prev_tri_size_m,
778 $ prev_tri_size_n, af( 1 ), odd_size, 0,
785 CALL ctbtrs( 'l
', 'n
', 'n
', ODD_SIZE, BW, BW, A( OFST + 1 ),
786 $ LLDA, AF( 1 ), ODD_SIZE, INFO )
791 CALL CHERK( 'l
', 'c
', BW, ODD_SIZE,
792 $ -ONE, AF( 1 ), ODD_SIZE, ZERO,
793 $ AF( 1 + (ODD_SIZE+2*BW)*BW), BW )
799 CALL CGESD2D( ICTXT, BW, BW, AF( ODD_SIZE*BW+2*MBW2+1 ), BW,
803.LT.
IF ( MYCOL NP-1 ) THEN
815 CALL CLATCPY( 'n
', BW, BW,
816 $ AF( ODD_SIZE-BW+1 ), ODD_SIZE,
817 $ AF( (ODD_SIZE)*BW+1), BW )
819 CALL CTRMM( 'r
', 'u
', 'c
', 'n
', BW, BW, -CONE,
820 $ A( ( OFST+(BW+1)+(ODD_SIZE-BW)*LLDA ) ), LLDA-1,
821 $ AF( (ODD_SIZE)*BW+1 ), BW )
835 CALL IGAMX2D( ICTXT, 'a
', ' ', 1, 1, INFO, 1, INFO, INFO,
838.EQ.
IF( MYCOL0 ) THEN
839 CALL IGEBS2D( ICTXT, 'a
', ' ', 1, 1, INFO, 1 )
841 CALL IGEBR2D( ICTXT, 'a
', ' ', 1, 1, INFO, 1, 0, 0 )
844.NE.
IF ( INFO0 ) THEN
859.EQ.
IF( MYCOL NPCOL-1 ) THEN
867.EQ..AND..GT.
IF( (MOD( MYCOL+1, 2 ) 0) ( MYCOL 0 ) ) THEN
869 CALL CGESD2D( ICTXT, BW, BW,
870 $ AF( ODD_SIZE*BW+1 ),
878 CALL CLAMOV( 'n
', BW, BW,
879 $ A( OFST+ODD_SIZE*LLDA+1 ),
880 $ LLDA-1, AF( ODD_SIZE*BW+MBW2+1 ),
885.LT.
IF( MYCOL NPCOL-1 ) THEN
887 CALL CGERV2D( ICTXT, BW, BW,
888 $ AF( ODD_SIZE*BW+2*MBW2+1 ),
894 CALL CAXPY( MBW2, CONE,
895 $ AF( ODD_SIZE*BW+2*MBW2+1 ),
896 $ 1, AF( ODD_SIZE*BW+MBW2+1 ), 1 )
911.NE.
IF( MOD( (MYCOL+1)/LEVEL_DIST, 2) 0 ) GOTO 11
915.GE.
IF( MYCOL-LEVEL_DIST 0 ) THEN
916 CALL CGERV2D( ICTXT, BW, BW, WORK( 1 ),
917 $ BW, 0, MYCOL-LEVEL_DIST )
919 CALL CAXPY( MBW2, CONE, WORK( 1 ), 1,
920 $ AF( ODD_SIZE*BW+MBW2+1 ), 1 )
926.LT.
IF( MYCOL+LEVEL_DIST NPCOL-1 ) THEN
927 CALL CGERV2D( ICTXT, BW, BW, WORK( 1 ),
928 $ BW, 0, MYCOL+LEVEL_DIST )
930 CALL CAXPY( MBW2, CONE, WORK( 1 ), 1,
931 $ AF( ODD_SIZE*BW+MBW2+1 ), 1 )
935 LEVEL_DIST = LEVEL_DIST*2
947 CALL CPOTRF( 'l
', BW, AF( ODD_SIZE*BW+MBW2+1 ),
959.EQ.
IF( LEVEL_DIST 1 )THEN
960 COMM_PROC = MYCOL + 1
965 CALL CLAMOV( 'n
', BW, BW, AF( ODD_SIZE*BW+1 ), BW,
966 $ AF( ODD_SIZE*BW+2*MBW2+1 ), BW )
969 COMM_PROC = MYCOL + LEVEL_DIST/2
972.LE.
IF( MYCOL/LEVEL_DIST (NPCOL-1)/LEVEL_DIST-2 )THEN
974 CALL CGERV2D( ICTXT, BW, BW,
975 $ AF( ODD_SIZE*BW+1 ),
978.EQ.
IF( INFO 0 ) THEN
984 CALL CTRSM( 'l
', 'l
', 'n
', 'n
', BW, BW, CONE,
985 $ AF( ODD_SIZE*BW+MBW2+1 ), BW,
986 $ AF( ODD_SIZE*BW+1 ), BW )
993 CALL CHERK( 'l
', 'c
', BW, BW, -ONE,
994 $ AF( (ODD_SIZE)*BW+1 ), BW, ZERO,
999 CALL CGESD2D( ICTXT, BW, BW, WORK( 1 ), BW,
1000 $ 0, MYCOL+LEVEL_DIST )
1010.GT..AND.
IF( (MYCOL/LEVEL_DIST 0 )
1011.LE.
$ ( MYCOL/LEVEL_DIST (NPCOL-1)/LEVEL_DIST-1 ) ) THEN
1013.GT.
IF( LEVEL_DIST 1)THEN
1018 CALL CGERV2D( ICTXT, BW, BW,
1019 $ AF( ODD_SIZE*BW+2*MBW2+1 ),
1020 $ BW, 0, MYCOL-LEVEL_DIST/2 )
1025.EQ.
IF( INFO0 ) THEN
1029 CALL CTRSM( 'r
', 'l
', 'c
', 'n
', BW, BW, CONE,
1030 $ AF( ODD_SIZE*BW+MBW2+1 ), BW,
1031 $ AF( ODD_SIZE*BW+2*MBW2+1 ), BW )
1039 CALL CHERK( 'l
', 'n
', BW, BW, -ONE,
1040 $ AF( (ODD_SIZE+2*BW)*BW+1 ), BW, ZERO,
1045 CALL CGESD2D( ICTXT, BW, BW, WORK( 1 ), BW,
1046 $ 0, MYCOL-LEVEL_DIST )
1050.LE.
IF( MYCOL/LEVEL_DIST (NPCOL-1)/LEVEL_DIST-2 ) THEN
1054.EQ.
IF( ( MOD( MYCOL/( 2*LEVEL_DIST ),2 )) 0 ) THEN
1055 COMM_PROC = MYCOL + LEVEL_DIST
1057 COMM_PROC = MYCOL - LEVEL_DIST
1064 CALL CGEMM( 'n
', 'n
', BW, BW, BW, -CONE,
1065 $ AF( ODD_SIZE*BW+2*MBW2+1 ), BW,
1066 $ AF( ODD_SIZE*BW+1 ), BW, CZERO, WORK( 1 ),
1071 CALL CGESD2D( ICTXT, BW, BW, WORK( 1 ), BW,
1092.GT.
IF( MYCOL 0 ) THEN
1093 PREV_TRI_SIZE_M= MIN( BW,
1094 $ NUMROC( N, PART_SIZE, MYCOL, 0, NPCOL ) )
1095 PREV_TRI_SIZE_N=MIN( BW,
1096 $ NUMROC( N, PART_SIZE, MYCOL-1, 0, NPCOL ) )
1099.LT.
IF( MYCOL NPCOL-1 ) THEN
1100 NEXT_TRI_SIZE_M=MIN( BW,
1101 $ NUMROC( N, PART_SIZE, MYCOL+1, 0, NPCOL ) )
1102 NEXT_TRI_SIZE_N= MIN( BW,
1103 $ NUMROC( N, PART_SIZE, MYCOL, 0, NPCOL ) )
1110 CALL CPBTRF( UPLO, ODD_SIZE, BW, A( OFST + 1),
1113.NE.
IF( INFO0 ) THEN
1119.LT.
IF ( MYCOL NP-1 ) THEN
1124 CALL CLAMOV( 'l
', BW, BW, A( ( OFST+1+ODD_SIZE*LLDA ) ),
1125 $ LLDA-1, AF( ODD_SIZE*BW+2*MBW2+1+BW-BW ), BW )
1130 CALL CTRTRS( 'u
', 'c
', 'n
', BW, BW,
1131 $ A( OFST+BW+1+(ODD_SIZE-BW)*LLDA ), LLDA-1,
1132 $ AF( ODD_SIZE*BW+2*MBW2+1 ), BW, INFO )
1136 CALL CLAMOV( 'l
', BW, BW, AF( ODD_SIZE*BW+2*MBW2+1+BW-BW ),
1137 $ BW, A(( OFST+1+ODD_SIZE*LLDA )), LLDA-1 )
1147 CALL CHERK( UPLO, 'c
', BW, BW, -ONE,
1148 $ AF( ODD_SIZE*BW+2*MBW2+1 ), BW, ONE,
1149 $ A( OFST+BW+1+ODD_SIZE*LLDA ), LLDA-1 )
1158.NE.
IF ( MYCOL 0 ) THEN
1168 CALL CLATCPY( 'l
', PREV_TRI_SIZE_N, PREV_TRI_SIZE_M,
1169 $ A( OFST+1 ), LLDA-1, AF( 1 ), ODD_SIZE )
1171.EQ.
IF ( INFO0 ) THEN
1173 CALL CTBTRS( 'u
', 'c
', 'n
', ODD_SIZE, BW, BW,
1174 $ A( OFST + 1 ), LLDA,
1175 $ AF( 1 ), ODD_SIZE, INFO )
1180 CALL CHERK( 'l
', 'c
', BW, ODD_SIZE,
1181 $ -ONE, AF( 1 ), ODD_SIZE, ZERO,
1182 $ AF( 1 + (ODD_SIZE+2*BW)*BW), BW )
1188 CALL CGESD2D( ICTXT, BW, BW, AF( ODD_SIZE*BW+2*MBW2+1 ), BW,
1192.LT.
IF ( MYCOL NP-1 ) THEN
1204 CALL CLATCPY( 'n
', BW, BW,
1205 $ AF( ODD_SIZE-BW+1 ), ODD_SIZE,
1206 $ AF( (ODD_SIZE)*BW+1), BW )
1208 CALL CTRMM( 'r
', 'l
', 'n
', 'n
', BW, BW, -CONE,
1209 $ A( ( OFST+1+ODD_SIZE*LLDA ) ), LLDA-1,
1210 $ AF( (ODD_SIZE)*BW+1 ), BW )
1223 CALL IGAMX2D( ICTXT, 'a
', ' ', 1, 1, INFO, 1, INFO, INFO,
1226.EQ.
IF( MYCOL0 ) THEN
1227 CALL IGEBS2D( ICTXT, 'a
', ' ', 1, 1, INFO, 1 )
1229 CALL IGEBR2D( ICTXT, 'a
', ' ', 1, 1, INFO, 1, 0, 0 )
1232.NE.
IF ( INFO0 ) THEN
1247.EQ.
IF( MYCOL NPCOL-1 ) THEN
1255.EQ..AND..GT.
IF( (MOD( MYCOL+1, 2 ) 0) ( MYCOL 0 ) ) THEN
1257 CALL CGESD2D( ICTXT, BW, BW,
1258 $ AF( ODD_SIZE*BW+1 ),
1266 CALL CLATCPY( 'u
', BW, BW,
1267 $ A( OFST+ ODD_SIZE*LLDA+1+BW ),
1268 $ LLDA-1, AF( ODD_SIZE*BW+MBW2+1 ),
1273.LT.
IF( MYCOL NPCOL-1 ) THEN
1275 CALL CGERV2D( ICTXT, BW, BW,
1276 $ AF( ODD_SIZE*BW+2*MBW2+1 ),
1282 CALL CAXPY( MBW2, CONE,
1283 $ AF( ODD_SIZE*BW+2*MBW2+1 ),
1284 $ 1, AF( ODD_SIZE*BW+MBW2+1 ), 1 )
1299.NE.
IF( MOD( (MYCOL+1)/LEVEL_DIST, 2) 0 ) GOTO 21
1303.GE.
IF( MYCOL-LEVEL_DIST 0 ) THEN
1304 CALL CGERV2D( ICTXT, BW, BW, WORK( 1 ),
1305 $ BW, 0, MYCOL-LEVEL_DIST )
1307 CALL CAXPY( MBW2, CONE, WORK( 1 ), 1,
1308 $ AF( ODD_SIZE*BW+MBW2+1 ), 1 )
1314.LT.
IF( MYCOL+LEVEL_DIST NPCOL-1 ) THEN
1315 CALL CGERV2D( ICTXT, BW, BW, WORK( 1 ),
1316 $ BW, 0, MYCOL+LEVEL_DIST )
1318 CALL CAXPY( MBW2, CONE, WORK( 1 ), 1,
1319 $ AF( ODD_SIZE*BW+MBW2+1 ), 1 )
1323 LEVEL_DIST = LEVEL_DIST*2
1335 CALL CPOTRF( 'l
', BW, AF( ODD_SIZE*BW+MBW2+1 ),
1338.NE.
IF( INFO0 ) THEN
1339 INFO = NPCOL + MYCOL
1347.EQ.
IF( LEVEL_DIST 1 )THEN
1348 COMM_PROC = MYCOL + 1
1353 CALL CLAMOV( 'n
', BW, BW, AF( ODD_SIZE*BW+1 ), BW,
1354 $ AF( ODD_SIZE*BW+2*MBW2+1 ), BW )
1357 COMM_PROC = MYCOL + LEVEL_DIST/2
1360.LE.
IF( MYCOL/LEVEL_DIST (NPCOL-1)/LEVEL_DIST-2 )THEN
1362 CALL CGERV2D( ICTXT, BW, BW,
1363 $ AF( ODD_SIZE*BW+1 ),
1364 $ BW, 0, COMM_PROC )
1366.EQ.
IF( INFO 0 ) THEN
1372 CALL CTRSM( 'l
', 'l
', 'n
', 'n
', BW, BW, CONE,
1373 $ AF( ODD_SIZE*BW+MBW2+1 ), BW,
1374 $ AF( ODD_SIZE*BW+1 ), BW )
1381 CALL CHERK( 'l
', 'c
', BW, BW, -ONE,
1382 $ AF( (ODD_SIZE)*BW+1 ), BW, ZERO,
1387 CALL CGESD2D( ICTXT, BW, BW, WORK( 1 ), BW,
1388 $ 0, MYCOL+LEVEL_DIST )
1398.GT..AND.
IF( (MYCOL/LEVEL_DIST 0 )
1399.LE.
$ ( MYCOL/LEVEL_DIST (NPCOL-1)/LEVEL_DIST-1 ) ) THEN
1401.GT.
IF( LEVEL_DIST 1)THEN
1406 CALL CGERV2D( ICTXT, BW, BW,
1407 $ AF( ODD_SIZE*BW+2*MBW2+1 ),
1408 $ BW, 0, MYCOL-LEVEL_DIST/2 )
1413.EQ.
IF( INFO0 ) THEN
1417 CALL CTRSM( 'r
', 'l
', 'c
', 'n
', BW, BW, CONE,
1418 $ AF( ODD_SIZE*BW+MBW2+1 ), BW,
1419 $ AF( ODD_SIZE*BW+2*MBW2+1 ), BW )
1427 CALL CHERK( 'l
', 'n
', BW, BW, -ONE,
1428 $ AF( (ODD_SIZE+2*BW)*BW+1 ), BW, ZERO,
1433 CALL CGESD2D( ICTXT, BW, BW, WORK( 1 ), BW,
1434 $ 0, MYCOL-LEVEL_DIST )
1438.LE.
IF( MYCOL/LEVEL_DIST (NPCOL-1)/LEVEL_DIST-2 ) THEN
1442.EQ.
IF( ( MOD( MYCOL/( 2*LEVEL_DIST ),2 )) 0 ) THEN
1443 COMM_PROC = MYCOL + LEVEL_DIST
1445 COMM_PROC = MYCOL - LEVEL_DIST
1452 CALL CGEMM( 'n
', 'n
', BW, BW, BW, -CONE,
1453 $ AF( ODD_SIZE*BW+2*MBW2+1 ), BW,
1454 $ AF( ODD_SIZE*BW+1 ), BW, CZERO, WORK( 1 ),
1459 CALL CGESD2D( ICTXT, BW, BW, WORK( 1 ), BW,
1476.NE.
IF( ICTXT_SAVE ICTXT_NEW ) THEN
1477 CALL BLACS_GRIDEXIT( ICTXT_NEW )
1489 WORK( 1 ) = WORK_SIZE_MIN
1493 CALL IGAMX2D( ICTXT, 'a
', ' ', 1, 1, INFO, 1, INFO, INFO,
1496.EQ.
IF( MYCOL0 ) THEN
1497 CALL IGEBS2D( ICTXT, 'a
', ' ', 1, 1, INFO, 1 )
1499 CALL IGEBR2D( ICTXT, 'a
', ' ', 1, 1, INFO, 1, 0, 0 )