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_, , 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 )
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 )
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
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.LT.
IF( MYCOLNP-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.EQ.
IF( MYCOL0 ) THEN
827 CALL IGEBS2D( ICTXT, 'a
', ' ', 1, 1, INFO, 1 )
829 CALL IGEBR2D( ICTXT, 'a
', ' ', 1, 1, INFO, 1, 0, 0 )
847.EQ.
IF( MYCOLNPCOL-1 ) THEN
855.EQ..AND..GT.
IF( ( MOD( MYCOL+1, 2 )0 ) ( MYCOL0 ) ) 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.LT.
IF( MYCOLNPCOL-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.NE.
IF( MOD( ( MYCOL+1 ) / LEVEL_DIST, 2 )0 )
898.GE.
IF( MYCOL-LEVEL_DIST0 ) 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.LT.
IF( MYCOL+LEVEL_DISTNPCOL-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.EQ.
IF( LEVEL_DIST1 ) 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.LE.
IF( MYCOL / LEVEL_DIST( 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.GT..AND.
IF( ( MYCOL / LEVEL_DIST0 )
991.LE.
$ ( MYCOL / LEVEL_DIST( NPCOL-1 ) / LEVEL_DIST-1 ) ) THEN
993.GT.
IF( LEVEL_DIST1 ) THEN
998 CALL DGERV2D( ICTXT, BW, BW, AF( ODD_SIZE*BW+2*MBW2+1 ),
999 $ BW, 0, MYCOL-LEVEL_DIST / 2 )
1004.EQ.
IF( INFO0 ) 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.LE.
IF( MYCOL / LEVEL_DIST( NPCOL-1 ) / LEVEL_DIST-2 ) THEN
1033.EQ.
IF( ( MOD( MYCOL / ( 2*LEVEL_DIST ), 2 ) )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.GT.
IF( MYCOL0 ) 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.LT.
IF( MYCOLNPCOL-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.NE.
IF( INFO0 ) THEN
1097.LT.
IF( MYCOLNP-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.NE.
IF( MYCOL0 ) THEN
1146 CALL DLATCPY( 'l
', PREV_TRI_SIZE_N, PREV_TRI_SIZE_M,
1147 $ A( OFST+1 ), LLDA-1, AF( 1 ), ODD_SIZE )
1149.EQ.
IF( INFO0 ) 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.LT.
IF( MYCOLNP-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.EQ.
IF( MYCOL0 ) THEN
1203 CALL IGEBS2D( ICTXT, 'a
', ' ', 1, 1, INFO, 1 )
1205 CALL IGEBR2D( ICTXT, 'a
', ' ', 1, 1, INFO, 1, 0, 0 )
1208.NE.
IF( INFO0 ) THEN
1223.EQ.
IF( MYCOLNPCOL-1 ) THEN
1231.EQ..AND..GT.
IF( ( MOD( MYCOL+1, 2 )0 ) ( MYCOL0 ) ) 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.LT.
IF( MYCOLNPCOL-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.NE.
IF( MOD( ( MYCOL+1 ) / LEVEL_DIST, 2 )0 )
1274.GE.
IF( MYCOL-LEVEL_DIST0 ) 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.LT.
IF( MYCOL+LEVEL_DISTNPCOL-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.NE.
IF( INFO0 ) THEN
1309 INFO = NPCOL + MYCOL
1317.EQ.
IF( LEVEL_DIST1 ) 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.LE.
IF( MYCOL / LEVEL_DIST( NPCOL-1 ) / LEVEL_DIST-2 ) THEN
1332 CALL DGERV2D( ICTXT, BW, BW, AF( ODD_SIZE*BW+1 ), BW, 0,
1335.EQ.
IF( INFO0 ) 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.GT..AND.
IF( ( MYCOL / LEVEL_DIST0 )
1367.LE.
$ ( MYCOL / LEVEL_DIST( NPCOL-1 ) / LEVEL_DIST-1 ) ) THEN
1369.GT.
IF( LEVEL_DIST1 ) THEN
1374 CALL DGERV2D( ICTXT, BW, BW, AF( ODD_SIZE*BW+2*MBW2+1 ),
1375 $ BW, 0, MYCOL-LEVEL_DIST / 2 )
1380.EQ.
IF( INFO0 ) 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.LE.
IF( MYCOL / LEVEL_DIST( NPCOL-1 ) / LEVEL_DIST-2 ) THEN
1409.EQ.
IF( ( MOD( MYCOL / ( 2*LEVEL_DIST ), 2 ) )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.NE.
IF( ICTXT_SAVEICTXT_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.EQ.
IF( MYCOL0 ) THEN
1464 CALL IGEBS2D( ICTXT, 'a
', ' ', 1, 1, INFO, 1 )
1466 CALL IGEBR2D( ICTXT, 'a
', ' ', 1, 1, INFO, 1, 0, 0 )