1 SUBROUTINE psdttrf( N, DL, D, DU, JA, DESCA, AF, LAF, WORK, LWORK,
10 INTEGER INFO, JA, LAF, LWORK, N
14 REAL AF( * ), D( * ), DL( * ), DU( * ), WORK( * )
356 parameter( one = 1.0e+0 )
358 parameter( zero = 0.0e+0 )
360 parameter( int_one = 1 )
361 INTEGER DESCMULT, BIGNUM
362 parameter( descmult = 100, bignum = descmult*descmult )
363 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
364 $ lld_, mb_, m_, nb_, n_, rsrc_
365 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
366 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
367 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
370 INTEGER COMM_PROC, CSRC, FIRST_PROC, I, ICTXT,
371 $ ictxt_new, ictxt_save, idum3, ja_new, laf_min,
372 $ level_dist, llda, mycol, myrow, my_num_cols,
373 $ nb, np, npcol, nprow, np_save, odd_size,
374 $ part_offset, part_size, return_code, store_n_a,
375 $ temp, work_size_min, work_u
378 INTEGER DESCA_1XP( 7 ), PARAM_CHECK( 7, 3 )
389 EXTERNAL numroc, sdot
405 temp = desca( dtype_ )
406 IF( temp.EQ.502 )
THEN
408 desca( dtype_ ) = 501
413 desca( dtype_ ) = temp
415 IF( return_code.NE.0 )
THEN
421 ictxt = desca_1xp( 2 )
422 csrc = desca_1xp( 5 )
424 llda = desca_1xp( 6 )
425 store_n_a = desca_1xp( 3 )
430 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
435 IF( lwork.LT.-1 )
THEN
437 ELSE IF( lwork.EQ.-1 )
THEN
447 IF( n+ja-1.GT.store_n_a )
THEN
453 IF( nprow.NE.1 )
THEN
457 IF( n.GT.np*nb-mod( ja-1, nb ) )
THEN
459 CALL pxerbla( ictxt,
'PSDTTRF, D&C alg.: only 1 block per proc'
464 IF( ( ja+n-1.GT.nb ) .AND. ( nb.LT.2*int_one ) )
THEN
466 CALL pxerbla( ictxt,
'PSDTTRF, D&C alg.: NB too small', -info )
473 laf_min = ( 12*npcol+3*nb )
475 IF( laf.LT.laf_min )
THEN
479 CALL pxerbla( ictxt,
'PSDTTRF: auxiliary storage error ',
486 work_size_min = 8*npcol
488 work( 1 ) = work_size_min
490 IF( lwork.LT.work_size_min )
THEN
491 IF( lwork.NE.-1 )
THEN
493 CALL pxerbla( ictxt,
'PSDTTRF: worksize error ', -info )
500 param_check( 7, 1 ) = desca( 5 )
501 param_check( 6, 1 ) = desca( 4 )
502 param_check( 5, 1 ) = desca( 3 )
503 param_check( 4, 1 ) = desca( 1 )
504 param_check( 3, 1 ) = ja
505 param_check( 2, 1 ) = n
506 param_check( 1, 1 ) = idum3
508 param_check( 7, 2 ) = 605
509 param_check( 6, 2 ) = 604
510 param_check( 5, 2 ) = 603
511 param_check( 4, 2 ) = 601
512 param_check( 3, 2 ) = 5
513 param_check( 2, 2 ) = 1
514 param_check( 1, 2 ) = 10
522 ELSE IF( info.LT.-descmult )
THEN
525 info = -info*descmult
530 CALL globchk( ictxt, 7, param_check, 7, param_check( 1, 3 ),
536 IF( info.EQ.bignum )
THEN
538 ELSE IF( mod( info, descmult ).EQ.0 )
THEN
539 info = -info / descmult
545 CALL pxerbla( ictxt,
'PSDTTRF', -info )
558 part_offset = nb*( ( ja-1 ) / ( npcol*nb ) )
560 IF( ( mycol-csrc ).LT.( ja-part_offset-1 ) / nb )
THEN
561 part_offset = part_offset + nb
564 IF( mycol.LT.csrc )
THEN
565 part_offset = part_offset - nb
574 first_proc = mod( ( ja-1 ) / nb+csrc, npcol )
578 ja_new = mod( ja-1, nb ) + 1
583 np = ( ja_new+n-2 ) / nb + 1
587 CALL reshape( ictxt, int_one, ictxt_new, int_one, first_proc,
594 desca_1xp( 2 ) = ictxt_new
598 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
602 IF( myrow.LT.0 )
THEN
615 my_num_cols = numroc( n, part_size, mycol, 0, npcol )
619 IF( mycol.EQ.0 )
THEN
620 part_offset = part_offset + mod( ja_new-1, part_size )
621 my_num_cols = my_num_cols - mod( ja_new-1, part_size )
626 odd_size = my_num_cols
627 IF( mycol.LT.np-1 )
THEN
628 odd_size = odd_size - int_one
633 work_u = int_one*odd_size + 3
650 IF( mycol.LT.np-1 )
THEN
656 CALL strsd2d( ictxt,
'U',
'N', 1, 1,
657 $ du( part_offset+odd_size+1 ), llda-1, 0,
665 CALL sdttrf( odd_size, dl( part_offset+2 ), d( part_offset+1 ),
666 $ du( part_offset+1 ), info )
674 IF( mycol.LT.np-1 )
THEN
683 dl( part_offset+odd_size+1 ) = ( dl( part_offset+odd_size+1 ) )
684 $ / ( d( part_offset+odd_size ) )
691 d( part_offset+odd_size+1 ) = d( part_offset+odd_size+1 ) -
692 $ dl( part_offset+odd_size+1 )*
693 $ du( part_offset+odd_size )
702 IF( mycol.NE.0 )
THEN
706 af( work_u+1 ) = ( dl( part_offset+1 ) )
712 CALL sdttrsv(
'L',
'N', odd_size, int_one,
713 $ dl( part_offset+2 ), d( part_offset+1 ),
714 $ du( part_offset+1 ), af( work_u+1 ), odd_size,
720 CALL strrv2d( ictxt,
'U',
'N', 1, 1, af( 1 ), odd_size, 0,
723 CALL sdttrsv(
'U',
'T', odd_size, int_one,
724 $ dl( part_offset+2 ), d( part_offset+1 ),
725 $ du( part_offset+1 ), af( 1 ), odd_size, info )
730 af( odd_size+3 ) = -one*sdot( odd_size, af( 1 ), 1,
731 $ af( work_u+1 ), 1 )
737 CALL sgesd2d( ictxt, int_one, int_one, af( odd_size+3 ),
738 $ int_one, 0, mycol-1 )
741 IF( mycol.LT.np-1 )
THEN
747 af( odd_size+1 ) = -one*( dl( part_offset+odd_size+1 )*
748 $ af( work_u+odd_size ) )
751 af( work_u+( odd_size )+1 ) = -one*
752 $ du( part_offset+odd_size )*( af( odd_size ) )
765 CALL igamx2d( ictxt,
'A',
' ', 1, 1, info, 1, info, info, -1, 0,
768 IF( mycol.EQ.0 )
THEN
769 CALL igebs2d( ictxt,
'A',
' ', 1, 1, info, 1 )
771 CALL igebr2d( ictxt,
'A',
' ', 1, 1, info, 1, 0, 0 )
789 IF( mycol.EQ.npcol-1 )
THEN
797 IF( ( mod( mycol+1, 2 ).EQ.0 ) .AND. ( mycol.GT.0 ) )
THEN
799 CALL sgesd2d( ictxt, int_one, int_one, af( odd_size+1 ),
800 $ int_one, 0, mycol-1 )
802 CALL sgesd2d( ictxt, int_one, int_one, af( work_u+odd_size+1 ),
803 $ int_one, 0, mycol-1 )
810 af( odd_size+2 ) = real( d( part_offset+odd_size+1 ) )
814 IF( mycol.LT.npcol-1 )
THEN
816 CALL sgerv2d( ictxt, int_one, int_one, af( odd_size+2+1 ),
817 $ int_one, 0, mycol+1 )
821 af( odd_size+2 ) = af( odd_size+2 ) + af( odd_size+3 )
836 IF( mod( ( mycol+1 ) / level_dist, 2 ).NE.0 )
841 IF( mycol-level_dist.GE.0 )
THEN
842 CALL sgerv2d( ictxt, int_one, int_one, work( 1 ), int_one, 0,
845 af( odd_size+2 ) = af( odd_size+2 ) + work( 1 )
851 IF( mycol+level_dist.LT.npcol-1 )
THEN
852 CALL sgerv2d( ictxt, int_one, int_one, work( 1 ), int_one, 0,
855 af( odd_size+2 ) = af( odd_size+2 ) + work( 1 )
859 level_dist = level_dist*2
868 IF( af( odd_size+2 ).EQ.zero )
THEN
877 IF( level_dist.EQ.1 )
THEN
878 comm_proc = mycol + 1
883 af( work_u+odd_size+3 ) = af( odd_size+1 )
885 af( odd_size+3 ) = af( work_u+odd_size+1 )
888 comm_proc = mycol + level_dist / 2
891 IF( mycol / level_dist.LE.( npcol-1 ) / level_dist-2 )
THEN
893 CALL sgerv2d( ictxt, int_one, int_one, af( odd_size+1 ),
894 $ int_one, 0, comm_proc )
896 CALL sgerv2d( ictxt, int_one, int_one, af( work_u+odd_size+1 ),
897 $ int_one, 0, comm_proc )
905 af( odd_size+1 ) = af( odd_size+1 ) / ( af( odd_size+2 ) )
912 work( 1 ) = -one*( af( odd_size+1 ) )*
913 $ af( work_u+( odd_size )+1 )
917 CALL sgesd2d( ictxt, int_one, int_one, work( 1 ), int_one, 0,
928 IF( ( mycol / level_dist.GT.0 ) .AND.
929 $ ( mycol / level_dist.LE.( npcol-1 ) / level_dist-1 ) )
THEN
931 IF( level_dist.GT.1 )
THEN
936 CALL sgerv2d( ictxt, int_one, int_one,
937 $ af( work_u+odd_size+2+1 ), int_one, 0,
938 $ mycol-level_dist / 2 )
943 CALL sgerv2d( ictxt, int_one, int_one, af( odd_size+2+1 ),
944 $ int_one, 0, mycol-level_dist / 2 )
953 af( odd_size+3 ) = af( odd_size+3 ) / ( af( odd_size+2 ) )
962 work( 1 ) = -one*af( odd_size+3 )*( af( work_u+odd_size+3 ) )
966 CALL sgesd2d( ictxt, int_one, int_one, work( 1 ), int_one, 0,
971 IF( mycol / level_dist.LE.( npcol-1 ) / level_dist-2 )
THEN
975 IF( ( mod( mycol / ( 2*level_dist ), 2 ) ).EQ.0 )
THEN
976 comm_proc = mycol + level_dist
978 comm_proc = mycol - level_dist
985 work( 1 ) = -one*af( work_u+odd_size+3 )*af( odd_size+1 )
989 CALL sgesd2d( ictxt, int_one, int_one, work( 1 ), int_one,
992 work( 1 ) = -one*af( odd_size+3 )*af( work_u+odd_size+1 )
996 CALL sgesd2d( ictxt, int_one, int_one, work( 1 ), int_one,
1012 IF( ictxt_save.NE.ictxt_new )
THEN
1013 CALL blacs_gridexit( ictxt_new )
1025 work( 1 ) = work_size_min
1029 CALL igamx2d( ictxt,
'A',
' ', 1, 1, info, 1, info, info, -1, 0,
1032 IF( mycol.EQ.0 )
THEN
1033 CALL igebs2d( ictxt,
'A',
' ', 1, 1, info, 1 )
1035 CALL igebr2d( ictxt,
'A',
' ', 1, 1, info, 1, 0, 0 )