1 SUBROUTINE pzdttrf( N, DL, D, DU, JA, DESCA, AF, LAF, WORK, LWORK,
9 INTEGER INFO, JA, LAF, LWORK, N
13 COMPLEX*16 AF( * ), D( * ), DL( * ), DU( * ), WORK( * )
356 DOUBLE PRECISION ONE, ZERO
357 parameter( one = 1.0d+0 )
358 parameter( zero = 0.0d+0 )
359 COMPLEX*16 CONE, CZERO
360 parameter( cone = ( 1.0d+0, 0.0d+0 ) )
361 parameter( czero = ( 0.0d+0, 0.0d+0 ) )
363 parameter( int_one = 1 )
364 INTEGER DESCMULT, BIGNUM
365 parameter(descmult = 100, bignum = descmult * descmult)
366 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
367 $ lld_, mb_, m_, nb_, n_, rsrc_
368 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
369 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
370 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
373 INTEGER COMM_PROC, CSRC, FIRST_PROC, I, ICTXT,
374 $ ictxt_new, ictxt_save, idum3, ja_new, laf_min,
375 $ level_dist, llda, mycol, myrow, my_num_cols,
376 $ nb, np, npcol, nprow, np_save, odd_size,
377 $ part_offset, part_size, return_code, store_n_a,
378 $ temp, work_size_min, work_u
381 INTEGER DESCA_1XP( 7 ), PARAM_CHECK( 7, 3 )
384 EXTERNAL blacs_get, blacs_gridexit, blacs_gridinfo,
386 $ zgemm, zgerv2d, zgesd2d, zlamov,
zlatcpy,
387 $ zpbtrf, zpotrf, zsyrk, ztbtrs, ztrmm, ztrrv2d,
388 $ ztrsd2d, ztrsm, ztrtrs
394 EXTERNAL lsame, numroc, zdotc
397 INTRINSIC ichar,
min, mod
410 temp = desca( dtype_ )
411 IF( temp .EQ. 502 )
THEN
413 desca( dtype_ ) = 501
418 desca( dtype_ ) = temp
420 IF( return_code .NE. 0)
THEN
421 info = -( 6*100 + 2 )
426 ictxt = desca_1xp( 2 )
427 csrc = desca_1xp( 5 )
429 llda = desca_1xp( 6 )
430 store_n_a = desca_1xp( 3 )
435 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
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 )
458 IF( nprow .NE. 1 )
THEN
462 IF( n .GT. np*nb-mod( ja-1, nb ))
THEN
465 $
'PZDTTRF, D&C alg.: only 1 block per proc',
470 IF((ja+n-1.GT.nb) .AND. ( nb.LT.2*int_one ))
THEN
473 $
'PZDTTRF, D&C alg.: NB too small',
481 laf_min = (12*npcol+3*nb)
483 IF( laf .LT. laf_min )
THEN
488 $
'PZDTTRF: auxiliary storage error ',
495 work_size_min = 8*npcol
497 work( 1 ) = work_size_min
499 IF( lwork .LT. work_size_min )
THEN
500 IF( lwork .NE. -1 )
THEN
503 $
'PZDTTRF: worksize error ',
511 param_check( 7, 1 ) = desca(5)
512 param_check( 6, 1 ) = desca(4)
513 param_check( 5, 1 ) = desca(3)
514 param_check( 4, 1 ) = desca(1)
515 param_check( 3, 1 ) = ja
516 param_check( 2, 1 ) = n
517 param_check( 1, 1 ) = idum3
519 param_check( 7, 2 ) = 605
520 param_check( 6, 2 ) = 604
521 param_check( 5, 2 ) = 603
522 param_check( 4, 2 ) = 601
523 param_check( 3, 2 ) = 5
524 param_check( 2, 2 ) = 1
525 param_check( 1, 2 ) = 10
533 ELSE IF( info.LT.-descmult )
THEN
536 info = -info * descmult
541 CALL globchk( ictxt, 7, param_check, 7,
542 $ param_check( 1, 3 ), info )
547 IF( info.EQ.bignum )
THEN
549 ELSE IF( mod( info, descmult ) .EQ. 0 )
THEN
550 info = -info / descmult
556 CALL pxerbla( ictxt,
'PZDTTRF', -info )
569 part_offset = nb*( (ja-1)/(npcol*nb) )
571 IF ( (mycol-csrc) .LT. (ja-part_offset-1)/nb )
THEN
572 part_offset = part_offset + nb
575 IF ( mycol .LT. csrc )
THEN
576 part_offset = part_offset - nb
585 first_proc = mod( ( ja-1 )/nb+csrc, npcol )
589 ja_new = mod( ja-1, nb ) + 1
594 np = ( ja_new+n-2 )/nb + 1
598 CALL reshape( ictxt, int_one, ictxt_new, int_one,
599 $ first_proc, int_one, np )
605 desca_1xp( 2 ) = ictxt_new
609 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
613 IF( myrow .LT. 0 )
THEN
626 my_num_cols = numroc( n, part_size, mycol, 0, npcol )
630 IF ( mycol .EQ. 0 )
THEN
631 part_offset = part_offset+mod( ja_new-1, part_size )
632 my_num_cols = my_num_cols - mod(ja_new-1, part_size )
637 odd_size = my_num_cols
638 IF ( mycol .LT. np-1 )
THEN
639 odd_size = odd_size - int_one
644 work_u = int_one*odd_size + 3
661 IF ( mycol .LT. np-1 )
THEN
667 CALL ztrsd2d( ictxt,
'U',
'N', 1, 1,
668 $ du( part_offset+odd_size+1 ), llda-1, 0,
676 CALL zdttrf( odd_size, dl( part_offset+2 ), d( part_offset+1 ),
677 $ du( part_offset+1 ), info )
685 IF ( mycol .LT. np-1 )
THEN
694 dl( part_offset+odd_size+1 ) =
695 $ ( dl( part_offset+odd_size+1 ) )
696 $ / ( d( part_offset+odd_size ) )
703 d( part_offset+odd_size+1 ) = d( part_offset+odd_size+1 )-
704 $ dl( part_offset+odd_size+1 )*du( part_offset+odd_size )
713 IF ( mycol .NE. 0 )
THEN
717 af( work_u+1 ) = ( dl( part_offset+1 ) )
723 CALL zdttrsv(
'L',
'N', odd_size, int_one,
724 $ dl( part_offset+2 ), d( part_offset+1 ),
725 $ du( part_offset+1 ), af( work_u+1 ), odd_size,
731 CALL ztrrv2d( ictxt,
'U',
'N', 1, 1, af( 1 ), odd_size, 0,
734 af( 1 ) = dconjg( af( 1 ) )
736 CALL zdttrsv(
'U',
'C', odd_size, int_one,
737 $ dl( part_offset+2 ), d( part_offset+1 ),
738 $ du( part_offset+1 ),
739 $ af( 1 ), odd_size, info )
744 af( odd_size+3 ) = -cone *
745 $ zdotc( odd_size, af( 1 ), 1, af( work_u+1 ), 1 )
751 CALL zgesd2d( ictxt, int_one, int_one, af( odd_size+3 ),
752 $ int_one, 0, mycol-1 )
755 IF ( mycol .LT. np-1 )
THEN
761 af( odd_size+1 ) = -cone
762 $ * dconjg( dl( part_offset+odd_size+1 )
763 $ * af( work_u+odd_size ) )
766 af(work_u+(odd_size)+1 ) = -cone
767 $ * du( part_offset+odd_size )
768 $ * dconjg( af( odd_size ) )
781 CALL igamx2d( ictxt,
'A',
' ', 1, 1, info, 1, info, info,
784 IF( mycol.EQ.0 )
THEN
785 CALL igebs2d( ictxt,
'A',
' ', 1, 1, info, 1 )
787 CALL igebr2d( ictxt,
'A',
' ', 1, 1, info, 1, 0, 0 )
790 IF ( info.NE.0 )
THEN
805 IF( mycol .EQ. npcol-1 )
THEN
813 IF( (mod( mycol+1, 2 ) .EQ. 0) .AND. ( mycol .GT. 0 ) )
THEN
815 CALL zgesd2d( ictxt, int_one, int_one,
817 $ int_one, 0, mycol-1 )
819 CALL zgesd2d( ictxt, int_one, int_one,
820 $ af( work_u+odd_size+1 ),
821 $ int_one, 0, mycol-1 )
829 $ dcmplx( d( part_offset+odd_size+1 ) )
833 IF( mycol.LT. npcol-1 )
THEN
835 CALL zgerv2d( ictxt, int_one, int_one,
836 $ af( odd_size+2+1 ),
842 af( odd_size+2 ) = af( odd_size+2 )+af( odd_size+3 )
857 IF( mod( (mycol+1)/level_dist, 2) .NE. 0 )
GOTO 11
861 IF( mycol-level_dist .GE. 0 )
THEN
862 CALL zgerv2d( ictxt, int_one, int_one, work( 1 ),
863 $ int_one, 0, mycol-level_dist )
865 af( odd_size+2 ) = af( odd_size+2 )+work( 1 )
871 IF( mycol+level_dist .LT. npcol-1 )
THEN
872 CALL zgerv2d( ictxt, int_one, int_one, work( 1 ),
873 $ int_one, 0, mycol+level_dist )
875 af( odd_size+2 ) = af( odd_size+2 )+work( 1 )
879 level_dist = level_dist*2
888 IF( af( odd_size+2 ) .EQ. czero )
THEN
897 IF( level_dist .EQ. 1 )
THEN
898 comm_proc = mycol + 1
903 af( work_u+odd_size+3 ) = af( odd_size+1 )
905 af( odd_size+3 ) = af( work_u+odd_size+1 )
908 comm_proc = mycol + level_dist/2
911 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )
THEN
913 CALL zgerv2d( ictxt, int_one, int_one,
915 $ int_one, 0, comm_proc )
917 CALL zgerv2d( ictxt, int_one, int_one,
918 $ af( work_u+odd_size+1 ),
919 $ int_one, 0, comm_proc )
921 IF( info .EQ. 0 )
THEN
927 af( odd_size+1 ) = af( odd_size+1 )
928 $ / dconjg( af( odd_size+2 ) )
935 work( 1 ) = -one*dconjg( af( odd_size+1 ) )*
936 $ af( work_u+(odd_size)+1 )
940 CALL zgesd2d( ictxt, int_one, int_one, work( 1 ), int_one,
941 $ 0, mycol+level_dist )
951 IF( (mycol/level_dist .GT. 0 ).AND.
952 $ ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) )
THEN
954 IF( level_dist .GT. 1)
THEN
959 CALL zgerv2d( ictxt, int_one, int_one,
960 $ af( work_u+odd_size+2+1 ),
961 $ int_one, 0, mycol-level_dist/2 )
966 CALL zgerv2d( ictxt, int_one, int_one,
967 $ af( odd_size+2+1 ),
968 $ int_one, 0, mycol-level_dist/2 )
977 af( odd_size+3 ) = af( odd_size+3 )
978 $ / ( af( odd_size+2 ) )
987 work( 1 ) = -one*af( odd_size+3 )
988 $ *dconjg( af( work_u+odd_size+3 ) )
992 CALL zgesd2d( ictxt, int_one, int_one, work( 1 ), int_one,
993 $ 0, mycol-level_dist )
997 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )
THEN
1001 IF( ( mod( mycol/( 2*level_dist ),2 )) .EQ.0 )
THEN
1002 comm_proc = mycol + level_dist
1004 comm_proc = mycol - level_dist
1011 work( 1 ) = -one*af( work_u+odd_size+3 )
1012 $ * af( odd_size+1 )
1016 CALL zgesd2d( ictxt, int_one, int_one, work( 1 ), int_one,
1019 work( 1 ) = -one*af( odd_size+3 )
1020 $ * af( work_u+odd_size+1 )
1024 CALL zgesd2d( ictxt, int_one, int_one, work( 1 ), int_one,
1040 IF( ictxt_save .NE. ictxt_new )
THEN
1041 CALL blacs_gridexit( ictxt_new )
1053 work( 1 ) = work_size_min
1057 CALL igamx2d( ictxt,
'A',
' ', 1, 1, info, 1, info, info,
1060 IF( mycol.EQ.0 )
THEN
1061 CALL igebs2d( ictxt,
'A',
' ', 1, 1, info, 1 )
1063 CALL igebr2d( ictxt,
'A',
' ', 1, 1, info, 1, 0, 0 )