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_, ,
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
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
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
575 PART_OFFSET = NB*( ( JA-1 ) / ( NPCOL*NB ) )
577.LT.
IF( ( MYCOL-CSRC )( JA-PART_OFFSET-1 ) / NB ) THEN
578 PART_OFFSET = PART_OFFSET + NB
581.LT.
IF( MYCOLCSRC ) 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.LT.
IF( MYROW0 ) THEN
632 MY_NUM_COLS = NUMROC( N, PART_SIZE, MYCOL, 0, NPCOL )
636.EQ.
IF( MYCOL0 ) 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.LT.
IF( MYCOLNP-1 ) THEN
649 ODD_SIZE = ODD_SIZE - BW
661 DO 20 I = 1, WORK_SIZE_MIN
667 IF( LSAME( UPLO, 'l
' ) ) THEN
676.GT.
IF( MYCOL0 ) 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.LT.
IF( MYCOLNPCOL-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.LT.
IF( MYCOLNP-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.LT.
IF( MYCOLNP-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.NE.
IF( MYCOL0 ) 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 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.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 )