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+0 )
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 )
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 )
381 EXTERNAL blacs_get, blacs_gridexit, blacs_gridinfo,
383 $ zgemm, zgerv2d, zgesd2d, zlamov,
zlatcpy,
384 $ zpbtrf, zpotrf, zsyrk, ztbtrs, ztrmm, ztrrv2d,
385 $ ztrsd2d, ztrsm, ztrtrs
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 )
427 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
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 $
'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
626 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
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 ztrsd2d( 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 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,
920 $ af( odd_size*bw+mbw2+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 IF ( info.NE.0 )
THEN
1247 IF( mycol .EQ. npcol-1 )
THEN
1255 IF( (mod( mycol+1, 2 ) .EQ. 0) .AND. ( mycol .GT. 0 ) )
THEN
1257 CALL zgesd2d( ictxt, bw, bw,
1258 $ af( odd_size*bw+1 ),
1267 $ a( ofst+ odd_size*llda+1+bw ),
1268 $ llda-1, af( odd_size*bw+mbw2+1 ),
1273 IF( mycol.LT. 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 IF( mod( (mycol+1)/level_dist, 2) .NE. 0 )
GOTO 21
1303 IF( mycol-level_dist .GE. 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 IF( mycol+level_dist .LT. 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 IF( info.NE.0 )
THEN
1339 info = npcol + mycol
1347 IF( level_dist .EQ. 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 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )
THEN
1362 CALL zgerv2d( ictxt, bw, bw,
1363 $ af( odd_size*bw+1 ),
1364 $ bw, 0, comm_proc )
1366 IF( info .EQ. 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 IF( (mycol/level_dist .GT. 0 ).AND.
1399 $ ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) )
THEN
1401 IF( level_dist .GT. 1)
THEN
1406 CALL zgerv2d( ictxt, bw, bw,
1407 $ af( odd_size*bw+2*mbw2+1 ),
1408 $ bw, 0, mycol-level_dist/2 )
1413 IF( info.EQ.0 )
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 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )
THEN
1442 IF( ( mod( mycol/( 2*level_dist ),2 )) .EQ.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 IF( ictxt_save .NE. 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 IF( mycol.EQ.0 )
THEN
1497 CALL igebs2d( ictxt,
'A',
' ', 1, 1, info, 1 )
1499 CALL igebr2d( ictxt,
'A',
' ', 1, 1, info, 1, 0, 0 )