1 SUBROUTINE pzpbtrf( UPLO, N, BW, A, JA, DESCA, AF, LAF, WORK,
10 INTEGER BW, INFO, JA, LAF, LWORK, N
14 COMPLEX*16 A( * ), AF( * ), WORK( * )
351 DOUBLE PRECISION ONE, ZERO
352 parameter( one = 1.0d+0 )
353 parameter( zero = 0.0d
354 COMPLEX*16 CONE, CZERO
355 parameter( cone = ( 1.0d+0, 0.0d+0 ) )
356 parameter( czero = ( 0.0d+0, 0.0d+0 ) )
358 parameter( int_one = 1 )
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_
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,
372 $ next_tri_size_n, np, npcol, nprow, np_save,
378 INTEGER DESCA_1XP( 7 ), ( 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
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
THEN
478 $
'PZPBTRF, D&C alg.: only 1 block per proc',
483 IF((ja+n-1.GT.nb) .AND. ( nb.LT.2*bw ))
THEN
486 $
'PZPBTRF, D&C alg.: NB too small',
494 laf_min = (nb+2*bw)*bw
496 IF( laf .LT. laf_min )
THEN
501 $
'PZPBTRF: 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 $
'PZPBTRF: 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,
'PZPBTRF', -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
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 ztrsd2d( ictxt,
'U',
'N', next_tri_size_m,
716 CALL zpbtrf( 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 ztrtrs(
'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 zlatcpy(
'L', bw, bw, af( odd_size*bw+2*mbw2+1+bw-bw ),
745 $ bw, a(( ofst+(bw+1)+(odd_size-bw)*llda )),
756 CALL zherk( 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 ztrrv2d( ictxt,
'U',
'N', prev_tri_size_m,
778 $ prev_tri_size_n, af( 1 ), odd_size, 0,
785 CALL ztbtrs(
'L',
'N',
'N', odd_size, bw, bw, a( ofst + 1 ),
786 $ llda, af( 1 ), odd_size, info )
791 CALL zherk(
'L',
'C', bw, odd_size,
792 $ -one, af( 1 ), odd_size, zero,
793 $ af( 1 + (odd_size+2*bw)*bw), bw )
799 CALL zgesd2d( ictxt, bw, bw, af( odd_size*bw+2*mbw2+1 ), bw,
803 IF ( mycol .LT. np-1 )
THEN
816 $ af( odd_size-bw+1 ), odd_size,
817 $ af( (odd_size)*bw+1), bw )
819 CALL ztrmm(
'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 IF( mycol.EQ.0 )
THEN
839 CALL igebs2d( ictxt,
'A',
' ', 1, 1, info, 1 )
841 CALL igebr2d( ictxt,
'A',
' ', 1, 1, info, 1, 0, 0 )
844 IF ( info.NE.0 )
THEN
859 IF( mycol .EQ. npcol-1 )
THEN
867 IF( (mod( mycol+1, 2 ) .EQ. 0) .AND. ( mycol .GT. 0 ) )
THEN
869 CALL zgesd2d( ictxt, bw, bw,
870 $ af( odd_size*bw+1 ),
878 CALL zlamov(
'N', bw, bw,
879 $ a( ofst+odd_size*llda+1 ),
880 $ llda-1, af( odd_size*bw+mbw2+1 ),
885 IF( mycol.LT. npcol-1 )
THEN
887 CALL zgerv2d( ictxt, bw, bw,
888 $ af( odd_size*bw+2*mbw2+1 ),
894 CALL zaxpy( mbw2, cone,
895 $ af( odd_size*bw+2*mbw2+1 ),
896 $ 1, af( odd_size*bw+mbw2+1 ), 1 )
911 IF( mod( (mycol+1)/level_dist, 2) .NE. 0 )
GOTO 11
915 IF( mycol-level_dist .GE. 0 )
THEN
916 CALL zgerv2d( ictxt, bw, bw, work( 1 ),
917 $ bw, 0, mycol-level_dist )
919 CALL zaxpy( mbw2, cone, work( 1 ), 1,
926 IF( mycol+level_dist .LT. npcol-1 )
THEN
927 CALL zgerv2d( ictxt, bw, bw, work( 1 ),
928 $ bw, 0, mycol+level_dist )
930 CALL zaxpy( mbw2, cone, work( 1 ), 1,
931 $ af( odd_size*bw+mbw2+1 ), 1 )
935 level_dist = level_dist*2
947 CALL zpotrf(
'L', bw, af( odd_size*bw+mbw2+1 ),
959 IF( level_dist .EQ. 1 )
THEN
960 comm_proc = mycol + 1
965 CALL zlamov(
'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 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )
THEN
974 CALL zgerv2d( ictxt, bw, bw,
975 $ af( odd_size*bw+1 ),
978 IF( info .EQ. 0 )
THEN
984 CALL ztrsm(
'L',
'L',
'N',
'N', bw, bw, cone,
985 $ af( odd_size*bw+mbw2+1 ), bw,
986 $ af( odd_size*bw+1 ), bw )
993 CALL zherk(
'L',
'C', bw, bw, -one,
994 $ af( (odd_size)*bw+1 ), bw, zero,
999 CALL zgesd2d( ictxt, bw, bw, work( 1 ), bw,
1000 $ 0, mycol+level_dist )
1010 IF( (mycol/level_dist .GT. 0 ).AND.
1011 $ ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) )
THEN
1013 IF( level_dist .GT. 1)
THEN
1018 CALL zgerv2d( ictxt, bw, bw,
1019 $ af( odd_size*bw+2*mbw2+1 ),
1020 $ bw, 0, mycol-level_dist/2 )
1025 IF( info.EQ.0 )
THEN
1029 CALL ztrsm(
'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 zherk(
'L',
'N', bw, bw, -one,
1040 $ af( (odd_size+2*bw)*bw+1 ), bw, zero,
1045 CALL zgesd2d( ictxt, bw, bw, work( 1 ), bw,
1046 $ 0, mycol-level_dist )
1050 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )
THEN
1054 IF( ( mod( mycol/( 2*level_dist ),2 )) .EQ.0 )
THEN
1055 comm_proc = mycol + level_dist
1057 comm_proc = mycol - level_dist
1064 CALL zgemm(
'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 zgesd2d( ictxt, bw, bw, work( 1 ), bw,
1092 IF( mycol .GT. 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 IF( mycol .LT. 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 zpbtrf( uplo, odd_size, bw, a( ofst + 1),
1113 IF( info.NE.0 )
THEN
1119 IF ( mycol .LT. np-1 )
THEN
1124 CALL zlamov(
'L', bw, bw, a( ( ofst+1+odd_size*llda ) ),
1125 $ llda-1, af( odd_size*bw+2*mbw2+1+bw-bw ), bw )
1130 CALL ztrtrs(
'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 zlamov(
'L', bw, bw, af( odd_size*bw+2*mbw2+1+bw-bw ),
1137 $ bw, a(( ofst+1+odd_size*llda )), llda-1 )
1147 CALL zherk( 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 IF ( mycol .NE. 0 )
THEN
1168 CALL zlatcpy(
'L', prev_tri_size_n, prev_tri_size_m,
1169 $ a( ofst+1 ), llda-1, af( 1 ), odd_size )
1171 IF ( info.EQ.0 )
THEN
1173 CALL ztbtrs(
'U',
'C',
'N', odd_size, bw, bw,
1174 $ a( ofst + 1 ), llda,
1175 $ af( 1 ), odd_size, info )
1180 CALL zherk(
'L',
'C', bw, odd_size,
1181 $ -one, af( 1 ), odd_size, zero,
1182 $ af( 1 + (odd_size+2*bw)*bw), bw )
1188 CALL zgesd2d( ictxt, bw, bw, af( odd_size*bw+2*mbw2+1 ), bw,
1192 IF ( mycol .LT. np-1 )
THEN
1205 $ af( odd_size-bw+1 ), odd_size,
1206 $ af( (odd_size)*bw+1), bw )
1208 CALL ztrmm(
'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 IF( mycol.EQ.0 )
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 ZGESD2D( ICTXT, BW, BW,
1258 $ AF( ODD_SIZE*BW+1 ),
1266 CALL ZLATCPY( '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 ZGERV2D( ICTXT, BW, BW,
1276 $ AF( ODD_SIZE*BW+2*MBW2+1 ),
1282 CALL ZAXPY( 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 ZGERV2D( ICTXT, BW, BW, WORK( 1 ),
1305 $ BW, 0, MYCOL-LEVEL_DIST )
1307 CALL ZAXPY( MBW2, CONE, WORK( 1 ), 1,
1308 $ AF( ODD_SIZE*BW+MBW2+1 ), 1 )
1314.LT.
IF( MYCOL+LEVEL_DIST NPCOL-1 ) THEN
1315 CALL ZGERV2D( ICTXT, BW, BW, WORK( 1 ),
1316 $ BW, 0, MYCOL+LEVEL_DIST )
1318 CALL ZAXPY( MBW2, CONE, WORK( 1 ), 1,
1319 $ AF( ODD_SIZE*BW+MBW2+1 ), 1 )
1323 LEVEL_DIST = LEVEL_DIST*2
1335 CALL ZPOTRF( '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 ZLAMOV( '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 ZGERV2D( ICTXT, BW, BW,
1363 $ AF( ODD_SIZE*BW+1 ),
1364 $ BW, 0, COMM_PROC )
1366.EQ.
IF( INFO 0 ) THEN
1372 CALL ZTRSM( 'l
', 'l
', 'n
', 'n
', BW, BW, CONE,
1373 $ AF( ODD_SIZE*BW+MBW2+1 ), BW,
1374 $ AF( ODD_SIZE*BW+1 ), BW )
1381 CALL ZHERK( 'l
', 'c
', BW, BW, -ONE,
1382 $ AF( (ODD_SIZE)*BW+1 ), BW, ZERO,
1387 CALL ZGESD2D( 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 ZGERV2D( 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 ZTRSM( '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 ZHERK( 'l
', 'n
', BW, BW, -ONE,
1428 $ AF( (ODD_SIZE+2*BW)*BW+1 ), BW, ZERO,
1433 CALL ZGESD2D( 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 ZGEMM( '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 ZGESD2D( 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 )