      subroutine eigen_dcx(n, d, e, lde, z, ldz, INFO, RET)
!$    use OMP_LIB
      use MPI
      use eigen_devel
      use eigen_blacs, only : eigen_get_blacs_context
      use eigen_dc
      implicit NONE

      integer, intent(in)           :: n, lde, ldz
      real(8), intent(inout)        :: d(1:n), e(1:2*lde)
      real(8), intent(out)          :: z(1:ldz,*)
      integer, intent(out)          :: info
      real(8), intent(out)          :: ret

! Parameters BLACS array descritor(the position of entry tags), etc
      INTEGER, PARAMETER            :: BLOCK_CYCLIC_2D = 1
      INTEGER, PARAMETER            :: DLEN_  = 9
      INTEGER, PARAMETER            :: DTYPE_ = 1
      INTEGER, PARAMETER            :: CTXT_  = 2
      INTEGER, PARAMETER            :: M_     = 3
      INTEGER, PARAMETER            :: N_     = 4
      INTEGER, PARAMETER            :: MB_    = 5
      INTEGER, PARAMETER            :: NB_    = 6
      INTEGER, PARAMETER            :: RSRC_  = 7
      INTEGER, PARAMETER            :: CSRC_  = 8
      INTEGER, PARAMETER            :: LLD_   = 9

      integer                       :: DESCZ( DLEN_ )
      integer                       :: DESCW( DLEN_ )
 
      integer                       :: i,j,nx,istat,NB,lddz,lddw
      integer                       :: NP, NQ, NPCOL, NPROW
      integer                       :: NPROCS, IAM, MYCOL, MYROW
      integer                       :: ICTXT

      integer                       :: world_size, my_rank, ierr
      integer                       :: TRILWMIN, LWORK, LIWORK
 
      real(8), pointer              :: work(:)
      integer, pointer              :: iwork(:)

      logical, parameter            :: USE_MY_REDIST = .TRUE.

#if defined(__INTEL_COMPILER)
      integer                       :: MKL_MODE
      integer, external             :: MKL_GET_DYNAMIC
#endif
      integer, external             :: NUMROC

#if TIMER_PRINT
      real(8)  :: d1,d2
#endif

 
      flops = 0D0
      dgemm_time = 0D0
 
      call eigen_timer_reset( )

#if TIMER_PRINT
      d1 = eigen_get_wtime()
#endif

      NPROCS = TRD_nnod
      IAM    = TRD_inod-1

      NPROW = x_nnod
      NPCOL = y_nnod

      ICTXT = eigen_get_blacs_context( )
!      ICTXT = BLACS_ICONTXT_FOR_EIGEN

!      CALL BLACS_GRIDINIT( ICTXT, 'Column-major', NPROW, NPCOL )

      MYROW = x_inod-1
      MYCOL = y_inod-1

!      call BLACS_GRIDINFO( ICTXT, NPROW, NPCOL, MYROW, MYCOL )


! BLACS array registration
      NB = 64
      NB = MIN(NB, N)

      NP = NUMROC( n, NB, MYROW, 0, NPROW )
      NQ = NUMROC( n, NB, MYCOL, 0, NPCOL )
      lddz = (n-1)/NPROW+1
      lddz = ((lddz-1)/NB+1)*NB
      lddw = (n-1)/NPCOL+1
      lddw = ((lddw-1)/NB+1)*NB
!
      call DESCINIT( DESCZ, n, n, NB, NB, 0, 0, ICTXT, lddz, INFO )

! preparing working arrays
      nx     = (N-1)/NPCOL+1
      LWORK  = MAX(1+6*N+2*NP*(NQ+MAX(NQ,NB)), lddz*lddw, ldz*nx)
      LIWORK = 2+7*n+8*NPCOL
      allocate(work(lwork), iwork(liwork), stat=istat)
      if(istat.ne.0) then
           print*,"Memory exhausted"
           call flush(6)
           call MPI_Abort( MPI_COMM_WORLD, 1, ierr )
      end if

! Somehow, Z must be nullified (Originally next loop is not required.)
!$OMP PARALLEL DO
!OCL XFILL
      do i=1, lddz*lddw
         z(i,1) = 0.0D+00
      enddo
!$OMP END PARALLEL DO
#if TIMER_PRINT
      d2 = eigen_get_wtime()
      IF(IAM==0)print*,"before PDSTEDC",d2-d1
#endif

      call DLAED6_INIT()

#if defined(__INTEL_COMPILER)
      MKL_MODE = MKL_GET_DYNAMIC()
      call MKL_SET_DYNAMIC(0)
#endif

#if TIMER_PRINT
      d1 = eigen_get_wtime ()
#endif
      CALL MY_PDSXEDC('I',2, n, d(1), e(1), lde, z(1,1), 1, 1, DESCZ,
     $               WORK(1), LWORK, IWORK(1), LIWORK, INFO)
#if TIMER_PRINT
      d2 = eigen_get_wtime()
#endif

#if defined(__INTEL_COMPILER)
      call MKL_SET_DYNAMIC(MKL_MODE)
#endif

#if TIMER_PRINT
      IF(IAM==0)print*,"PDSTEDC",d2-d1
#endif

      IF ( NB == 1 ) THEN
         do i=nx,1,-1
            work(1:lddz)=z(1+(i-1)*lddz:lddz+(i-1)*lddz,1)
            z(1:lddz,i)=work(1:lddz)
         enddo
         do i=1,nx
            z(lddz+1:ldz,i)=0.0D0
         enddo
         call bcast_dbl( d(1), n, 1, TRD_COMM_WORLD )
      ELSE

      IF( USE_MY_REDIST )THEN
#if TIMER_PRINT
         d1 = eigen_get_wtime()
#endif
         call dc_redist1( n, NB, z, work, lddz, iwork, liwork/2 )
#if TIMER_PRINT
         d2 = eigen_get_wtime()
         IF(IAM==0)print*,"MY-REDIST1",d2-d1
         d1 = eigen_get_wtime()
#endif
         call dc_redist2( n, NB, work, lddz, z, ldz, iwork, liwork/2 )
#if TIMER_PRINT
         d2 = eigen_get_wtime()
         IF(IAM==0)print*,"MY-REDIST2",d2-d1
#endif
      ELSE
#if TIMER_PRINT
         d1 = eigen_get_wtime()
#endif
         call DESCINIT( DESCW, n, n, 1, 1, 0, 0, ICTXT, ldz, INFO )
         call PDGEMR2D( n, n, z, 1, 1, DESCZ, work, 1, 1, DESCW, ICTXT )
#if TIMER_PRINT
         d2 = eigen_get_wtime()
         IF(IAM==0)print*,"PDGEMR2D",d2-d1
#endif
      END IF ! if ( USE_MY_REDIST ) .. else ..

#if TIMER_PRINT
         d1 = eigen_get_wtime()
#endif
!$OMP PARALLEL PRIVATE(i)
!$    IF ( omp_get_thread_num()==0 ) THEN
         call bcast_dbl( d(1), n, 1, TRD_COMM_WORLD )
!$    ENDIF
!$    IF ( omp_get_num_threads()==1 .OR.
!$   $     omp_get_thread_num()==1 ) THEN
      IF( .NOT.USE_MY_REDIST )THEN
         do i=1,ldz*nx
            z(i,1)=work(i)
         enddo
      ENDIF
!$    ENDIF
!$OMP END PARALLEL
#if TIMER_PRINT
         d2 = eigen_get_wtime()
         IF(IAM==0)print*,"RERE1",d2-d1
#endif
      END IF ! if ( NB == 1 ) .. else ..

      call eigen_timer_print( )

! freeing working arrays
      deallocate(work)
      deallocate(iwork)

 
! BLACS/PBLAS/SCALAPACK finalize
!      call BLACS_GRIDEXIT( ICTXT )

      call reduce_dbl( flops, ret, 1, 1, TRD_COMM_WORLD )

#if TIMER_PRINT
      IF(IAM==0)THEN
         print*,"PDGEMM", dgemm_time, 
     &          1D-9*flops/dgemm_time,"GFLOPS"
      ENDIF
#endif

      ret = flops

      return
      end subroutine  eigen_dcx

