1 SUBROUTINE pdpbtrf( UPLO, N, BW, A, JA, DESCA, AF, LAF, WORK,
10 INTEGER BW, INFO, JA, LAF, LWORK, N
14 DOUBLE PRECISION A( * ), AF( * ), WORK( * )
350 parameter( one = 1.0d+0 )
351 DOUBLE PRECISION ZERO
352 parameter( zero = 0.0d+0 )
354 parameter( int_one = 1 )
355 INTEGER DESCMULT, BIGNUM
356 parameter( descmult = 100, bignum = descmult*descmult )
357 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
358 $ lld_, mb_, m_, nb_, n_, rsrc_
359 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
360 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
361 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
364 INTEGER COMM_PROC, CSRC, FIRST_PROC, I, ICTXT,
365 $ ictxt_new, ictxt_save, idum1, idum3, ja_new,
366 $ laf_min, level_dist, llda, mbw2, mycol, myrow,
367 $ my_num_cols, nb, next_tri_size_m,
368 $ next_tri_size_n, np, npcol, nprow, np_save,
369 $ odd_size, ofst, part_offset, part_size,
370 $ prev_tri_size_m, prev_tri_size_n, return_code,
371 $ store_n_a, work_size_min
374 INTEGER DESCA_1XP( 7 ), PARAM_CHECK( 9, 3 )
377 EXTERNAL blacs_gridexit, blacs_gridinfo, daxpy,
379 $
dlatcpy, dpbtrf, dpotrf, dsyrk, dtbtrs, dtrmm,
380 $ dtrrv2d, dtrsd2d, dtrsm, dtrtrs,
globchk,
386 EXTERNAL lsame, numroc
389 INTRINSIC ichar,
min, mod
404 IF( return_code.NE.0 )
THEN
410 ictxt = desca_1xp( 2 )
411 csrc = desca_1xp( 5 )
413 llda = desca_1xp( 6 )
414 store_n_a = desca_1xp( 3 )
423 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
428 IF( lsame( uplo,
'U' ) )
THEN
430 ELSE IF( lsame( uplo,
'L' ) )
THEN
436 IF( lwork.LT.-1 )
THEN
438 ELSE IF( lwork.EQ.-1 )
THEN
448 IF( n+ja-1.GT.store_n_a )
THEN
452 IF( ( bw.GT.n-1 ) .OR. ( bw.LT.0 ) )
THEN
456 IF( llda.LT.( bw+1 ) )
THEN
466 IF( nprow.NE.1 )
THEN
470 IF( n.GT.np*nb-mod( ja-1, nb ) )
THEN
472 CALL pxerbla( ictxt,
'PDPBTRF, D&C alg.: only 1 block per proc'
477 IF( ( ja+n-1.GT.nb ) .AND. ( nb.LT.2*bw ) )
THEN
479 CALL pxerbla( ictxt,
'PDPBTRF, D&C alg.: NB too small', -info )
486 laf_min = ( nb+2*bw )*bw
488 IF( laf.LT.laf_min )
THEN
492 CALL pxerbla( ictxt,
'PDPBTRF: auxiliary storage error ',
499 work_size_min = bw*bw
501 work( 1 ) = work_size_min
503 IF( lwork.LT.work_size_min )
THEN
504 IF( lwork.NE.-1 )
THEN
506 CALL pxerbla( ictxt,
'PDPBTRF: worksize error ', -info )
513 param_check( 9, 1 ) = desca( 5 )
514 param_check( 8, 1 ) = desca( 4 )
515 param_check( 7, 1 ) = desca( 3 )
516 param_check( 6, 1 ) = desca( 1 )
517 param_check( 5, 1 ) = ja
518 param_check( 4, 1 ) = bw
519 param_check( 3, 1 ) = n
520 param_check( 2, 1 ) = idum3
521 param_check( 1, 1 ) = idum1
523 param_check( 9, 2 ) = 605
524 param_check( 8, 2 ) = 604
525 param_check( 7, 2 ) = 603
526 param_check( 6, 2 ) = 601
527 param_check( 5, 2 ) = 5
528 param_check( 4, 2 ) = 3
529 param_check( 3, 2 ) = 2
530 param_check( 2, 2 ) = 10
531 param_check( 1, 2 ) = 1
539 ELSE IF( info.LT.-descmult )
THEN
542 info = -info*descmult
547 CALL globchk( ictxt, 9, param_check, 9, param_check( 1, 3 ),
553 IF( info.EQ.bignum )
THEN
555 ELSE IF( mod( info, descmult ).EQ.0 )
THEN
556 info = -info / descmult
562 CALL pxerbla( ictxt,
'PDPBTRF', -info )
575 part_offset = nb*( ( ja-1 ) / ( npcol*nb ) )
577 IF( ( mycol-csrc ).LT.( ja-part_offset-1 ) / nb )
THEN
578 part_offset = part_offset + nb
581 IF( mycol.LT.csrc )
THEN
582 part_offset = part_offset - nb
591 first_proc = mod( ( ja-1 ) / nb+csrc, npcol )
595 ja_new = mod( ja-1, nb ) + 1
600 np = ( ja_new+n-2 ) / nb + 1
604 CALL reshape( ictxt, int_one, ictxt_new, int_one, first_proc,
611 desca_1xp( 2 ) = ictxt_new
615 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
619 IF( myrow.LT.0 )
THEN
632 my_num_cols = numroc( n, part_size, mycol, 0, npcol )
636 IF( mycol.EQ.0 )
THEN
637 part_offset = part_offset + mod( ja_new-1, part_size )
638 my_num_cols = my_num_cols - mod( ja_new-1, part_size )
643 ofst = part_offset*llda
647 odd_size = my_num_cols
648 IF( mycol.LT.np-1 )
THEN
649 odd_size = odd_size - bw
661 DO 20 i = 1, work_size_min
667 IF( lsame( uplo,
'L' ) )
THEN
676 IF( mycol.GT.0 )
THEN
677 prev_tri_size_m =
min( bw, numroc( n, part_size, mycol, 0,
679 prev_tri_size_n =
min( bw, numroc( n, part_size, mycol-1, 0,
683 IF( mycol.LT.npcol-1 )
THEN
684 next_tri_size_m =
min( bw, numroc( n, part_size, mycol+1, 0,
686 next_tri_size_n =
min( bw, numroc( n, part_size, mycol, 0,
690 IF( mycol.LT.np-1 )
THEN
696 CALL dtrsd2d( ictxt,
'U',
'N', next_tri_size_m,
697 $ next_tri_size_n, a( ofst+odd_size*llda+( bw+
698 $ 1 ) ), llda-1, 0, mycol+1 )
705 CALL dpbtrf( uplo, odd_size, bw, a( ofst+1 ), llda, info )
713 IF( mycol.LT.np-1 )
THEN
718 CALL dlatcpy(
'U', bw, bw, a( ( ofst+( bw+1 )+( odd_size-
719 $ bw )*llda ) ), llda-1,
720 $ af( odd_size*bw+2*mbw2+1+bw-bw ), bw )
724 CALL dtrtrs(
'L',
'N',
'N', bw, bw,
725 $ a( ofst+1+( odd_size-bw )*llda ), llda-1,
726 $ af( odd_size*bw+2*mbw2+1 ), bw, info )
732 CALL dlatcpy(
'L', bw, bw, af( odd_size*bw+2*mbw2+1+bw-bw ),
733 $ bw, a( ( ofst+( bw+1 )+( odd_size-bw )*
744 CALL dsyrk( uplo,
'T', bw, bw, -one,
745 $ af( odd_size*bw+2*mbw2+1 ), bw, one,
746 $ a( ofst+1+odd_size*llda ), llda-1 )
755 IF( mycol.NE.0 )
THEN
765 CALL dtrrv2d( ictxt,
'U',
'N', prev_tri_size_m,
766 $ prev_tri_size_n, af( 1 ), odd_size, 0,
773 CALL dtbtrs(
'L',
'N',
'N', odd_size, bw, bw,
774 $ a( ofst+1 ), llda, af( 1 ), odd_size, info )
779 CALL dsyrk(
'L',
'T', bw, odd_size, -one, af( 1 ),
780 $ odd_size, zero, af( 1+( odd_size+2*bw )*bw ),
787 CALL dgesd2d( ictxt, bw, bw, af( odd_size*bw+2*mbw2+1 ),
791 IF( mycol.LT.np-1 )
THEN
803 CALL dlatcpy(
'N', bw, bw, af( odd_size-bw+1 ),
804 $ odd_size, af( ( odd_size )*bw+1 ), bw )
806 CALL dtrmm(
'R',
'U',
'T',
'N', bw, bw, -one,
807 $ a( ( ofst+( bw+1 )+( odd_size-bw )*
808 $ llda ) ), llda-1, af( ( odd_size )*bw+1 ),
823 CALL igamx2d( ictxt,
'A',
' ', 1, 1, info, 1, info, info, -1,
826 IF( mycol.EQ.0 )
THEN
827 CALL igebs2d( ictxt,
'A',
' ', 1, 1, info, 1 )
829 CALL igebr2d( ictxt,
'A',
' ', 1, 1, info, 1, 0, 0 )
847 IF( mycol.EQ.npcol-1 )
THEN
855 IF( ( mod( mycol+1, 2 ).EQ.0 ) .AND. ( mycol.GT.0 ) )
THEN
857 CALL dgesd2d( ictxt, bw, bw, af( odd_size*bw+1 ), bw, 0,
865 CALL dlamov(
'N', bw, bw, a( ofst+odd_size*llda+1 ), llda-1,
866 $ af( odd_size*bw+mbw2+1 ), bw )
870 IF( mycol.LT.npcol-1 )
THEN
872 CALL dgerv2d( ictxt, bw, bw, af( odd_size*bw+2*mbw2+1 ), bw,
877 CALL daxpy( mbw2, one, af( odd_size*bw+2*mbw2+1 ), 1,
878 $ af( odd_size*bw+mbw2+1 ), 1 )
893 IF( mod( ( mycol+1 ) / level_dist, 2 ).NE.0 )
898 IF( mycol-level_dist.GE.0 )
THEN
899 CALL dgerv2d( ictxt, bw, bw, work( 1 ), bw, 0,
902 CALL daxpy( mbw2, one, work( 1 ), 1,
903 $ af( odd_size*bw+mbw2+1 ), 1 )
909 IF( mycol+level_dist.LT.npcol-1 )
THEN
910 CALL dgerv2d( ictxt, bw, bw, work( 1 ), bw, 0,
913 CALL daxpy( mbw2, one, work( 1 ), 1,
914 $ af( odd_size*bw+mbw2+1 ), 1 )
918 level_dist = level_dist*2
930 CALL dpotrf(
'L', bw, af( odd_size*bw+mbw2+1 ), bw, info )
941 IF( level_dist.EQ.1 )
THEN
942 comm_proc = mycol + 1
947 CALL dlamov(
'N', bw, bw, af( odd_size*bw+1 ), bw,
948 $ af( odd_size*bw+2*mbw2+1 ), bw )
951 comm_proc = mycol + level_dist / 2
954 IF( mycol / level_dist.LE.( npcol-1 ) / level_dist-2 )
THEN
956 CALL dgerv2d( ictxt, bw, bw, af( odd_size*bw+1 ), bw, 0,
965 CALL dtrsm(
'L',
'L',
'N',
'N', bw, bw, one,
966 $ af( odd_size*bw+mbw2+1 ), bw,
967 $ af( odd_size*bw+1 ), bw )
974 CALL dsyrk(
'L',
'T', bw, bw, -one, af( ( odd_size )*bw+1 ),
975 $ bw, zero, work( 1 ), bw )
979 CALL dgesd2d( ictxt, bw, bw, work( 1 ), bw, 0,
990 IF( ( mycol / level_dist.GT.0 ) .AND.
991 $ ( mycol / level_dist.LE.( npcol-1 ) / level_dist-1 ) )
THEN
993 IF( level_dist.GT.1 )
THEN
998 CALL dgerv2d( ictxt, bw, bw, af( odd_size*bw+2*mbw2+1 ),
999 $ bw, 0, mycol-level_dist / 2 )
1004 IF( info.EQ.0 )
THEN
1008 CALL dtrsm(
'R',
'L',
'T',
'N', bw, bw, one,
1009 $ af( odd_size*bw+mbw2+1 ), bw,
1010 $ af( odd_size*bw+2*mbw2+1 ), bw )
1018 CALL dsyrk(
'L',
'N', bw, bw, -one,
1019 $ af( ( odd_size+2*bw )*bw+1 ), bw, zero,
1024 CALL dgesd2d( ictxt, bw, bw, work( 1 ), bw, 0,
1025 $ mycol-level_dist )
1029 IF( mycol / level_dist.LE.( npcol-1 ) / level_dist-2 )
THEN
1033 IF( ( mod( mycol / ( 2*level_dist ), 2 ) ).EQ.0 )
THEN
1034 comm_proc = mycol + level_dist
1036 comm_proc = mycol - level_dist
1043 CALL dgemm(
'N',
'N', bw, bw, bw, -one,
1044 $ af( odd_size*bw+2*mbw2+1 ), bw,
1045 $ af( odd_size*bw+1 ), bw, zero, work( 1 ),
1050 CALL dgesd2d( ictxt, bw, bw, work( 1 ), bw, 0,
1071 IF( mycol.GT.0 )
THEN
1072 prev_tri_size_m =
min( bw, numroc( n, part_size, mycol, 0,
1074 prev_tri_size_n =
min( bw, numroc( n, part_size, mycol-1, 0,
1078 IF( mycol.LT.npcol-1 )
THEN
1079 next_tri_size_m =
min( bw, numroc( n, part_size, mycol+1, 0,
1081 next_tri_size_n =
min( bw, numroc( n, part_size, mycol, 0,
1089 CALL dpbtrf( uplo, odd_size, bw, a( ofst+1 ), llda, info )
1091 IF( info.NE.0 )
THEN
1097 IF( mycol.LT.np-1 )
THEN
1102 CALL dlamov(
'L', bw, bw, a( ( ofst+1+odd_size*llda ) ),
1103 $ llda-1, af( odd_size*bw+2*mbw2+1+bw-bw ), bw )
1108 CALL dtrtrs(
'U',
'T',
'N', bw, bw,
1109 $ a( ofst+bw+1+( odd_size-bw )*llda ), llda-1,
1110 $ af( odd_size*bw+2*mbw2+1 ), bw, info )
1114 CALL dlamov(
'L', bw, bw, af( odd_size*bw+2*mbw2+1+bw-bw ),
1115 $ bw, a( ( ofst+1+odd_size*llda ) ), llda-1 )
1125 CALL dsyrk( uplo,
'T', bw, bw, -one,
1126 $ af( odd_size*bw+2*mbw2+1 ), bw, one,
1127 $ a( ofst+bw+1+odd_size*llda ), llda-1 )
1136 IF( mycol.NE.0 )
THEN
1146 CALL dlatcpy(
'L', prev_tri_size_n, prev_tri_size_m,
1147 $ a( ofst+1 ), llda-1, af( 1 ), odd_size )
1149 IF( info.EQ.0 )
THEN
1151 CALL dtbtrs(
'U',
'T',
'N', odd_size, bw, bw,
1152 $ a( ofst+1 ), llda, af( 1 ), odd_size, info )
1157 CALL dsyrk(
'L',
'T', bw, odd_size, -one, af( 1 ),
1158 $ odd_size, zero, af( 1+( odd_size+2*bw )*bw ),
1165 CALL dgesd2d( ictxt, bw, bw, af( odd_size*bw+2*mbw2+1 ),
1169 IF( mycol.LT.np-1 )
THEN
1181 CALL dlatcpy(
'N', bw, bw, af( odd_size-bw+1 ),
1182 $ odd_size, af( ( odd_size )*bw+1 ), bw )
1184 CALL dtrmm(
'R',
'L',
'N',
'N', bw, bw, -one,
1185 $ a( ( ofst+1+odd_size*llda ) ), llda-1,
1186 $ af( ( odd_size )*bw+1 ), bw )
1199 CALL igamx2d( ictxt,
'A',
' ', 1, 1, info, 1, info, info, -1,
1202 IF( mycol.EQ.0 )
THEN
1203 CALL igebs2d( ictxt,
'A',
' ', 1, 1, info, 1 )
1205 CALL igebr2d( ictxt,
'A',
' ', 1, 1, info, 1, 0, 0 )
1208 IF( info.NE.0 )
THEN
1223 IF( mycol.EQ.npcol-1 )
THEN
1231 IF( ( mod( mycol+1, 2 ).EQ.0 ) .AND. ( mycol.GT.0 ) )
THEN
1233 CALL dgesd2d( ictxt, bw, bw, af( odd_size*bw+1 ), bw, 0,
1241 CALL dlatcpy(
'U', bw, bw, a( ofst+odd_size*llda+1+bw ),
1242 $ llda-1, af( odd_size*bw+mbw2+1 ), bw )
1246 IF( mycol.LT.npcol-1 )
THEN
1248 CALL dgerv2d( ictxt, bw, bw, af( odd_size*bw+2*mbw2+1 ), bw,
1253 CALL daxpy( mbw2, one, af( odd_size*bw+2*mbw2+1 ), 1,
1254 $ af( odd_size*bw+mbw2+1 ), 1 )
1269 IF( mod( ( mycol+1 ) / level_dist, 2 ).NE.0 )
1274 IF( mycol-level_dist.GE.0 )
THEN
1275 CALL dgerv2d( ictxt, bw, bw, work( 1 ), bw, 0,
1276 $ mycol-level_dist )
1278 CALL daxpy( mbw2, one, work( 1 ), 1,
1279 $ af( odd_size*bw+mbw2+1 ), 1 )
1285 IF( mycol+level_dist.LT.npcol-1 )
THEN
1286 CALL dgerv2d( ictxt, bw, bw, work( 1 ), bw, 0,
1287 $ mycol+level_dist )
1289 CALL daxpy( mbw2, one, work( 1 ), 1,
1290 $ af( odd_size*bw+mbw2+1 ), 1 )
1294 level_dist = level_dist*2
1306 CALL dpotrf(
'L', bw, af( odd_size*bw+mbw2+1 ), bw, info )
1308 IF( info.NE.0 )
THEN
1309 info = npcol + mycol
1317 IF( level_dist.EQ.1 )
THEN
1318 comm_proc = mycol + 1
1323 CALL dlamov(
'N', bw, bw, af( odd_size*bw+1 ), bw,
1324 $ af( odd_size*bw+2*mbw2+1 ), bw )
1327 comm_proc = mycol + level_dist / 2
1330 IF( mycol / level_dist.LE.( npcol-1 ) / level_dist-2 )
THEN
1332 CALL dgerv2d( ictxt, bw, bw, af( odd_size*bw+1 ), bw, 0,
1335 IF( info.EQ.0 )
THEN
1341 CALL dtrsm(
'L',
'L',
'N',
'N', bw, bw, one,
1342 $ af( odd_size*bw+mbw2+1 ), bw,
1343 $ af( odd_size*bw+1 ), bw )
1350 CALL dsyrk(
'L',
'T', bw, bw, -one, af( ( odd_size )*bw+1 ),
1351 $ bw, zero, work( 1 ), bw )
1355 CALL dgesd2d( ictxt, bw, bw, work( 1 ), bw, 0,
1356 $ mycol+level_dist )
1366 IF( ( mycol / level_dist.GT.0 ) .AND.
1367 $ ( mycol / level_dist.LE.( npcol-1 ) / level_dist-1 ) )
THEN
1369 IF( level_dist.GT.1 )
THEN
1374 CALL dgerv2d( ictxt, bw, bw, af( odd_size*bw+2*mbw2+1 ),
1375 $ bw, 0, mycol-level_dist / 2 )
1380 IF( info.EQ.0 )
THEN
1384 CALL dtrsm(
'R',
'L',
'T',
'N', bw, bw, one,
1385 $ af( odd_size*bw+mbw2+1 ), bw,
1386 $ af( odd_size*bw+2*mbw2+1 ), bw )
1394 CALL dsyrk(
'L',
'N', bw, bw, -one,
1395 $ af( ( odd_size+2*bw )*bw+1 ), bw, zero,
1400 CALL dgesd2d( ictxt, bw, bw, work( 1 ), bw, 0,
1401 $ mycol-level_dist )
1405 IF( mycol / level_dist.LE.( npcol-1 ) / level_dist-2 )
THEN
1409 IF( ( mod( mycol / ( 2*level_dist ), 2 ) ).EQ.0 )
THEN
1410 comm_proc = mycol + level_dist
1412 comm_proc = mycol - level_dist
1419 CALL dgemm(
'N',
'N', bw, bw, bw, -one,
1420 $ af( odd_size*bw+2*mbw2+1 ), bw,
1421 $ af( odd_size*bw+1 ), bw, zero, work( 1 ),
1426 CALL dgesd2d( ictxt, bw, bw, work( 1 ), bw, 0,
1443 IF( ictxt_save.NE.ictxt_new )
THEN
1444 CALL blacs_gridexit( ictxt_new )
1456 work( 1 ) = work_size_min
1460 CALL igamx2d( ictxt,
'A',
' ', 1, 1, info, 1, info, info, -1, 0,
1463 IF( mycol.EQ.0 )
THEN
1464 CALL igebs2d( ictxt,
'A',
' ', 1, 1, info, 1 )
1466 CALL igebr2d( ictxt,
'A',
' ', 1, 1, info, 1, 0, 0 )