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,
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 )
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
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,
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*
765 CALL igamx2d( ictxt, 'a
', ' ', 1, 1, INFO, 1, INFO, INFO, -1, 0,
768.EQ.
IF( MYCOL0 ) THEN
769 CALL IGEBS2D( ICTXT, 'a
', ' ', 1, 1, INFO, 1 )
771 CALL IGEBR2D( ICTXT, 'a
', ' ', 1, 1, INFO, 1, 0, 0 )
789.EQ.
IF( MYCOLNPCOL-1 ) THEN
797.EQ..AND..GT.
IF( ( MOD( MYCOL+1, 2 )0 ) ( MYCOL0 ) ) 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.LT.
IF( MYCOLNPCOL-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.NE.
IF( MOD( ( MYCOL+1 ) / LEVEL_DIST, 2 )0 )
841.GE.
IF( MYCOL-LEVEL_DIST0 ) 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.LT.
IF( MYCOL+LEVEL_DISTNPCOL-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.EQ.
IF( AF( ODD_SIZE+2 )ZERO ) THEN
877.EQ.
IF( LEVEL_DIST1 ) 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.LE.
IF( MYCOL / LEVEL_DIST( 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.GT..AND.
IF( ( MYCOL / LEVEL_DIST0 )
929.LE.
$ ( MYCOL / LEVEL_DIST( NPCOL-1 ) / LEVEL_DIST-1 ) ) THEN
931.GT.
IF( LEVEL_DIST1 ) 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.LE.
IF( MYCOL / LEVEL_DIST( NPCOL-1 ) / LEVEL_DIST-2 ) THEN
975.EQ.
IF( ( MOD( MYCOL / ( 2*LEVEL_DIST ), 2 ) )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.NE.
IF( ICTXT_SAVEICTXT_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.EQ.
IF( MYCOL0 ) THEN
1033 CALL IGEBS2D( ICTXT, 'a
', ' ', 1, 1, INFO, 1 )
1035 CALL IGEBR2D( ICTXT, 'a',
' ', 1, 1, info, 1, 0, 0 )